Mailcommon

filterimporterevolution.cpp
1 /*
2  SPDX-FileCopyrightText: 2012-2022 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "filterimporterevolution.h"
8 #include "filter/filtermanager.h"
9 #include "filter/mailfilter.h"
10 
11 #include "mailcommon_debug.h"
12 #include <QDir>
13 #include <QFile>
14 using namespace MailCommon;
15 
16 FilterImporterEvolution::FilterImporterEvolution(QFile *file)
17  : FilterImporterAbstract()
18 {
19  QDomDocument doc;
20  if (!loadDomElement(doc, file)) {
21  return;
22  }
23 
24  QDomElement filters = doc.documentElement();
25 
26  if (filters.isNull()) {
27  qCDebug(MAILCOMMON_LOG) << "No filters defined";
28  return;
29  }
30  filters = filters.firstChildElement(QStringLiteral("ruleset"));
31  for (QDomElement e = filters.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
32  const QString tag = e.tagName();
33  if (tag == QLatin1String("rule")) {
34  parseFilters(e);
35  } else {
36  qCDebug(MAILCOMMON_LOG) << " unknown tag " << tag;
37  }
38  }
39 }
40 
41 FilterImporterEvolution::~FilterImporterEvolution() = default;
42 
43 QString FilterImporterEvolution::defaultFiltersSettingsPath()
44 {
45  return QStringLiteral("%1/.config/evolution/mail/filters.xml").arg(QDir::homePath());
46 }
47 
48 void FilterImporterEvolution::parsePartAction(const QDomElement &ruleFilter, MailCommon::MailFilter *filter, parseType type)
49 {
50  for (QDomElement partFilter = ruleFilter.firstChildElement(); !partFilter.isNull(); partFilter = partFilter.nextSiblingElement()) {
51  const QString nexttag = partFilter.tagName();
52  if (nexttag == QLatin1String("part")) {
53  if (partFilter.hasAttribute(QStringLiteral("name"))) {
54  const QString name = partFilter.attribute(QStringLiteral("name"));
55  qCDebug(MAILCOMMON_LOG) << " parsePartAction name attribute :" << name;
56  if (type == FilterImporterEvolution::PartType) {
57  QByteArray fieldName;
58 
59  if (name == QLatin1String("to")) {
60  fieldName = "to";
61  } else if (name == QLatin1String("sender")) {
62  fieldName = "from";
63  } else if (name == QLatin1String("cc")) {
64  fieldName = "cc";
65  } else if (name == QLatin1String("bcc")) {
66  fieldName = "bcc"; // Verify
67  // TODO
68  } else if (name == QLatin1String("senderto")) {
69  // TODO
70  } else if (name == QLatin1String("subject")) {
71  fieldName = "subject";
72  } else if (name == QLatin1String("header")) {
73  fieldName = "<any header>";
74  } else if (name == QLatin1String("body")) {
75  fieldName = "<body>";
76  } else if (name == QLatin1String("sexp")) {
77  // TODO
78  } else if (name == QLatin1String("sent-date")) {
79  // TODO
80  } else if (name == QLatin1String("recv-date")) {
81  fieldName = "<date>";
82  } else if (name == QLatin1String("label")) {
83  // TODO
84  } else if (name == QLatin1String("score")) {
85  // TODO
86  } else if (name == QLatin1String("size")) {
87  fieldName = "<size>";
88  } else if (name == QLatin1String("status")) {
89  fieldName = "<status>";
90  } else if (name == QLatin1String("follow-up")) {
91  // TODO
92  } else if (name == QLatin1String("completed-on")) {
93  // TODO
94  } else if (name == QLatin1String("attachments")) {
95  // TODO
96  } else if (name == QLatin1String("mlist")) {
97  fieldName = "list-id"; // Verify
98  } else if (name == QLatin1String("regex")) {
99  // TODO
100  } else if (name == QLatin1String("source")) {
101  // TODO
102  } else if (name == QLatin1String("pipe")) {
103  // TODO
104  } else if (name == QLatin1String("junk")) {
105  // TODO
106  } else if (name == QLatin1String("all")) {
107  filter->pattern()->setOp(SearchPattern::OpAll);
108  break;
109  } else {
110  qCDebug(MAILCOMMON_LOG) << " parttype part : name : not implemented :" << name;
111  }
112  if (fieldName.isEmpty()) {
113  qCDebug(MAILCOMMON_LOG) << " parttype part : name : not implemented :" << name;
114  continue;
115  }
116  QString contents;
117  SearchRule::Function functionName = SearchRule::FuncNone;
118 
119  for (QDomElement valueFilter = partFilter.firstChildElement(); !valueFilter.isNull(); valueFilter = valueFilter.nextSiblingElement()) {
120  const QString valueTag = valueFilter.tagName();
121 
122  if (valueTag == QLatin1String("value")) {
123  if (valueFilter.hasAttribute(QStringLiteral("name"))) {
124  const QString name = valueFilter.attribute(QStringLiteral("name"));
125  if (name == QLatin1String("flag")) {
126  const QString flag = valueFilter.attribute(QStringLiteral("value"));
127  qCDebug(MAILCOMMON_LOG) << " flag :" << flag;
128  if (flag == QLatin1String("Seen")) {
129  contents = QStringLiteral("Read");
130  } else if (flag == QLatin1String("Answered")) {
131  contents = QStringLiteral("Sent");
132  } else if (flag == QLatin1String("Draft")) {
133  // FIXME
134  } else if (flag == QLatin1String("Flagged")) { // Important
135  contents = QStringLiteral("Important");
136  } else if (flag == QLatin1String("Junk")) {
137  contents = QStringLiteral("Spam");
138  } else {
139  qCDebug(MAILCOMMON_LOG) << " unknown status flags " << flag;
140  }
141  }
142  qCDebug(MAILCOMMON_LOG) << " value filter name :" << name;
143  }
144  if (valueFilter.hasAttribute(QStringLiteral("type"))) {
145  const QString name = valueFilter.attribute(QStringLiteral("type"));
146  if (name == QLatin1String("option")) {
147  // Nothing we will look at value
148  } else if (name == QLatin1String("string")) {
149  QDomElement string = valueFilter.firstChildElement();
150  contents = string.text();
151  } else if (name == QLatin1String("folder")) {
152  QDomElement folder = valueFilter.firstChildElement();
153  if (folder.hasAttribute(QStringLiteral("uri"))) {
154  contents = folder.attribute(QStringLiteral("uri"));
155  if (!contents.isEmpty()) {
156  contents.remove(QStringLiteral("folder://"));
157  }
158  }
159  } else if (name == QLatin1String("address")) {
160  QDomElement address = valueFilter.firstChildElement();
161  contents = address.text();
162  } else if (name == QLatin1String("integer")) {
163  if (valueFilter.hasAttribute(QStringLiteral("integer"))) {
164  contents = valueFilter.attribute(QStringLiteral("integer"));
165  int val = contents.toInt();
166  val = val * 1024; // store in Ko
167  contents = QString::number(val);
168  }
169  } else {
170  qCDebug(MAILCOMMON_LOG) << " type not implemented " << name;
171  }
172  }
173  if (valueFilter.hasAttribute(QStringLiteral("value"))) {
174  const QString value = valueFilter.attribute(QStringLiteral("value"));
175  qCDebug(MAILCOMMON_LOG) << " value filter value :" << name;
176  if (value == QLatin1String("contains")) {
177  functionName = SearchRule::FuncContains;
178  } else if (value == QLatin1String("not contains")) {
179  functionName = SearchRule::FuncContainsNot;
180  } else if (value == QLatin1String("is not")) {
181  functionName = SearchRule::FuncNotEqual;
182  } else if (value == QLatin1String("is")) {
183  functionName = SearchRule::FuncEquals;
184  } else if (value == QLatin1String("exist")) {
185  // TODO
186  } else if (value == QLatin1String("not exist")) {
187  // TODO
188  } else if (value == QLatin1String("not starts with")) {
189  functionName = SearchRule::FuncNotStartWith;
190  } else if (value == QLatin1String("ends with")) {
191  functionName = SearchRule::FuncEndWith;
192  } else if (value == QLatin1String("not ends with")) {
193  functionName = SearchRule::FuncNotEndWith;
194  } else if (value == QLatin1String("matches soundex")) {
195  // TODO
196  } else if (value == QLatin1String("not match soundex")) {
197  // TODO
198  } else if (value == QLatin1String("before")) {
199  // TODO
200  } else if (value == QLatin1String("after")) {
201  // TODO
202  } else if (value == QLatin1String("greater-than")) {
203  functionName = SearchRule::FuncIsGreater;
204  } else if (value == QLatin1String("less-than")) {
205  functionName = SearchRule::FuncIsLess;
206  } else if (value == QLatin1String("starts with")) {
207  functionName = SearchRule::FuncStartWith;
208  }
209  }
210  }
211  }
212  SearchRule::Ptr rule = SearchRule::createInstance(fieldName, functionName, contents);
213  filter->pattern()->append(rule);
214  } else if (type == FilterImporterEvolution::ActionType) {
215  QString actionName;
216  if (name == QLatin1String("stop")) {
217  filter->setStopProcessingHere(true);
218  break;
219  } else if (name == QLatin1String("move-to-folder")) {
220  actionName = QStringLiteral("transfer");
221  } else if (name == QLatin1String("copy-to-folder")) {
222  actionName = QStringLiteral("copy");
223  } else if (name == QLatin1String("delete")) {
224  actionName = QStringLiteral("delete");
225  } else if (name == QLatin1String("label")) {
226  // TODO
227  } else if (name == QLatin1String("colour")) {
228  // TODO
229  } else if (name == QLatin1String("score")) {
230  // TODO
231  } else if (name == QLatin1String("adj-score")) {
232  // TODO
233  } else if (name == QLatin1String("set-status")) {
234  actionName = QStringLiteral("set status");
235  } else if (name == QLatin1String("unset-status")) {
236  actionName = QStringLiteral("unset status");
237  } else if (name == QLatin1String("play-sound")) {
238  actionName = QStringLiteral("play sound");
239  } else if (name == QLatin1String("shell")) {
240  actionName = QStringLiteral("execute");
241  } else if (name == QLatin1String("pipe")) {
242  actionName = QStringLiteral("filter app");
243  } else if (name == QLatin1String("forward")) {
244  actionName = QStringLiteral("forward");
245  }
246  if (actionName.isEmpty()) {
247  qCDebug(MAILCOMMON_LOG) << " actiontype part : name : not implemented :" << name;
248  }
249  QString value;
250  for (QDomElement valueFilter = partFilter.firstChildElement(); !valueFilter.isNull(); valueFilter = valueFilter.nextSiblingElement()) {
251  const QString valueTag = valueFilter.tagName();
252  if (valueTag == QLatin1String("value")) {
253  if (valueFilter.hasAttribute(QStringLiteral("name"))) {
254  const QString name = valueFilter.attribute(QStringLiteral("name"));
255  qCDebug(MAILCOMMON_LOG) << " value filter name :" << name;
256  }
257  if (valueFilter.hasAttribute(QStringLiteral("type"))) {
258  const QString name = valueFilter.attribute(QStringLiteral("type"));
259  qCDebug(MAILCOMMON_LOG) << " value filter type :" << name;
260  if (name == QLatin1String("option")) {
261  // Nothing we will look at value
262  } else if (name == QLatin1String("string")) {
263  // TODO
264  } else if (name == QLatin1String("folder")) {
265  QDomElement folder = valueFilter.firstChildElement();
266 
267  if (folder.hasAttribute(QStringLiteral("uri"))) {
268  value = folder.attribute(QStringLiteral("uri"));
269  if (!value.isEmpty()) {
270  value.remove(QStringLiteral("folder://"));
271  }
272  qCDebug(MAILCOMMON_LOG) << " contents folder :" << value;
273  }
274  } else if (name == QLatin1String("address")) {
275  // TODO
276  }
277  }
278  if (valueFilter.hasAttribute(QStringLiteral("value"))) {
279  const QString name = valueFilter.attribute(QStringLiteral("value"));
280  qCDebug(MAILCOMMON_LOG) << " value filter value :" << name;
281  if (value == QLatin1String("contains")) {
282  // TODO
283  }
284  }
285  }
286  }
287  createFilterAction(filter, actionName, value);
288  }
289  }
290  }
291  }
292 }
293 
294 void FilterImporterEvolution::parseFilters(const QDomElement &e)
295 {
296  auto filter = new MailCommon::MailFilter();
297  if (e.hasAttribute(QStringLiteral("enabled"))) {
298  const QString attr = e.attribute(QStringLiteral("enabled"));
299  if (attr == QLatin1String("false")) {
300  filter->setEnabled(false);
301  }
302  }
303 
304  if (e.hasAttribute(QStringLiteral("grouping"))) {
305  const QString attr = e.attribute(QStringLiteral("grouping"));
306  if (attr == QLatin1String("all")) {
307  filter->pattern()->setOp(SearchPattern::OpAnd);
308  } else if (attr == QLatin1String("any")) {
309  filter->pattern()->setOp(SearchPattern::OpOr);
310  } else {
311  qCDebug(MAILCOMMON_LOG) << " grouping not implemented: " << attr;
312  }
313  }
314 
315  if (e.hasAttribute(QStringLiteral("source"))) {
316  const QString attr = e.attribute(QStringLiteral("source"));
317  if (attr == QLatin1String("incoming")) {
318  filter->setApplyOnInbound(true);
319  } else if (attr == QLatin1String("outgoing")) {
320  filter->setApplyOnInbound(false);
321  filter->setApplyOnOutbound(true);
322  } else {
323  qCDebug(MAILCOMMON_LOG) << " source not implemented :" << attr;
324  }
325  }
326  for (QDomElement ruleFilter = e.firstChildElement(); !ruleFilter.isNull(); ruleFilter = ruleFilter.nextSiblingElement()) {
327  const QString nexttag = ruleFilter.tagName();
328  if (nexttag == QLatin1String("title")) {
329  filter->pattern()->setName(ruleFilter.text());
330  filter->setToolbarName(ruleFilter.text());
331  } else if (nexttag == QLatin1String("partset")) {
332  parsePartAction(ruleFilter, filter, PartType);
333  } else if (nexttag == QLatin1String("actionset")) {
334  parsePartAction(ruleFilter, filter, ActionType);
335  } else {
336  qCDebug(MAILCOMMON_LOG) << " tag not implemented : " << nexttag;
337  }
338  }
339 
340  appendFilter(filter);
341 }
QString text() const const
std::shared_ptr< SearchRule > Ptr
Defines a pointer to a search rule.
Definition: searchrule.h:29
QString number(int n, int base)
QString tagName() const const
bool isNull() const const
QString homePath()
The MailFilter class.
Definition: mailfilter.h:28
bool isEmpty() const const
static SearchRule::Ptr createInstance(const QByteArray &field=QByteArray(), Function function=FuncContains, const QString &contents=QString())
Creates a new search rule of a certain type by instantiating the appropriate subclass depending on th...
Definition: searchrule.cpp:75
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
int toInt(bool *ok, int base) const const
QDomElement nextSiblingElement(const QString &tagName) const const
PostalAddress address(const QVariant &location)
QDomElement documentElement() const const
Function
Describes operators for comparison of field and contents.
Definition: searchrule.h:40
QDomElement firstChildElement(const QString &tagName) const const
QString & remove(int position, int n)
bool hasAttribute(const QString &name) const const
bool isEmpty() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString name(StandardShortcut id)
QString attribute(const QString &name, const QString &defValue) const const
The filter dialog.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Oct 1 2022 04:00:53 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.