Libksieve

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

KDE's Doxygen guidelines are available online.