Libksieve

vacationscriptextractor.h
1/*
2 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#pragma once
8
9#include "sieve-vacation.h"
10#include "vacationutils.h"
11
12#include "error.h"
13#include "parser.h"
14#include "scriptbuilder.h"
15
16#include "libksievecore_debug.h"
17#include <cassert>
18#include <climits>
19#include <map>
20#include <set>
21#include <vector>
22
23namespace KSieveExt
24{
25class MultiScriptBuilder : public KSieve::ScriptBuilder
26{
27 std::vector<KSieve::ScriptBuilder *> mBuilders;
28
29public:
30 MultiScriptBuilder()
31 : KSieve::ScriptBuilder()
32 {
33 }
34
35 MultiScriptBuilder(KSieve::ScriptBuilder *sb1)
36 : KSieve::ScriptBuilder()
37 , mBuilders(1)
38 {
39 mBuilders[0] = sb1;
40 assert(sb1);
41 }
42
43 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2)
44 : KSieve::ScriptBuilder()
45 , mBuilders(2)
46 {
47 mBuilders[0] = sb1;
48 mBuilders[1] = sb2;
49 assert(sb1);
50 assert(sb2);
51 }
52
53 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2, KSieve::ScriptBuilder *sb3)
54 : KSieve::ScriptBuilder()
55 , mBuilders(3)
56 {
57 mBuilders[0] = sb1;
58 mBuilders[1] = sb2;
59 mBuilders[2] = sb3;
60 assert(sb1);
61 assert(sb2);
62 assert(sb3);
63 }
64
65 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2, KSieve::ScriptBuilder *sb3, KSieve::ScriptBuilder *sb4)
66 : KSieve::ScriptBuilder()
67 , mBuilders(4)
68 {
69 mBuilders[0] = sb1;
70 mBuilders[1] = sb2;
71 mBuilders[2] = sb3;
72 mBuilders[3] = sb4;
73 assert(sb1);
74 assert(sb2);
75 assert(sb3);
76 assert(sb4);
77 }
78
79 ~MultiScriptBuilder() override = default;
80
81private:
82#ifdef FOREACH
83#undef FOREACH
84#endif
85#define FOREACH \
86 for (std::vector<KSieve::ScriptBuilder *>::const_iterator it = mBuilders.begin(), end = mBuilders.end(); it != end; ++it) \
87 (*it)->
88 void commandStart(const QString &identifier, int lineNumber) override
89 {
90 FOREACH commandStart(identifier, lineNumber);
91 }
92
93 void commandEnd(int lineNumber) override
94 {
95 FOREACH commandEnd(lineNumber);
96 }
97
98 void testStart(const QString &identifier) override
99 {
100 FOREACH testStart(identifier);
101 }
102
103 void testEnd() override
104 {
105 FOREACH testEnd();
106 }
107
108 void testListStart() override
109 {
110 FOREACH testListStart();
111 }
112
113 void testListEnd() override
114 {
115 FOREACH testListEnd();
116 }
117
118 void blockStart(int lineNumber) override
119 {
120 FOREACH blockStart(lineNumber);
121 }
122
123 void blockEnd(int lineNumber) override
124 {
125 FOREACH blockEnd(lineNumber);
126 }
127
128 void hashComment(const QString &comment) override
129 {
130 FOREACH hashComment(comment);
131 }
132
133 void bracketComment(const QString &comment) override
134 {
135 FOREACH bracketComment(comment);
136 }
137
138 void lineFeed() override
139 {
140 FOREACH lineFeed();
141 }
142
143 void error(const KSieve::Error &e) override
144 {
145 FOREACH error(e);
146 }
147
148 void finished() override
149 {
150 FOREACH finished();
151 }
152
153 void taggedArgument(const QString &tag) override
154 {
155 FOREACH taggedArgument(tag);
156 }
157
158 void stringArgument(const QString &string, bool multiline, const QString &fixme) override
159 {
160 FOREACH stringArgument(string, multiline, fixme);
161 }
162
163 void numberArgument(unsigned long number, char quantifier) override
164 {
165 FOREACH numberArgument(number, quantifier);
166 }
167
168 void stringListArgumentStart() override
169 {
170 FOREACH stringListArgumentStart();
171 }
172
173 void stringListEntry(const QString &string, bool multiline, const QString &fixme) override
174 {
175 FOREACH stringListEntry(string, multiline, fixme);
176 }
177
178 void stringListArgumentEnd() override
179 {
180 FOREACH stringListArgumentEnd();
181 }
182
183#undef FOREACH
184};
185}
186
187namespace KSieveCore
188{
189class GenericInformationExtractor : public KSieve::ScriptBuilder
190{
191public:
192 enum BuilderMethod {
193 Any,
194 TaggedArgument,
195 StringArgument,
196 NumberArgument,
197 CommandStart,
198 CommandEnd,
199 TestStart,
200 TestEnd,
201 TestListStart,
202 TestListEnd,
203 BlockStart,
204 BlockEnd,
205 StringListArgumentStart,
206 StringListEntry,
207 StringListArgumentEnd
208 };
209
210 struct StateNode {
211 // expectation:
212 int depth;
213 BuilderMethod method;
214 const char *string;
215 // actions:
216 int if_found;
217 int if_not_found;
218 const char *save_tag;
219 };
220
221 const std::vector<StateNode> mNodes;
222 std::map<QString, QString> mResults;
223 std::set<unsigned int> mRecursionGuard;
224 unsigned int mState;
225 int mNestingDepth;
226
227 int mLineNumber;
228
229public:
230 GenericInformationExtractor(const std::vector<StateNode> &nodes)
231 : KSieve::ScriptBuilder()
232 , mNodes(nodes)
233 , mState(0)
234 , mNestingDepth(0)
235 , mLineNumber(0)
236 {
237 }
238
239 const std::map<QString, QString> &results() const
240 {
241 return mResults;
242 }
243
244private:
245 void process(BuilderMethod method, const QString &string = QString())
246 {
247 doProcess(method, string);
248 mRecursionGuard.clear();
249 }
250
251 void doProcess(BuilderMethod method, const QString &string)
252 {
253 mRecursionGuard.insert(mState);
254 bool found = true;
255 const StateNode &expected = mNodes[mState];
256 if (expected.depth != -1 && mNestingDepth != expected.depth) {
257 found = false;
258 }
259 if (expected.method != Any && method != expected.method) {
260 found = false;
261 }
262 if (const char *str = expected.string) {
263 if (string.toLower() != QString::fromUtf8(str).toLower()) {
264 found = false;
265 }
266 }
267 qCDebug(LIBKSIEVECORE_LOG) << (found ? "found:" : "not found:") << mState << "->" << (found ? expected.if_found : expected.if_not_found);
268 mState = found ? expected.if_found : expected.if_not_found;
269 assert(mState < mNodes.size());
270 if (found) {
271 if (const char *save_tag = expected.save_tag) {
272 mResults[QString::fromLatin1(save_tag)] = string;
273 }
274 }
275 if (!found && !mRecursionGuard.count(mState)) {
276 doProcess(method, string);
277 }
278 }
279
280 void commandStart(const QString &identifier, int lineNumber) override
281 {
282 Q_UNUSED(lineNumber)
283 qCDebug(LIBKSIEVECORE_LOG);
284 process(CommandStart, identifier);
285 }
286
287 void commandEnd(int lineNumber) override
288 {
289 Q_UNUSED(lineNumber)
290 qCDebug(LIBKSIEVECORE_LOG);
291 process(CommandEnd);
292 }
293
294 void testStart(const QString &identifier) override
295 {
296 qCDebug(LIBKSIEVECORE_LOG);
297 process(TestStart, identifier);
298 }
299
300 void testEnd() override
301 {
302 qCDebug(LIBKSIEVECORE_LOG);
303 process(TestEnd);
304 }
305
306 void testListStart() override
307 {
308 qCDebug(LIBKSIEVECORE_LOG);
309 process(TestListStart);
310 }
311
312 void testListEnd() override
313 {
314 qCDebug(LIBKSIEVECORE_LOG);
315 process(TestListEnd);
316 }
317
318 void blockStart(int lineNumber) override
319 {
320 Q_UNUSED(lineNumber)
321 qCDebug(LIBKSIEVECORE_LOG);
322 process(BlockStart);
323 ++mNestingDepth;
324 }
325
326 void blockEnd(int lineNumber) override
327 {
328 Q_UNUSED(lineNumber)
329 qCDebug(LIBKSIEVECORE_LOG);
330 --mNestingDepth;
331 process(BlockEnd);
332 }
333
334 void hashComment(const QString &) override
335 {
336 qCDebug(LIBKSIEVECORE_LOG);
337 }
338
339 void bracketComment(const QString &) override
340 {
341 qCDebug(LIBKSIEVECORE_LOG);
342 }
343
344 void lineFeed() override
345 {
346 qCDebug(LIBKSIEVECORE_LOG);
347 }
348
349 void error(const KSieve::Error &) override
350 {
351 qCDebug(LIBKSIEVECORE_LOG);
352 mState = 0;
353 }
354
355 void finished() override
356 {
357 qCDebug(LIBKSIEVECORE_LOG);
358 }
359
360 void taggedArgument(const QString &tag) override
361 {
362 qCDebug(LIBKSIEVECORE_LOG);
363 process(TaggedArgument, tag);
364 }
365
366 void stringArgument(const QString &string, bool, const QString &) override
367 {
368 qCDebug(LIBKSIEVECORE_LOG);
369 process(StringArgument, string);
370 }
371
372 void numberArgument(unsigned long number, char) override
373 {
374 qCDebug(LIBKSIEVECORE_LOG);
375 process(NumberArgument, QString::number(number));
376 }
377
378 void stringListArgumentStart() override
379 {
380 qCDebug(LIBKSIEVECORE_LOG);
381 process(StringListArgumentStart);
382 }
383
384 void stringListEntry(const QString &string, bool, const QString &) override
385 {
386 qCDebug(LIBKSIEVECORE_LOG);
387 process(StringListEntry, string);
388 }
389
390 void stringListArgumentEnd() override
391 {
392 qCDebug(LIBKSIEVECORE_LOG);
393 process(StringListArgumentEnd);
394 }
395};
396
397using GIE = GenericInformationExtractor;
398static const GenericInformationExtractor::StateNode spamNodes[] = {
399 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0
400 {0, GIE::TestStart, "allof", 2, 3, nullptr}, // 1
401 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2
402 {0, GIE::TestStart, "not", 4, 3, nullptr}, // 3
403 {0, GIE::TestStart, "header", 5, 3, nullptr}, // 4
404 {0, GIE::TaggedArgument, "contains", 6, 0, nullptr}, // 5
405
406 // accept both string and string-list:
407 {0, GIE::StringArgument, "x-spam-flag", 12, 7, "x-spam-flag"}, // 6
408 {0, GIE::StringListArgumentStart, nullptr, 8, 0, nullptr}, // 7
409 {0, GIE::StringListEntry, "x-spam-flag", 9, 10, "x-spam-flag"}, // 8
410 {0, GIE::StringListEntry, nullptr, 9, 11, nullptr}, // 9
411 {0, GIE::StringListArgumentEnd, nullptr, 0, 8, nullptr}, // 10
412 {0, GIE::StringListArgumentEnd, nullptr, 12, 0, nullptr}, // 11
413
414 // accept both string and string-list:
415 {0, GIE::StringArgument, "yes", 18, 13, "spam-flag-yes"}, // 12
416 {0, GIE::StringListArgumentStart, nullptr, 14, 0, nullptr}, // 13
417 {0, GIE::StringListEntry, "yes", 15, 16, "spam-flag-yes"}, // 14
418 {0, GIE::StringListEntry, nullptr, 15, 17, nullptr}, // 15
419 {0, GIE::StringListArgumentEnd, nullptr, 0, 14, nullptr}, // 16
420 {0, GIE::StringListArgumentEnd, nullptr, 18, 0, nullptr}, // 17
421
422 {0, GIE::TestEnd, nullptr, 21, 20, nullptr}, // 18
423 {0, GIE::Any, nullptr, 21, 0, nullptr}, // 19
424 {0, GIE::TestListEnd, nullptr, 21, 19, nullptr}, // 20
425
426 // block of command, find "stop", take nested if's into account:
427 {0, GIE::BlockStart, nullptr, 22, 18, nullptr}, // 21
428 {1, GIE::CommandStart, "vacation", 24, 22, "vacation"}, // 22
429 {1, GIE::Any, nullptr, 24, 0, nullptr}, // 23
430 {0, GIE::BlockEnd, nullptr, 25, 23, nullptr}, // 24
431
432 {-1, GIE::Any, nullptr, 25, 25, nullptr}, // 25 end state
433};
434static const unsigned int numSpamNodes = sizeof spamNodes / sizeof *spamNodes;
435
436class SpamDataExtractor : public GenericInformationExtractor
437{
438public:
439 SpamDataExtractor()
440 : GenericInformationExtractor(std::vector<StateNode>(spamNodes, spamNodes + numSpamNodes))
441 {
442 }
443
444 bool found() const
445 {
446 return mResults.count(QStringLiteral("x-spam-flag")) && mResults.count(QStringLiteral("spam-flag-yes")) && mResults.count(QStringLiteral("vacation"));
447 }
448};
449
450// to understand this table, study the output of
451// libksieve/tests/parsertest
452// 'if not address :domain :contains ["from"] ["mydomain.org"] { keep; stop; }'
453static const GenericInformationExtractor::StateNode domainNodes[] = {
454 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0
455 {0, GIE::TestStart, "allof", 2, 3, nullptr}, // 1
456 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2
457 {0, GIE::TestStart, "address", 4, 3, nullptr}, // 3
458
459 // :domain and :contains in arbitrary order:
460 {0, GIE::TaggedArgument, "domain", 5, 6, nullptr}, // 4
461 {0, GIE::TaggedArgument, "contains", 8, 0, nullptr}, // 5
462 {0, GIE::TaggedArgument, "contains", 7, 0, nullptr}, // 6
463 {0, GIE::TaggedArgument, "domain", 8, 0, nullptr}, // 7
464
465 // accept both string and string-list:
466 {0, GIE::StringArgument, "from", 14, 9, "from"}, // 8
467 {0, GIE::StringListArgumentStart, nullptr, 10, 0, nullptr}, // 9
468 {0, GIE::StringListEntry, "from", 11, 12, "from"}, // 10
469 {0, GIE::StringListEntry, nullptr, 11, 13, nullptr}, // 11
470 {0, GIE::StringListArgumentEnd, nullptr, 0, 10, nullptr}, // 12
471 {0, GIE::StringListArgumentEnd, nullptr, 14, 0, nullptr}, // 13
472
473 // string: save, string-list: save last
474 {0, GIE::StringArgument, nullptr, 18, 15, "domainName"}, // 14
475 {0, GIE::StringListArgumentStart, nullptr, 16, 0, nullptr}, // 15
476 {0, GIE::StringListEntry, nullptr, 16, 17, "domainName"}, // 16
477 {0, GIE::StringListArgumentEnd, nullptr, 18, 0, nullptr}, // 17
478
479 {0, GIE::TestEnd, nullptr, 18, 20, nullptr}, // 18
480 {0, GIE::Any, nullptr, 18, 0, nullptr}, // 19
481
482 // block of commands, find "stop", take nested if's into account:
483 {0, GIE::BlockStart, nullptr, 21, 19, nullptr}, // 20
484 {1, GIE::CommandStart, "vacation", 23, 21, "vacation"}, // 21
485 {1, GIE::Any, nullptr, 23, 0, nullptr}, // 22
486 {0, GIE::BlockEnd, nullptr, 24, 22, nullptr}, // 23
487
488 {-1, GIE::Any, nullptr, 24, 24, nullptr} // 24 end state
489};
490static const unsigned int numDomainNodes = sizeof domainNodes / sizeof *domainNodes;
491
492class DomainRestrictionDataExtractor : public GenericInformationExtractor
493{
494public:
495 DomainRestrictionDataExtractor()
496 : GenericInformationExtractor(std::vector<StateNode>(domainNodes, domainNodes + numDomainNodes))
497 {
498 }
499
500 QString domainName() /*not const, since map::op[] isn't const*/
501 {
502 return mResults.count(QStringLiteral("vacation")) && mResults.count(QStringLiteral("from")) ? mResults[QStringLiteral("domainName")] : QString();
503 }
504};
505
506// if not allof (currentdate :value "ge" date "YYYY-MM-DD",
507// currentfate :value "le" date "YYYY-MM-DD) { keep; stop; }
508static const GenericInformationExtractor::StateNode datesNodes[] = {
509 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0
510 {0, GIE::TestStart, "allof", 2, 0, nullptr}, // 1
511
512 // handle startDate and endDate in arbitrary order
513 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2
514 {0, GIE::TestStart, "currentdate", 4, 3, nullptr}, // 3
515 {0, GIE::TaggedArgument, "value", 5, 4, nullptr}, // 4
516 {0, GIE::StringArgument, "ge", 6, 10, nullptr}, // 5
517 {0, GIE::StringArgument, "date", 7, 8, nullptr}, // 6
518 {0, GIE::StringArgument, nullptr, 15, 0, "startDate"}, // 7
519 {0, GIE::StringArgument, "iso8601", 9, 0, nullptr}, // 8
520 {0, GIE::StringArgument, nullptr, 15, 0, "startDateTime"}, // 9
521 {0, GIE::StringArgument, "le", 11, 0, nullptr}, // 10
522 {0, GIE::StringArgument, "date", 12, 13, nullptr}, // 11
523 {0, GIE::StringArgument, nullptr, 15, 0, "endDate"}, // 12
524 {0, GIE::StringArgument, "iso8601", 14, 0, nullptr}, // 13
525 {0, GIE::StringArgument, nullptr, 15, 0, "endDateTime"}, // 14
526 {0, GIE::TestEnd, nullptr, 16, 0, nullptr}, // 15
527
528 {0, GIE::TestStart, "currentdate", 17, 16, nullptr}, // 16
529 {0, GIE::TaggedArgument, "value", 18, 17, nullptr}, // 17
530 {0, GIE::StringArgument, "le", 19, 23, nullptr}, // 18
531 {0, GIE::StringArgument, "date", 20, 21, nullptr}, // 19
532 {0, GIE::StringArgument, nullptr, 28, 0, "endDate"}, // 20
533 {0, GIE::StringArgument, "iso8601", 22, 0, nullptr}, // 21
534 {0, GIE::StringArgument, nullptr, 28, 0, "endDateTime"}, // 22
535 {0, GIE::StringArgument, "ge", 24, 0, nullptr}, // 23
536 {0, GIE::StringArgument, "date", 25, 26, nullptr}, // 24
537 {0, GIE::StringArgument, nullptr, 28, 0, "startDate"}, // 25
538 {0, GIE::StringArgument, "iso8601", 27, 0, nullptr}, // 26
539 {0, GIE::StringArgument, nullptr, 28, 0, "startDateTime"}, // 27
540 {0, GIE::TestEnd, nullptr, 32, 0, nullptr}, // 28
541 {0, GIE::TestStart, nullptr, 31, 30, nullptr}, // 29
542 {-1, GIE::Any, nullptr, 32, 0, nullptr}, // 30
543 {0, GIE::TestEnd, nullptr, 32, 30, nullptr}, // 31
544 {0, GIE::TestListEnd, nullptr, 33, 29, nullptr}, // 32
545
546 {0, GIE::TestEnd, nullptr, 34, 0, nullptr}, // 33
547
548 // block of commands, find "stop", take nested if's into account:
549 {0, GIE::BlockStart, nullptr, 36, 33, nullptr}, // 34
550 {-1, GIE::Any, nullptr, 36, 0, nullptr}, // 35
551 {1, GIE::CommandStart, "vacation", 38, 35, "vacation"}, // 36
552 {-1, GIE::Any, nullptr, 38, 0, nullptr}, // 37
553 {0, GIE::BlockEnd, nullptr, 39, 37, nullptr}, // 38
554
555 {-1, GIE::Any, nullptr, 39, 39, nullptr} // 39 end state
556};
557
558static const unsigned int numDatesNodes = sizeof datesNodes / sizeof *datesNodes;
559
560class DateExtractor : public GenericInformationExtractor
561{
562public:
563 DateExtractor()
564 : GenericInformationExtractor(std::vector<StateNode>(datesNodes, datesNodes + numDatesNodes))
565 {
566 }
567
568 QDate endDate() const
569 {
570 if (results().count(QStringLiteral("endDateTime")) == 1) {
571 return datetime(QStringLiteral("endDateTime")).date();
572 } else {
573 return date(QStringLiteral("endDate"));
574 }
575 }
576
577 QDate startDate() const
578 {
579 if (results().count(QStringLiteral("startDateTime")) == 1) {
580 return datetime(QStringLiteral("startDateTime")).date();
581 } else {
582 return date(QStringLiteral("startDate"));
583 }
584 }
585
586 QTime endTime() const
587 {
588 return datetime(QStringLiteral("endDateTime")).time();
589 }
590
591 QTime startTime() const
592 {
593 return datetime(QStringLiteral("startDateTime")).time();
594 }
595
596private:
597 QDate date(const QString &name) const
598 {
599 if (results().count(name) == 0) {
600 return {};
601 } else {
602 return QDate::fromString(results().at(name), Qt::ISODate);
603 }
604 }
605
606 QDateTime datetime(const QString &name) const
607 {
608 if (results().count(name) == 0) {
609 return {};
610 } else {
611 return QDateTime::fromString(results().at(name), Qt::ISODate);
612 }
613 }
614};
615
616class VacationDataExtractor : public KSieve::ScriptBuilder
617{
618 enum Context {
619 None = 0,
620 // command itself:
621 VacationCommand,
622 // tagged args:
623 Days,
624 Addresses,
625 Subject,
626 VacationEnd,
627 IfBlock,
628 RedirectCommand
629 };
630
631public:
632 VacationDataExtractor();
633 ~VacationDataExtractor() override;
634
635 bool commandFound() const
636 {
637 return mContext == VacationEnd;
638 }
639
640 bool active() const
641 {
642 return mActive;
643 }
644
645 int notificationInterval() const
646 {
647 return mNotificationInterval;
648 }
649
650 const QString &messageText() const
651 {
652 return mMessageText;
653 }
654
655 const QStringList &aliases() const
656 {
657 return mAliases;
658 }
659
660 const QString &ifComment() const
661 {
662 return mIfComment;
663 }
664
665 VacationUtils::MailAction mailAction() const
666 {
667 return mMailAction;
668 }
669
670 const QString &mailActionRecipient() const
671 {
672 return mMailActionRecipient;
673 }
674
675 const QString &subject() const
676 {
677 return mSubject;
678 }
679
680 int lineStart() const
681 {
682 return mLineStart;
683 }
684
685 int lineEnd() const
686 {
687 return mLineEnd;
688 }
689
690private:
691 void commandStart(const QString &identifier, int lineNumber) override;
692
693 void commandEnd(int lineNumber) override;
694
695 void testStart(const QString &) override;
696 void testEnd() override
697 {
698 }
699
700 void testListStart() override
701 {
702 }
703
704 void testListEnd() override
705 {
706 }
707
708 void blockStart(int lineNumber) override;
709 void blockEnd(int lineNumber) override;
710 void hashComment(const QString &) override;
711 void bracketComment(const QString &) override
712 {
713 }
714
715 void lineFeed() override
716 {
717 }
718
719 void error(const KSieve::Error &e) override;
720 void finished() override;
721
722 void taggedArgument(const QString &tag) override;
723
724 void stringArgument(const QString &string, bool, const QString &) override;
725
726 void numberArgument(unsigned long number, char) override;
727
728 void stringListArgumentStart() override;
729 void stringListEntry(const QString &string, bool, const QString &) override;
730 void stringListArgumentEnd() override;
731
732private:
733 Context mContext = None;
734 int mNotificationInterval = 0;
735 QString mMessageText;
736 QString mSubject;
737 QStringList mAliases;
738 bool mActive = true;
739 bool mInIfBlock = false;
740 bool mFoundInBlock = false;
741 int mBlockLevel = 0;
742 QString mIfComment;
743 int mLineStart = 0;
744 int mLineEnd = 0;
745
746 VacationUtils::MailAction mMailAction = VacationUtils::Keep;
747 Context mMailActionContext = None;
748 QString mMailActionRecipient;
749
750 void reset();
751};
752
753class RequireExtractor : public KSieve::ScriptBuilder
754{
755 enum Context {
756 None = 0,
757 // command itself:
758 RequireCommand,
759 EndState
760 };
761
762public:
763 RequireExtractor();
764 ~RequireExtractor() override;
765
766 bool commandFound() const
767 {
768 return mContext == EndState;
769 }
770
771 const QStringList &requirements() const
772 {
773 return mRequirements;
774 }
775
776 int lineStart() const
777 {
778 return mLineStart;
779 }
780
781 int lineEnd() const
782 {
783 return mLineEnd;
784 }
785
786private:
787 void commandStart(const QString &identifier, int lineNumber) override;
788
789 void commandEnd(int lineNumber) override;
790
791 void testStart(const QString &) override
792 {
793 }
794
795 void testEnd() override
796 {
797 }
798
799 void testListStart() override
800 {
801 }
802
803 void testListEnd() override
804 {
805 }
806
807 void blockStart(int lineNumber) override
808 {
809 Q_UNUSED(lineNumber)
810 }
811
812 void blockEnd(int lineNumber) override
813 {
814 Q_UNUSED(lineNumber)
815 }
816
817 void hashComment(const QString &) override
818 {
819 }
820
821 void bracketComment(const QString &) override
822 {
823 }
824
825 void lineFeed() override
826 {
827 }
828
829 void error(const KSieve::Error &e) override;
830 void finished() override;
831
832 void taggedArgument(const QString &tag) override
833 {
834 Q_UNUSED(tag)
835 }
836
837 void numberArgument(unsigned long number, char) override
838 {
839 Q_UNUSED(number)
840 }
841
842 void stringArgument(const QString &string, bool, const QString &) override;
843
844 void stringListArgumentStart() override
845 {
846 }
847
848 void stringListEntry(const QString &string, bool, const QString &) override;
849 void stringListArgumentEnd() override
850 {
851 }
852
853private:
854 Context mContext;
855 QStringList mRequirements;
856 int mLineStart;
857 int mLineEnd;
858};
859}
QDate fromString(QStringView string, QStringView format, QCalendar cal)
QDate date() const const
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
QTime time() const const
qsizetype count() const const
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:09:39 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.