File indexing completed on 2025-02-16 04:55:54
0001 /* 0002 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "sieve-vacation.h" 0010 #include "vacationutils.h" 0011 0012 #include "error.h" 0013 #include "parser.h" 0014 #include "scriptbuilder.h" 0015 0016 #include "libksievecore_debug.h" 0017 #include <cassert> 0018 #include <climits> 0019 #include <map> 0020 #include <set> 0021 #include <vector> 0022 0023 namespace KSieveExt 0024 { 0025 class MultiScriptBuilder : public KSieve::ScriptBuilder 0026 { 0027 std::vector<KSieve::ScriptBuilder *> mBuilders; 0028 0029 public: 0030 MultiScriptBuilder() 0031 : KSieve::ScriptBuilder() 0032 { 0033 } 0034 0035 MultiScriptBuilder(KSieve::ScriptBuilder *sb1) 0036 : KSieve::ScriptBuilder() 0037 , mBuilders(1) 0038 { 0039 mBuilders[0] = sb1; 0040 assert(sb1); 0041 } 0042 0043 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2) 0044 : KSieve::ScriptBuilder() 0045 , mBuilders(2) 0046 { 0047 mBuilders[0] = sb1; 0048 mBuilders[1] = sb2; 0049 assert(sb1); 0050 assert(sb2); 0051 } 0052 0053 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2, KSieve::ScriptBuilder *sb3) 0054 : KSieve::ScriptBuilder() 0055 , mBuilders(3) 0056 { 0057 mBuilders[0] = sb1; 0058 mBuilders[1] = sb2; 0059 mBuilders[2] = sb3; 0060 assert(sb1); 0061 assert(sb2); 0062 assert(sb3); 0063 } 0064 0065 MultiScriptBuilder(KSieve::ScriptBuilder *sb1, KSieve::ScriptBuilder *sb2, KSieve::ScriptBuilder *sb3, KSieve::ScriptBuilder *sb4) 0066 : KSieve::ScriptBuilder() 0067 , mBuilders(4) 0068 { 0069 mBuilders[0] = sb1; 0070 mBuilders[1] = sb2; 0071 mBuilders[2] = sb3; 0072 mBuilders[3] = sb4; 0073 assert(sb1); 0074 assert(sb2); 0075 assert(sb3); 0076 assert(sb4); 0077 } 0078 0079 ~MultiScriptBuilder() override = default; 0080 0081 private: 0082 #ifdef FOREACH 0083 #undef FOREACH 0084 #endif 0085 #define FOREACH \ 0086 for (std::vector<KSieve::ScriptBuilder *>::const_iterator it = mBuilders.begin(), end = mBuilders.end(); it != end; ++it) \ 0087 (*it)-> 0088 void commandStart(const QString &identifier, int lineNumber) override 0089 { 0090 FOREACH commandStart(identifier, lineNumber); 0091 } 0092 0093 void commandEnd(int lineNumber) override 0094 { 0095 FOREACH commandEnd(lineNumber); 0096 } 0097 0098 void testStart(const QString &identifier) override 0099 { 0100 FOREACH testStart(identifier); 0101 } 0102 0103 void testEnd() override 0104 { 0105 FOREACH testEnd(); 0106 } 0107 0108 void testListStart() override 0109 { 0110 FOREACH testListStart(); 0111 } 0112 0113 void testListEnd() override 0114 { 0115 FOREACH testListEnd(); 0116 } 0117 0118 void blockStart(int lineNumber) override 0119 { 0120 FOREACH blockStart(lineNumber); 0121 } 0122 0123 void blockEnd(int lineNumber) override 0124 { 0125 FOREACH blockEnd(lineNumber); 0126 } 0127 0128 void hashComment(const QString &comment) override 0129 { 0130 FOREACH hashComment(comment); 0131 } 0132 0133 void bracketComment(const QString &comment) override 0134 { 0135 FOREACH bracketComment(comment); 0136 } 0137 0138 void lineFeed() override 0139 { 0140 FOREACH lineFeed(); 0141 } 0142 0143 void error(const KSieve::Error &e) override 0144 { 0145 FOREACH error(e); 0146 } 0147 0148 void finished() override 0149 { 0150 FOREACH finished(); 0151 } 0152 0153 void taggedArgument(const QString &tag) override 0154 { 0155 FOREACH taggedArgument(tag); 0156 } 0157 0158 void stringArgument(const QString &string, bool multiline, const QString &fixme) override 0159 { 0160 FOREACH stringArgument(string, multiline, fixme); 0161 } 0162 0163 void numberArgument(unsigned long number, char quantifier) override 0164 { 0165 FOREACH numberArgument(number, quantifier); 0166 } 0167 0168 void stringListArgumentStart() override 0169 { 0170 FOREACH stringListArgumentStart(); 0171 } 0172 0173 void stringListEntry(const QString &string, bool multiline, const QString &fixme) override 0174 { 0175 FOREACH stringListEntry(string, multiline, fixme); 0176 } 0177 0178 void stringListArgumentEnd() override 0179 { 0180 FOREACH stringListArgumentEnd(); 0181 } 0182 0183 #undef FOREACH 0184 }; 0185 } 0186 0187 namespace KSieveCore 0188 { 0189 class GenericInformationExtractor : public KSieve::ScriptBuilder 0190 { 0191 public: 0192 enum BuilderMethod { 0193 Any, 0194 TaggedArgument, 0195 StringArgument, 0196 NumberArgument, 0197 CommandStart, 0198 CommandEnd, 0199 TestStart, 0200 TestEnd, 0201 TestListStart, 0202 TestListEnd, 0203 BlockStart, 0204 BlockEnd, 0205 StringListArgumentStart, 0206 StringListEntry, 0207 StringListArgumentEnd 0208 }; 0209 0210 struct StateNode { 0211 // expectation: 0212 int depth; 0213 BuilderMethod method; 0214 const char *string; 0215 // actions: 0216 int if_found; 0217 int if_not_found; 0218 const char *save_tag; 0219 }; 0220 0221 const std::vector<StateNode> mNodes; 0222 std::map<QString, QString> mResults; 0223 std::set<unsigned int> mRecursionGuard; 0224 unsigned int mState; 0225 int mNestingDepth; 0226 0227 int mLineNumber; 0228 0229 public: 0230 GenericInformationExtractor(const std::vector<StateNode> &nodes) 0231 : KSieve::ScriptBuilder() 0232 , mNodes(nodes) 0233 , mState(0) 0234 , mNestingDepth(0) 0235 , mLineNumber(0) 0236 { 0237 } 0238 0239 const std::map<QString, QString> &results() const 0240 { 0241 return mResults; 0242 } 0243 0244 private: 0245 void process(BuilderMethod method, const QString &string = QString()) 0246 { 0247 doProcess(method, string); 0248 mRecursionGuard.clear(); 0249 } 0250 0251 void doProcess(BuilderMethod method, const QString &string) 0252 { 0253 mRecursionGuard.insert(mState); 0254 bool found = true; 0255 const StateNode &expected = mNodes[mState]; 0256 if (expected.depth != -1 && mNestingDepth != expected.depth) { 0257 found = false; 0258 } 0259 if (expected.method != Any && method != expected.method) { 0260 found = false; 0261 } 0262 if (const char *str = expected.string) { 0263 if (string.toLower() != QString::fromUtf8(str).toLower()) { 0264 found = false; 0265 } 0266 } 0267 qCDebug(LIBKSIEVECORE_LOG) << (found ? "found:" : "not found:") << mState << "->" << (found ? expected.if_found : expected.if_not_found); 0268 mState = found ? expected.if_found : expected.if_not_found; 0269 assert(mState < mNodes.size()); 0270 if (found) { 0271 if (const char *save_tag = expected.save_tag) { 0272 mResults[QString::fromLatin1(save_tag)] = string; 0273 } 0274 } 0275 if (!found && !mRecursionGuard.count(mState)) { 0276 doProcess(method, string); 0277 } 0278 } 0279 0280 void commandStart(const QString &identifier, int lineNumber) override 0281 { 0282 Q_UNUSED(lineNumber) 0283 qCDebug(LIBKSIEVECORE_LOG); 0284 process(CommandStart, identifier); 0285 } 0286 0287 void commandEnd(int lineNumber) override 0288 { 0289 Q_UNUSED(lineNumber) 0290 qCDebug(LIBKSIEVECORE_LOG); 0291 process(CommandEnd); 0292 } 0293 0294 void testStart(const QString &identifier) override 0295 { 0296 qCDebug(LIBKSIEVECORE_LOG); 0297 process(TestStart, identifier); 0298 } 0299 0300 void testEnd() override 0301 { 0302 qCDebug(LIBKSIEVECORE_LOG); 0303 process(TestEnd); 0304 } 0305 0306 void testListStart() override 0307 { 0308 qCDebug(LIBKSIEVECORE_LOG); 0309 process(TestListStart); 0310 } 0311 0312 void testListEnd() override 0313 { 0314 qCDebug(LIBKSIEVECORE_LOG); 0315 process(TestListEnd); 0316 } 0317 0318 void blockStart(int lineNumber) override 0319 { 0320 Q_UNUSED(lineNumber) 0321 qCDebug(LIBKSIEVECORE_LOG); 0322 process(BlockStart); 0323 ++mNestingDepth; 0324 } 0325 0326 void blockEnd(int lineNumber) override 0327 { 0328 Q_UNUSED(lineNumber) 0329 qCDebug(LIBKSIEVECORE_LOG); 0330 --mNestingDepth; 0331 process(BlockEnd); 0332 } 0333 0334 void hashComment(const QString &) override 0335 { 0336 qCDebug(LIBKSIEVECORE_LOG); 0337 } 0338 0339 void bracketComment(const QString &) override 0340 { 0341 qCDebug(LIBKSIEVECORE_LOG); 0342 } 0343 0344 void lineFeed() override 0345 { 0346 qCDebug(LIBKSIEVECORE_LOG); 0347 } 0348 0349 void error(const KSieve::Error &) override 0350 { 0351 qCDebug(LIBKSIEVECORE_LOG); 0352 mState = 0; 0353 } 0354 0355 void finished() override 0356 { 0357 qCDebug(LIBKSIEVECORE_LOG); 0358 } 0359 0360 void taggedArgument(const QString &tag) override 0361 { 0362 qCDebug(LIBKSIEVECORE_LOG); 0363 process(TaggedArgument, tag); 0364 } 0365 0366 void stringArgument(const QString &string, bool, const QString &) override 0367 { 0368 qCDebug(LIBKSIEVECORE_LOG); 0369 process(StringArgument, string); 0370 } 0371 0372 void numberArgument(unsigned long number, char) override 0373 { 0374 qCDebug(LIBKSIEVECORE_LOG); 0375 process(NumberArgument, QString::number(number)); 0376 } 0377 0378 void stringListArgumentStart() override 0379 { 0380 qCDebug(LIBKSIEVECORE_LOG); 0381 process(StringListArgumentStart); 0382 } 0383 0384 void stringListEntry(const QString &string, bool, const QString &) override 0385 { 0386 qCDebug(LIBKSIEVECORE_LOG); 0387 process(StringListEntry, string); 0388 } 0389 0390 void stringListArgumentEnd() override 0391 { 0392 qCDebug(LIBKSIEVECORE_LOG); 0393 process(StringListArgumentEnd); 0394 } 0395 }; 0396 0397 using GIE = GenericInformationExtractor; 0398 static const GenericInformationExtractor::StateNode spamNodes[] = { 0399 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0 0400 {0, GIE::TestStart, "allof", 2, 3, nullptr}, // 1 0401 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2 0402 {0, GIE::TestStart, "not", 4, 3, nullptr}, // 3 0403 {0, GIE::TestStart, "header", 5, 3, nullptr}, // 4 0404 {0, GIE::TaggedArgument, "contains", 6, 0, nullptr}, // 5 0405 0406 // accept both string and string-list: 0407 {0, GIE::StringArgument, "x-spam-flag", 12, 7, "x-spam-flag"}, // 6 0408 {0, GIE::StringListArgumentStart, nullptr, 8, 0, nullptr}, // 7 0409 {0, GIE::StringListEntry, "x-spam-flag", 9, 10, "x-spam-flag"}, // 8 0410 {0, GIE::StringListEntry, nullptr, 9, 11, nullptr}, // 9 0411 {0, GIE::StringListArgumentEnd, nullptr, 0, 8, nullptr}, // 10 0412 {0, GIE::StringListArgumentEnd, nullptr, 12, 0, nullptr}, // 11 0413 0414 // accept both string and string-list: 0415 {0, GIE::StringArgument, "yes", 18, 13, "spam-flag-yes"}, // 12 0416 {0, GIE::StringListArgumentStart, nullptr, 14, 0, nullptr}, // 13 0417 {0, GIE::StringListEntry, "yes", 15, 16, "spam-flag-yes"}, // 14 0418 {0, GIE::StringListEntry, nullptr, 15, 17, nullptr}, // 15 0419 {0, GIE::StringListArgumentEnd, nullptr, 0, 14, nullptr}, // 16 0420 {0, GIE::StringListArgumentEnd, nullptr, 18, 0, nullptr}, // 17 0421 0422 {0, GIE::TestEnd, nullptr, 21, 20, nullptr}, // 18 0423 {0, GIE::Any, nullptr, 21, 0, nullptr}, // 19 0424 {0, GIE::TestListEnd, nullptr, 21, 19, nullptr}, // 20 0425 0426 // block of command, find "stop", take nested if's into account: 0427 {0, GIE::BlockStart, nullptr, 22, 18, nullptr}, // 21 0428 {1, GIE::CommandStart, "vacation", 24, 22, "vacation"}, // 22 0429 {1, GIE::Any, nullptr, 24, 0, nullptr}, // 23 0430 {0, GIE::BlockEnd, nullptr, 25, 23, nullptr}, // 24 0431 0432 {-1, GIE::Any, nullptr, 25, 25, nullptr}, // 25 end state 0433 }; 0434 static const unsigned int numSpamNodes = sizeof spamNodes / sizeof *spamNodes; 0435 0436 class SpamDataExtractor : public GenericInformationExtractor 0437 { 0438 public: 0439 SpamDataExtractor() 0440 : GenericInformationExtractor(std::vector<StateNode>(spamNodes, spamNodes + numSpamNodes)) 0441 { 0442 } 0443 0444 bool found() const 0445 { 0446 return mResults.count(QStringLiteral("x-spam-flag")) && mResults.count(QStringLiteral("spam-flag-yes")) && mResults.count(QStringLiteral("vacation")); 0447 } 0448 }; 0449 0450 // to understand this table, study the output of 0451 // libksieve/tests/parsertest 0452 // 'if not address :domain :contains ["from"] ["mydomain.org"] { keep; stop; }' 0453 static const GenericInformationExtractor::StateNode domainNodes[] = { 0454 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0 0455 {0, GIE::TestStart, "allof", 2, 3, nullptr}, // 1 0456 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2 0457 {0, GIE::TestStart, "address", 4, 3, nullptr}, // 3 0458 0459 // :domain and :contains in arbitrary order: 0460 {0, GIE::TaggedArgument, "domain", 5, 6, nullptr}, // 4 0461 {0, GIE::TaggedArgument, "contains", 8, 0, nullptr}, // 5 0462 {0, GIE::TaggedArgument, "contains", 7, 0, nullptr}, // 6 0463 {0, GIE::TaggedArgument, "domain", 8, 0, nullptr}, // 7 0464 0465 // accept both string and string-list: 0466 {0, GIE::StringArgument, "from", 14, 9, "from"}, // 8 0467 {0, GIE::StringListArgumentStart, nullptr, 10, 0, nullptr}, // 9 0468 {0, GIE::StringListEntry, "from", 11, 12, "from"}, // 10 0469 {0, GIE::StringListEntry, nullptr, 11, 13, nullptr}, // 11 0470 {0, GIE::StringListArgumentEnd, nullptr, 0, 10, nullptr}, // 12 0471 {0, GIE::StringListArgumentEnd, nullptr, 14, 0, nullptr}, // 13 0472 0473 // string: save, string-list: save last 0474 {0, GIE::StringArgument, nullptr, 18, 15, "domainName"}, // 14 0475 {0, GIE::StringListArgumentStart, nullptr, 16, 0, nullptr}, // 15 0476 {0, GIE::StringListEntry, nullptr, 16, 17, "domainName"}, // 16 0477 {0, GIE::StringListArgumentEnd, nullptr, 18, 0, nullptr}, // 17 0478 0479 {0, GIE::TestEnd, nullptr, 18, 20, nullptr}, // 18 0480 {0, GIE::Any, nullptr, 18, 0, nullptr}, // 19 0481 0482 // block of commands, find "stop", take nested if's into account: 0483 {0, GIE::BlockStart, nullptr, 21, 19, nullptr}, // 20 0484 {1, GIE::CommandStart, "vacation", 23, 21, "vacation"}, // 21 0485 {1, GIE::Any, nullptr, 23, 0, nullptr}, // 22 0486 {0, GIE::BlockEnd, nullptr, 24, 22, nullptr}, // 23 0487 0488 {-1, GIE::Any, nullptr, 24, 24, nullptr} // 24 end state 0489 }; 0490 static const unsigned int numDomainNodes = sizeof domainNodes / sizeof *domainNodes; 0491 0492 class DomainRestrictionDataExtractor : public GenericInformationExtractor 0493 { 0494 public: 0495 DomainRestrictionDataExtractor() 0496 : GenericInformationExtractor(std::vector<StateNode>(domainNodes, domainNodes + numDomainNodes)) 0497 { 0498 } 0499 0500 QString domainName() /*not const, since map::op[] isn't const*/ 0501 { 0502 return mResults.count(QStringLiteral("vacation")) && mResults.count(QStringLiteral("from")) ? mResults[QStringLiteral("domainName")] : QString(); 0503 } 0504 }; 0505 0506 // if not allof (currentdate :value "ge" date "YYYY-MM-DD", 0507 // currentfate :value "le" date "YYYY-MM-DD) { keep; stop; } 0508 static const GenericInformationExtractor::StateNode datesNodes[] = { 0509 {0, GIE::CommandStart, "if", 1, 0, nullptr}, // 0 0510 {0, GIE::TestStart, "allof", 2, 0, nullptr}, // 1 0511 0512 // handle startDate and endDate in arbitrary order 0513 {0, GIE::TestListStart, nullptr, 3, 0, nullptr}, // 2 0514 {0, GIE::TestStart, "currentdate", 4, 3, nullptr}, // 3 0515 {0, GIE::TaggedArgument, "value", 5, 4, nullptr}, // 4 0516 {0, GIE::StringArgument, "ge", 6, 10, nullptr}, // 5 0517 {0, GIE::StringArgument, "date", 7, 8, nullptr}, // 6 0518 {0, GIE::StringArgument, nullptr, 15, 0, "startDate"}, // 7 0519 {0, GIE::StringArgument, "iso8601", 9, 0, nullptr}, // 8 0520 {0, GIE::StringArgument, nullptr, 15, 0, "startDateTime"}, // 9 0521 {0, GIE::StringArgument, "le", 11, 0, nullptr}, // 10 0522 {0, GIE::StringArgument, "date", 12, 13, nullptr}, // 11 0523 {0, GIE::StringArgument, nullptr, 15, 0, "endDate"}, // 12 0524 {0, GIE::StringArgument, "iso8601", 14, 0, nullptr}, // 13 0525 {0, GIE::StringArgument, nullptr, 15, 0, "endDateTime"}, // 14 0526 {0, GIE::TestEnd, nullptr, 16, 0, nullptr}, // 15 0527 0528 {0, GIE::TestStart, "currentdate", 17, 16, nullptr}, // 16 0529 {0, GIE::TaggedArgument, "value", 18, 17, nullptr}, // 17 0530 {0, GIE::StringArgument, "le", 19, 23, nullptr}, // 18 0531 {0, GIE::StringArgument, "date", 20, 21, nullptr}, // 19 0532 {0, GIE::StringArgument, nullptr, 28, 0, "endDate"}, // 20 0533 {0, GIE::StringArgument, "iso8601", 22, 0, nullptr}, // 21 0534 {0, GIE::StringArgument, nullptr, 28, 0, "endDateTime"}, // 22 0535 {0, GIE::StringArgument, "ge", 24, 0, nullptr}, // 23 0536 {0, GIE::StringArgument, "date", 25, 26, nullptr}, // 24 0537 {0, GIE::StringArgument, nullptr, 28, 0, "startDate"}, // 25 0538 {0, GIE::StringArgument, "iso8601", 27, 0, nullptr}, // 26 0539 {0, GIE::StringArgument, nullptr, 28, 0, "startDateTime"}, // 27 0540 {0, GIE::TestEnd, nullptr, 32, 0, nullptr}, // 28 0541 {0, GIE::TestStart, nullptr, 31, 30, nullptr}, // 29 0542 {-1, GIE::Any, nullptr, 32, 0, nullptr}, // 30 0543 {0, GIE::TestEnd, nullptr, 32, 30, nullptr}, // 31 0544 {0, GIE::TestListEnd, nullptr, 33, 29, nullptr}, // 32 0545 0546 {0, GIE::TestEnd, nullptr, 34, 0, nullptr}, // 33 0547 0548 // block of commands, find "stop", take nested if's into account: 0549 {0, GIE::BlockStart, nullptr, 36, 33, nullptr}, // 34 0550 {-1, GIE::Any, nullptr, 36, 0, nullptr}, // 35 0551 {1, GIE::CommandStart, "vacation", 38, 35, "vacation"}, // 36 0552 {-1, GIE::Any, nullptr, 38, 0, nullptr}, // 37 0553 {0, GIE::BlockEnd, nullptr, 39, 37, nullptr}, // 38 0554 0555 {-1, GIE::Any, nullptr, 39, 39, nullptr} // 39 end state 0556 }; 0557 0558 static const unsigned int numDatesNodes = sizeof datesNodes / sizeof *datesNodes; 0559 0560 class DateExtractor : public GenericInformationExtractor 0561 { 0562 public: 0563 DateExtractor() 0564 : GenericInformationExtractor(std::vector<StateNode>(datesNodes, datesNodes + numDatesNodes)) 0565 { 0566 } 0567 0568 QDate endDate() const 0569 { 0570 if (results().count(QStringLiteral("endDateTime")) == 1) { 0571 return datetime(QStringLiteral("endDateTime")).date(); 0572 } else { 0573 return date(QStringLiteral("endDate")); 0574 } 0575 } 0576 0577 QDate startDate() const 0578 { 0579 if (results().count(QStringLiteral("startDateTime")) == 1) { 0580 return datetime(QStringLiteral("startDateTime")).date(); 0581 } else { 0582 return date(QStringLiteral("startDate")); 0583 } 0584 } 0585 0586 QTime endTime() const 0587 { 0588 return datetime(QStringLiteral("endDateTime")).time(); 0589 } 0590 0591 QTime startTime() const 0592 { 0593 return datetime(QStringLiteral("startDateTime")).time(); 0594 } 0595 0596 private: 0597 QDate date(const QString &name) const 0598 { 0599 if (results().count(name) == 0) { 0600 return {}; 0601 } else { 0602 return QDate::fromString(results().at(name), Qt::ISODate); 0603 } 0604 } 0605 0606 QDateTime datetime(const QString &name) const 0607 { 0608 if (results().count(name) == 0) { 0609 return {}; 0610 } else { 0611 return QDateTime::fromString(results().at(name), Qt::ISODate); 0612 } 0613 } 0614 }; 0615 0616 class VacationDataExtractor : public KSieve::ScriptBuilder 0617 { 0618 enum Context { 0619 None = 0, 0620 // command itself: 0621 VacationCommand, 0622 // tagged args: 0623 Days, 0624 Addresses, 0625 Subject, 0626 VacationEnd, 0627 IfBlock, 0628 RedirectCommand 0629 }; 0630 0631 public: 0632 VacationDataExtractor(); 0633 ~VacationDataExtractor() override; 0634 0635 bool commandFound() const 0636 { 0637 return mContext == VacationEnd; 0638 } 0639 0640 bool active() const 0641 { 0642 return mActive; 0643 } 0644 0645 int notificationInterval() const 0646 { 0647 return mNotificationInterval; 0648 } 0649 0650 const QString &messageText() const 0651 { 0652 return mMessageText; 0653 } 0654 0655 const QStringList &aliases() const 0656 { 0657 return mAliases; 0658 } 0659 0660 const QString &ifComment() const 0661 { 0662 return mIfComment; 0663 } 0664 0665 VacationUtils::MailAction mailAction() const 0666 { 0667 return mMailAction; 0668 } 0669 0670 const QString &mailActionRecipient() const 0671 { 0672 return mMailActionRecipient; 0673 } 0674 0675 const QString &subject() const 0676 { 0677 return mSubject; 0678 } 0679 0680 int lineStart() const 0681 { 0682 return mLineStart; 0683 } 0684 0685 int lineEnd() const 0686 { 0687 return mLineEnd; 0688 } 0689 0690 private: 0691 void commandStart(const QString &identifier, int lineNumber) override; 0692 0693 void commandEnd(int lineNumber) override; 0694 0695 void testStart(const QString &) override; 0696 void testEnd() override 0697 { 0698 } 0699 0700 void testListStart() override 0701 { 0702 } 0703 0704 void testListEnd() override 0705 { 0706 } 0707 0708 void blockStart(int lineNumber) override; 0709 void blockEnd(int lineNumber) override; 0710 void hashComment(const QString &) override; 0711 void bracketComment(const QString &) override 0712 { 0713 } 0714 0715 void lineFeed() override 0716 { 0717 } 0718 0719 void error(const KSieve::Error &e) override; 0720 void finished() override; 0721 0722 void taggedArgument(const QString &tag) override; 0723 0724 void stringArgument(const QString &string, bool, const QString &) override; 0725 0726 void numberArgument(unsigned long number, char) override; 0727 0728 void stringListArgumentStart() override; 0729 void stringListEntry(const QString &string, bool, const QString &) override; 0730 void stringListArgumentEnd() override; 0731 0732 private: 0733 Context mContext = None; 0734 int mNotificationInterval = 0; 0735 QString mMessageText; 0736 QString mSubject; 0737 QStringList mAliases; 0738 bool mActive = true; 0739 bool mInIfBlock = false; 0740 bool mFoundInBlock = false; 0741 int mBlockLevel = 0; 0742 QString mIfComment; 0743 int mLineStart = 0; 0744 int mLineEnd = 0; 0745 0746 VacationUtils::MailAction mMailAction = VacationUtils::Keep; 0747 Context mMailActionContext = None; 0748 QString mMailActionRecipient; 0749 0750 void reset(); 0751 }; 0752 0753 class RequireExtractor : public KSieve::ScriptBuilder 0754 { 0755 enum Context { 0756 None = 0, 0757 // command itself: 0758 RequireCommand, 0759 EndState 0760 }; 0761 0762 public: 0763 RequireExtractor(); 0764 ~RequireExtractor() override; 0765 0766 bool commandFound() const 0767 { 0768 return mContext == EndState; 0769 } 0770 0771 const QStringList &requirements() const 0772 { 0773 return mRequirements; 0774 } 0775 0776 int lineStart() const 0777 { 0778 return mLineStart; 0779 } 0780 0781 int lineEnd() const 0782 { 0783 return mLineEnd; 0784 } 0785 0786 private: 0787 void commandStart(const QString &identifier, int lineNumber) override; 0788 0789 void commandEnd(int lineNumber) override; 0790 0791 void testStart(const QString &) override 0792 { 0793 } 0794 0795 void testEnd() override 0796 { 0797 } 0798 0799 void testListStart() override 0800 { 0801 } 0802 0803 void testListEnd() override 0804 { 0805 } 0806 0807 void blockStart(int lineNumber) override 0808 { 0809 Q_UNUSED(lineNumber) 0810 } 0811 0812 void blockEnd(int lineNumber) override 0813 { 0814 Q_UNUSED(lineNumber) 0815 } 0816 0817 void hashComment(const QString &) override 0818 { 0819 } 0820 0821 void bracketComment(const QString &) override 0822 { 0823 } 0824 0825 void lineFeed() override 0826 { 0827 } 0828 0829 void error(const KSieve::Error &e) override; 0830 void finished() override; 0831 0832 void taggedArgument(const QString &tag) override 0833 { 0834 Q_UNUSED(tag) 0835 } 0836 0837 void numberArgument(unsigned long number, char) override 0838 { 0839 Q_UNUSED(number) 0840 } 0841 0842 void stringArgument(const QString &string, bool, const QString &) override; 0843 0844 void stringListArgumentStart() override 0845 { 0846 } 0847 0848 void stringListEntry(const QString &string, bool, const QString &) override; 0849 void stringListArgumentEnd() override 0850 { 0851 } 0852 0853 private: 0854 Context mContext; 0855 QStringList mRequirements; 0856 int mLineStart; 0857 int mLineEnd; 0858 }; 0859 }