Mailcommon

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

KDE's Doxygen guidelines are available online.