Libksieve

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

KDE's Doxygen guidelines are available online.