Messagelib

attachmentstrategy.cpp
1 /* -*- c++ -*-
2  attachmentstrategy.cpp
3 
4  This file is part of KMail, the KDE mail client.
5  SPDX-FileCopyrightText: 2003 Marc Mutz <[email protected]>
6  SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected]
7  SPDX-FileCopyrightText: 2009 Andras Mantia <[email protected]>
8 
9  SPDX-License-Identifier: GPL-2.0-or-later
10 */
11 
12 #include "attachmentstrategy.h"
13 
14 #include <MimeTreeParser/NodeHelper>
15 #include <MimeTreeParser/Util>
16 
17 #include <KMime/Content>
18 
19 #include <QIcon>
20 
21 #include "messageviewer_debug.h"
22 
23 using namespace MessageViewer;
24 
25 static AttachmentStrategy::Display smartDisplay(KMime::Content *node)
26 {
27  const auto cd = node->contentDisposition(false);
28  if (cd) {
29  if (cd->disposition() == KMime::Headers::CDinline) {
30  // explicit "inline" disposition:
31  return AttachmentStrategy::Inline;
32  }
33  if (cd->disposition() == KMime::Headers::CDattachment) {
34  // explicit "attachment" disposition:
35  return AttachmentStrategy::AsIcon;
36  }
37  }
38 
39  const auto ct = node->contentType(false);
40  if (ct && ct->isText() && ct->name().trimmed().isEmpty() && (!cd || cd->filename().trimmed().isEmpty())) {
41  // text/* w/o filename parameter:
42  return AttachmentStrategy::Inline;
43  }
44  return AttachmentStrategy::AsIcon;
45 }
46 
47 //
48 // IconicAttachmentStrategy:
49 // show everything but the first text/plain body as icons
50 //
51 
52 class IconicAttachmentStrategy : public AttachmentStrategy
53 {
54  friend class AttachmentStrategy;
55 
56 protected:
57  IconicAttachmentStrategy()
59  {
60  }
61 
62  ~IconicAttachmentStrategy() override = default;
63 
64 public:
65  Q_REQUIRED_RESULT const char *name() const override
66  {
67  return "iconic";
68  }
69 
70  Q_REQUIRED_RESULT bool inlineNestedMessages() const override
71  {
72  return false;
73  }
74 
75  Display defaultDisplay(KMime::Content *node) const override
76  {
77  if (node->contentType()->isText()
78  && (!node->parent() || (node->contentDisposition()->filename().trimmed().isEmpty() && node->contentType(false)->name().trimmed().isEmpty()))) {
79  // text/* w/o filename parameter:
80  return Inline;
81  }
82  return AsIcon;
83  }
84 };
85 
86 //
87 // SmartAttachmentStrategy:
88 // in addition to Iconic, show all body parts
89 // with content-disposition == "inline" and
90 // all text parts without a filename or name parameter inline
91 //
92 
93 class SmartAttachmentStrategy : public AttachmentStrategy
94 {
95  friend class AttachmentStrategy;
96 
97 protected:
98  SmartAttachmentStrategy()
100  {
101  }
102 
103  ~SmartAttachmentStrategy() override = default;
104 
105 public:
106  Q_REQUIRED_RESULT const char *name() const override
107  {
108  return "smart";
109  }
110 
111  Q_REQUIRED_RESULT bool inlineNestedMessages() const override
112  {
113  return true;
114  }
115 
116  Display defaultDisplay(KMime::Content *node) const override
117  {
118  return smartDisplay(node);
119  }
120 };
121 
122 //
123 // InlinedAttachmentStrategy:
124 // show everything possible inline
125 //
126 
127 class InlinedAttachmentStrategy : public AttachmentStrategy
128 {
129  friend class AttachmentStrategy;
130 
131 protected:
132  InlinedAttachmentStrategy()
134  {
135  }
136 
137  ~InlinedAttachmentStrategy() override = default;
138 
139 public:
140  Q_REQUIRED_RESULT const char *name() const override
141  {
142  return "inlined";
143  }
144 
145  Q_REQUIRED_RESULT bool inlineNestedMessages() const override
146  {
147  return true;
148  }
149 
150  Display defaultDisplay(KMime::Content *) const override
151  {
152  return Inline;
153  }
154 };
155 
156 //
157 // HiddenAttachmentStrategy
158 // show nothing except the first text/plain body part _at all_
159 //
160 
161 class HiddenAttachmentStrategy : public AttachmentStrategy
162 {
163  friend class AttachmentStrategy;
164 
165 protected:
166  HiddenAttachmentStrategy()
168  {
169  }
170 
171  ~HiddenAttachmentStrategy() override = default;
172 
173 public:
174  Q_REQUIRED_RESULT const char *name() const override
175  {
176  return "hidden";
177  }
178 
179  Q_REQUIRED_RESULT bool inlineNestedMessages() const override
180  {
181  return false;
182  }
183 
184  Display defaultDisplay(KMime::Content *node) const override
185  {
186  if (node->contentType()->isText() && node->contentDisposition()->filename().trimmed().isEmpty()
187  && node->contentType(false)->name().trimmed().isEmpty()) {
188  // text/* w/o filename parameter:
189  return Inline;
190  }
191  if (!node->parent()) {
192  return Inline;
193  }
194 
195  if (node->parent() && node->parent()->contentType()->isMultipart() && node->parent()->contentType(false)->subType() == "related") {
196  return Inline;
197  }
198 
199  return None;
200  }
201 };
202 
203 class HeaderOnlyAttachmentStrategy : public AttachmentStrategy
204 {
205  friend class AttachmentStrategy;
206 
207 protected:
208  HeaderOnlyAttachmentStrategy()
210  {
211  }
212 
213  ~HeaderOnlyAttachmentStrategy() override = default;
214 
215 public:
216  Q_REQUIRED_RESULT const char *name() const override
217  {
218  return "headerOnly";
219  }
220 
221  Q_REQUIRED_RESULT bool inlineNestedMessages() const override
222  {
223  return true;
224  }
225 
226  Display defaultDisplay(KMime::Content *node) const override
227  {
229  return smartDisplay(node);
230  }
231 
232  if (!MimeTreeParser::Util::labelForContent(node).isEmpty() && QIcon::hasThemeIcon(MimeTreeParser::Util::iconNameForContent(node))
233  && !MimeTreeParser::Util::isTypeBlacklisted(node)) {
234  return None;
235  }
236  return smartDisplay(node);
237  }
238 
239  Q_REQUIRED_RESULT bool requiresAttachmentListInHeader() const override
240  {
241  return true;
242  }
243 };
244 
245 //
246 // AttachmentStrategy abstract base:
247 //
248 
249 AttachmentStrategy::AttachmentStrategy() = default;
250 
251 AttachmentStrategy::~AttachmentStrategy() = default;
252 
253 const AttachmentStrategy *AttachmentStrategy::create(Type type)
254 {
255  switch (type) {
256  case Iconic:
257  return iconic();
258  case Smart:
259  return smart();
260  case Inlined:
261  return inlined();
262  case Hidden:
263  return hidden();
264  case HeaderOnly:
265  return headerOnly();
266  }
267  qCCritical(MESSAGEVIEWER_LOG) << "Unknown attachment strategy ( type ==" << static_cast<int>(type) << ") requested!";
268  return nullptr; // make compiler happy
269 }
270 
271 const AttachmentStrategy *AttachmentStrategy::create(const QString &type)
272 {
273  const QString lowerType = type.toLower();
274  if (lowerType == QLatin1String("iconic")) {
275  return iconic();
276  }
277  // if ( lowerType == "smart" ) return smart(); // not needed, see below
278  if (lowerType == QLatin1String("inlined")) {
279  return inlined();
280  }
281  if (lowerType == QLatin1String("hidden")) {
282  return hidden();
283  }
284  if (lowerType == QLatin1String("headeronly")) {
285  return headerOnly();
286  }
287  // don't kFatal here, b/c the strings are user-provided
288  // (KConfig), so fail gracefully to the default:
289  return smart();
290 }
291 
292 static const AttachmentStrategy *iconicStrategy = nullptr;
293 static const AttachmentStrategy *smartStrategy = nullptr;
294 static const AttachmentStrategy *inlinedStrategy = nullptr;
295 static const AttachmentStrategy *hiddenStrategy = nullptr;
296 static const AttachmentStrategy *headerOnlyStrategy = nullptr;
297 
298 const AttachmentStrategy *AttachmentStrategy::iconic()
299 {
300  if (!iconicStrategy) {
301  iconicStrategy = new IconicAttachmentStrategy();
302  }
303  return iconicStrategy;
304 }
305 
306 const AttachmentStrategy *AttachmentStrategy::smart()
307 {
308  if (!smartStrategy) {
309  smartStrategy = new SmartAttachmentStrategy();
310  }
311  return smartStrategy;
312 }
313 
314 const AttachmentStrategy *AttachmentStrategy::inlined()
315 {
316  if (!inlinedStrategy) {
317  inlinedStrategy = new InlinedAttachmentStrategy();
318  }
319  return inlinedStrategy;
320 }
321 
322 const AttachmentStrategy *AttachmentStrategy::hidden()
323 {
324  if (!hiddenStrategy) {
325  hiddenStrategy = new HiddenAttachmentStrategy();
326  }
327  return hiddenStrategy;
328 }
329 
330 const AttachmentStrategy *AttachmentStrategy::headerOnly()
331 {
332  if (!headerOnlyStrategy) {
333  headerOnlyStrategy = new HeaderOnlyAttachmentStrategy();
334  }
335  return headerOnlyStrategy;
336 }
337 
338 bool AttachmentStrategy::requiresAttachmentListInHeader() const
339 {
340  return false;
341 }
QByteArray subType() const
Headers::ContentDisposition * contentDisposition(bool create=true)
const QLatin1String name
bool hasThemeIcon(const QString &name)
bool isEmpty() const const
QString trimmed() const const
static bool isInEncapsulatedMessage(KMime::Content *node)
Headers::ContentType * contentType(bool create=true)
QString toLower() const const
The AttachmentStrategy class.
Content * parent() const
Display
Used to determine if the visible part of the anchor contains only the name part and not the given ema...
Definition: stringutil.h:92
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Dec 5 2021 23:04:53 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.