diff --git a/libksieve/src/ksieveui/CMakeLists.txt b/libksieve/src/ksieveui/CMakeLists.txt --- a/libksieve/src/ksieveui/CMakeLists.txt +++ b/libksieve/src/ksieveui/CMakeLists.txt @@ -36,6 +36,8 @@ vacation/vacationcheckjob.cpp vacation/multiimapvacationmanager.cpp vacation/vacationmanager.cpp + vacation/legacy/vacationutils.cpp + vacation/legacy/vacationscriptextractor.cpp ) set(ksieveui_editor_LIB_SRCS diff --git a/libksieve/src/ksieveui/vacation/autotests/CMakeLists.txt b/libksieve/src/ksieveui/vacation/autotests/CMakeLists.txt --- a/libksieve/src/ksieveui/vacation/autotests/CMakeLists.txt +++ b/libksieve/src/ksieveui/vacation/autotests/CMakeLists.txt @@ -6,6 +6,8 @@ macro( add_vacation_test _source ) set( _test ${_source}test.cpp ../${_source}.cpp + ../legacy/vacationutils.cpp + ../legacy/vacationscriptextractor.cpp ../vacationscriptextractor.cpp ${CMAKE_BINARY_DIR}/libksieve/src/ksieveui/sieve-vacation.cpp ) diff --git a/libksieve/src/ksieveui/vacation/autotests/data/vacation-deactivate-complex-old.siv b/libksieve/src/ksieveui/vacation/autotests/data/vacation-deactivate-complex-old.siv new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/autotests/data/vacation-deactivate-complex-old.siv @@ -0,0 +1,8 @@ +require ["date","relational","vacation"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if false # allof (currentdate :zone "+0100" :value "ge" "date" "2015-01-02", currentdate :zone "+0100" :value "le" "date" "2015-03-04", not header :contains "X-Spam-Flag" "YES", address :domain :contains "from" "example.org") +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; +} \ No newline at end of file diff --git a/libksieve/src/ksieveui/vacation/autotests/data/vacation-old.siv b/libksieve/src/ksieveui/vacation/autotests/data/vacation-old.siv new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/autotests/data/vacation-old.siv @@ -0,0 +1,11 @@ +require "vacation"; +require "relational"; +require "date"; + +if header :contains "X-Spam-Flag" "YES" { keep; stop; } +if not address :domain :contains "from" "example.org" { keep; stop; } +if not allof(currentdate :value "ge" "date" "2015-01-02", currentdate :value "le" "date" "2015-03-04") { keep; stop; } +vacation :addresses [ "test@test.de" ] :days 7 :subject "XXX" text: +dsfgsdfgsdfg +. +; diff --git a/libksieve/src/ksieveui/vacation/autotests/vacationutilstest.cpp b/libksieve/src/ksieveui/vacation/autotests/vacationutilstest.cpp --- a/libksieve/src/ksieveui/vacation/autotests/vacationutilstest.cpp +++ b/libksieve/src/ksieveui/vacation/autotests/vacationutilstest.cpp @@ -19,6 +19,7 @@ #include "vacationutilstest.h" #include "ksieveui/vacation/vacationutils.h" +#include "ksieveui/vacation/legacy/vacationutils.h" #include @@ -73,6 +74,7 @@ QTest::newRow("deactivate") << QStringLiteral("vacation-deactivate.siv") << true << false; QTest::newRow("deactivate-multiple if") << QStringLiteral("vacation-deactivate-multiple.siv") << true << false; QTest::newRow("deactivate-complex") << QStringLiteral("vacation-deactivate-complex.siv") << true << false; + QTest::newRow("old") << QStringLiteral("vacation-old.siv") << true << true; } void VacationUtilsTest::testParseActivate() @@ -97,6 +99,7 @@ QTest::newRow("simple") << QStringLiteral("vacation-simple.siv") << QStringLiteral("vacation-deactivate.siv"); QTest::newRow("complex") << QStringLiteral("vacation-complex.siv") << QStringLiteral("vacation-deactivate-complex.siv"); + QTest::newRow("old") << QStringLiteral("vacation-old.siv") << QStringLiteral("vacation-deactivate-complex-old.siv"); } void VacationUtilsTest::testParseScript() diff --git a/libksieve/src/ksieveui/vacation/legacy/README b/libksieve/src/ksieveui/vacation/legacy/README new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/legacy/README @@ -0,0 +1,5 @@ +This is a legacy code to read/write the old vacation scripts for KDE 4 version of kontact. +If once this new version is rolled out, there is no need to keep the legacy way of read/write the vacation script, +because it is not compatible to any other system. The only need to keep this code is for migration old vacation scripts to new one. + +23. October 2015 - Sndro Knauß diff --git a/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.h b/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.h new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.h @@ -0,0 +1,334 @@ +/* + Copyright (c) 2013-2015 Montel Laurent + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef LEGACY_VACATIONSCRIPTEXTRACTOR_H +#define LEGACY_VACATIONSCRIPTEXTRACTOR_H + +#include "sieve-vacation.h" +#include "../vacationscriptextractor.h" +#include "util/util.h" + +#include +#include +#include +#include + +#include "libksieve_debug.h" +#include +#include +#include +#include +#include + +namespace KSieveUi +{ +namespace Legacy +{ + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +static const GenericInformationExtractor::StateNode spamNodes[] = { + { 0, GIE::CommandStart, "if", 1, 0, Q_NULLPTR }, // 0 + { 0, GIE::TestStart, "header", 2, 0, Q_NULLPTR }, // 1 + { 0, GIE::TaggedArgument, "contains", 3, 0, Q_NULLPTR }, // 2 + + // accept both string and string-list: + { 0, GIE::StringArgument, "x-spam-flag", 9, 4, "x-spam-flag" }, // 3 + { 0, GIE::StringListArgumentStart, Q_NULLPTR, 5, 0, Q_NULLPTR }, // 4 + { 0, GIE::StringListEntry, "x-spam-flag", 6, 7, "x-spam-flag" }, // 5 + { 0, GIE::StringListEntry, Q_NULLPTR, 6, 8, Q_NULLPTR }, // 6 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 0, 5, Q_NULLPTR }, // 7 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 9, 0, Q_NULLPTR }, // 8 + + // accept both string and string-list: + { 0, GIE::StringArgument, "yes", 15, 10, "spam-flag-yes" }, // 9 + { 0, GIE::StringListArgumentStart, Q_NULLPTR, 11, 0, Q_NULLPTR }, // 10 + { 0, GIE::StringListEntry, "yes", 12, 13, "spam-flag-yes" }, // 11 + { 0, GIE::StringListEntry, Q_NULLPTR, 12, 14, Q_NULLPTR }, // 12 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 0, 11, Q_NULLPTR }, // 13 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 15, 0, Q_NULLPTR }, // 14 + + { 0, GIE::TestEnd, Q_NULLPTR, 16, 0, Q_NULLPTR }, // 15 + + // block of command, find "stop", take nested if's into account: + { 0, GIE::BlockStart, Q_NULLPTR, 17, 0, Q_NULLPTR }, // 16 + { 1, GIE::CommandStart, "stop", 20, 19, "stop" }, // 17 + { -1, GIE::Any, Q_NULLPTR, 17, 0, Q_NULLPTR }, // 18 + { 0, GIE::BlockEnd, Q_NULLPTR, 0, 18, Q_NULLPTR }, // 19 + + { -1, GIE::Any, Q_NULLPTR, 20, 20, Q_NULLPTR }, // 20 end state +}; +static const unsigned int numSpamNodes = sizeof spamNodes / sizeof * spamNodes; + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +class __attribute__ ((__deprecated__)) SpamDataExtractor : public GenericInformationExtractor +{ +public: + SpamDataExtractor() + : GenericInformationExtractor(std::vector(spamNodes, spamNodes + numSpamNodes)) + { + + } + + bool found() const + { + return mResults.count(QStringLiteral("x-spam-flag")) && + mResults.count(QStringLiteral("spam-flag-yes")) && + mResults.count(QStringLiteral("stop")); + } +}; + +// to understand this table, study the output of +// libksieve/tests/parsertest +// 'if not address :domain :contains ["from"] ["mydomain.org"] { keep; stop; }' +static const GenericInformationExtractor::StateNode domainNodes[] = { + { 0, GIE::CommandStart, "if", 1, 0, Q_NULLPTR }, // 0 + { 0, GIE::TestStart, "not", 2, 0, Q_NULLPTR, }, // 1 + { 0, GIE::TestStart, "address", 3, 0, Q_NULLPTR }, // 2 + + // :domain and :contains in arbitrary order: + { 0, GIE::TaggedArgument, "domain", 4, 5, Q_NULLPTR }, // 3 + { 0, GIE::TaggedArgument, "contains", 7, 0, Q_NULLPTR }, // 4 + { 0, GIE::TaggedArgument, "contains", 6, 0, Q_NULLPTR }, // 5 + { 0, GIE::TaggedArgument, "domain", 7, 0, Q_NULLPTR }, // 6 + + // accept both string and string-list: + { 0, GIE::StringArgument, "from", 13, 8, "from" }, // 7 + { 0, GIE::StringListArgumentStart, Q_NULLPTR, 9, 0, Q_NULLPTR }, // 8 + { 0, GIE::StringListEntry, "from", 10, 11, "from" }, // 9 + { 0, GIE::StringListEntry, Q_NULLPTR, 10, 12, Q_NULLPTR }, // 10 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 0, 9, Q_NULLPTR }, // 11 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 13, 0, Q_NULLPTR }, // 12 + + // string: save, string-list: save last + { 0, GIE::StringArgument, Q_NULLPTR, 17, 14, "domainName" }, // 13 + { 0, GIE::StringListArgumentStart, Q_NULLPTR, 15, 0, Q_NULLPTR }, // 14 + { 0, GIE::StringListEntry, Q_NULLPTR, 15, 16, "domainName" }, // 15 + { 0, GIE::StringListArgumentEnd, Q_NULLPTR, 17, 0, Q_NULLPTR }, // 16 + + { 0, GIE::TestEnd, Q_NULLPTR, 18, 0, Q_NULLPTR }, // 17 + { 0, GIE::TestEnd, Q_NULLPTR, 19, 0, Q_NULLPTR }, // 18 + + // block of commands, find "stop", take nested if's into account: + { 0, GIE::BlockStart, Q_NULLPTR, 20, 0, Q_NULLPTR }, // 19 + { 1, GIE::CommandStart, "stop", 23, 22, "stop" }, // 20 + { -1, GIE::Any, Q_NULLPTR, 20, 0, Q_NULLPTR }, // 21 + { 0, GIE::BlockEnd, Q_NULLPTR, 0, 21, Q_NULLPTR }, // 22 + + { -1, GIE::Any, Q_NULLPTR, 23, 23, Q_NULLPTR } // 23 end state +}; +static const unsigned int numDomainNodes = sizeof domainNodes / sizeof * domainNodes; + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +class __attribute__ ((__deprecated__)) DomainRestrictionDataExtractor : public GenericInformationExtractor +{ +public: + DomainRestrictionDataExtractor() + : GenericInformationExtractor(std::vector(domainNodes, domainNodes + numDomainNodes)) + { + + } + + QString domainName() /*not const, since map::op[] isn't const*/ + { + return mResults.count(QStringLiteral("stop")) && mResults.count(QStringLiteral("from")) + ? mResults[QStringLiteral("domainName")] : QString(); + } +}; + +// if not allof (currentDate :value "ge" date "YYYY-MM-DD", +// currentDate :value "le" date "YYYY-MM-DD") { keep; stop; } +static const GenericInformationExtractor::StateNode datesNodes[] = { + { 0, GIE::CommandStart, "if", 1, 0, Q_NULLPTR }, // 0 + { 0, GIE::TestStart, "not", 2, 0, Q_NULLPTR }, // 1 + { 0, GIE::TestStart, "allof", 3, 0, Q_NULLPTR }, // 2 + + // handle startDate and endDate in arbitrary order + { 0, GIE::TestListStart, Q_NULLPTR, 4, 0, Q_NULLPTR }, // 3 + { 0, GIE::TestStart, "currentdate", 5, 0, Q_NULLPTR }, // 4 + { 0, GIE::TaggedArgument, "value", 6, 0, Q_NULLPTR }, // 5 + { 0, GIE::StringArgument, "ge", 7, 9, Q_NULLPTR }, // 6 + { 0, GIE::StringArgument, "date", 8, 0, Q_NULLPTR }, // 7 + { 0, GIE::StringArgument, Q_NULLPTR, 12, 0, "startDate" }, // 8 + { 0, GIE::StringArgument, "le", 10, 0, Q_NULLPTR }, // 9 + { 0, GIE::StringArgument, "date", 11, 0, Q_NULLPTR }, // 10 + { 0, GIE::StringArgument, Q_NULLPTR, 12, 0, "endDate" }, // 11 + { 0, GIE::TestEnd, Q_NULLPTR, 13, 0, Q_NULLPTR }, // 12 + + { 0, GIE::TestStart, "currentdate", 14, 0, Q_NULLPTR }, // 13 + { 0, GIE::TaggedArgument, "value", 15, 0, Q_NULLPTR }, // 14 + { 0, GIE::StringArgument, "le", 16, 18, Q_NULLPTR }, // 15 + { 0, GIE::StringArgument, "date", 17, 0, Q_NULLPTR }, // 16 + { 0, GIE::StringArgument, Q_NULLPTR, 21, 0, "endDate" }, // 17 + { 0, GIE::StringArgument, "ge", 19, 0, Q_NULLPTR }, // 18 + { 0, GIE::StringArgument, "date", 20, 0, Q_NULLPTR }, // 19 + { 0, GIE::StringArgument, Q_NULLPTR, 21, 0, "startDate" }, // 20 + { 0, GIE::TestEnd, Q_NULLPTR, 22, 0, Q_NULLPTR }, // 21 + { 0, GIE::TestListEnd, Q_NULLPTR, 23, 0, Q_NULLPTR }, // 22 + + { 0, GIE::TestEnd, Q_NULLPTR, 24, 0, Q_NULLPTR }, // 23 + { 0, GIE::TestEnd, Q_NULLPTR, 25, 0, Q_NULLPTR }, // 24 + + // block of commands, find "stop", take nested if's into account: + { 0, GIE::BlockStart, Q_NULLPTR, 26, 0, Q_NULLPTR }, // 25 + { 1, GIE::CommandStart, "stop", 29, 28, "stop" }, // 26 + { -1, GIE::Any, Q_NULLPTR, 26, 0, Q_NULLPTR }, // 27 + { 0, GIE::BlockEnd, Q_NULLPTR, 0, 27, Q_NULLPTR }, // 28 + + { -1, GIE::Any, Q_NULLPTR, 27, 27, Q_NULLPTR } // 29 end state +}; + +static const unsigned int numDatesNodes = sizeof datesNodes / sizeof * datesNodes; + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +class __attribute__ ((__deprecated__)) DateExtractor : public GenericInformationExtractor +{ +public: + DateExtractor() + : GenericInformationExtractor(std::vector(datesNodes, datesNodes + numDatesNodes)) + { + } + + QDate endDate() const + { + return date(QStringLiteral("endDate")); + } + + QDate startDate() const + { + return date(QStringLiteral("startDate")); + } + +private: + QDate date(const QString &name) const + { + if (mResults.count(name) == 0) { + return QDate(); + } else { + return QDate::fromString(mResults.at(name), Qt::ISODate); + } + } +}; + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +class __attribute__ ((__deprecated__)) VacationDataExtractor : public KSieve::ScriptBuilder +{ + enum Context { + None = 0, + // command itself: + VacationCommand, + // tagged args: + Days, Addresses, Subject, + VacationEnd + }; +public: + VacationDataExtractor(); + virtual ~VacationDataExtractor(); + bool commandFound() const + { + return mContext == VacationEnd; + } + int notificationInterval() const + { + return mNotificationInterval; + } + const QString &messageText() const + { + return mMessageText; + } + const QStringList &aliases() const + { + return mAliases; + } + + const QString &subject() const + { + return mSubject; + } + +private: + void commandStart(const QString &identifier, int lineNumber) Q_DECL_OVERRIDE; + + void commandEnd(int lineNumber) Q_DECL_OVERRIDE; + + void testStart(const QString &) Q_DECL_OVERRIDE {} + void testEnd() Q_DECL_OVERRIDE {} + void testListStart() Q_DECL_OVERRIDE {} + void testListEnd() Q_DECL_OVERRIDE {} + void blockStart(int lineNumber) Q_DECL_OVERRIDE + { + Q_UNUSED(lineNumber) + + } + void blockEnd(int lineNumber) Q_DECL_OVERRIDE + { + Q_UNUSED(lineNumber) + } + void hashComment(const QString &) Q_DECL_OVERRIDE {} + void bracketComment(const QString &) Q_DECL_OVERRIDE {} + void lineFeed() Q_DECL_OVERRIDE {} + void error(const KSieve::Error &e) Q_DECL_OVERRIDE; + void finished() Q_DECL_OVERRIDE; + + void taggedArgument(const QString &tag) Q_DECL_OVERRIDE; + + void stringArgument(const QString &string, bool, const QString &) Q_DECL_OVERRIDE; + + void numberArgument(unsigned long number, char) Q_DECL_OVERRIDE; + + void stringListArgumentStart() Q_DECL_OVERRIDE; + void stringListEntry(const QString &string, bool, const QString &) Q_DECL_OVERRIDE; + void stringListArgumentEnd() Q_DECL_OVERRIDE; + +private: + Context mContext; + int mNotificationInterval; + QString mMessageText; + QString mSubject; + QStringList mAliases; + + void reset(); +}; +} +} + +#endif // LEGACY_VACATIONSCRIPTEXTRACTOR_H diff --git a/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.cpp b/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.cpp new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/legacy/vacationscriptextractor.cpp @@ -0,0 +1,139 @@ +/* + Copyright (c) 2013-2015 Montel Laurent + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "vacationscriptextractor.h" + +using namespace KSieveUi::Legacy; +KSieveUi::Legacy::VacationDataExtractor::VacationDataExtractor() + : KSieve::ScriptBuilder(), + mContext(None), + mNotificationInterval(0) +{ + qCDebug(LIBKSIEVE_LOG); +} + +KSieveUi::Legacy::VacationDataExtractor::~VacationDataExtractor() +{ + +} + +void KSieveUi::Legacy::VacationDataExtractor::commandStart(const QString &identifier, int lineNumber) +{ + Q_UNUSED(lineNumber); + qCDebug(LIBKSIEVE_LOG) << "( \"" << identifier << "\" )"; + if (identifier != QLatin1String("vacation")) { + return; + } + reset(); + mContext = VacationCommand; +} + +void KSieveUi::Legacy::VacationDataExtractor::commandEnd(int lineNumber) +{ + Q_UNUSED(lineNumber); + qCDebug(LIBKSIEVE_LOG); + if (mContext != None && mContext != VacationEnd) { + mContext = VacationEnd; + } else { + mContext = None; + } +} + +void KSieveUi::Legacy::VacationDataExtractor::error(const KSieve::Error &e) +{ + qCDebug(LIBKSIEVE_LOG) << e.asString() << "@" << e.line() << "," << e.column(); +} + +void KSieveUi::Legacy::VacationDataExtractor::finished() +{ + +} + +void KSieveUi::Legacy::VacationDataExtractor::taggedArgument(const QString &tag) +{ + qCDebug(LIBKSIEVE_LOG) << "( \"" << tag << "\" )"; + if (mContext != VacationCommand) { + return; + } + if (tag == QLatin1String("days")) { + mContext = Days; + } else if (tag == QLatin1String("addresses")) { + mContext = Addresses; + } else if (tag == QLatin1String("subject")) { + mContext = Subject; + } +} + +void KSieveUi::Legacy::VacationDataExtractor::stringArgument(const QString &string, bool, const QString &) +{ + qCDebug(LIBKSIEVE_LOG) << "( \"" << string << "\" )"; + if (mContext == Addresses) { + mAliases.push_back(string); + mContext = VacationCommand; + } else if (mContext == Subject) { + mSubject = string; + mContext = VacationCommand; + } else if (mContext == VacationCommand) { + mMessageText = string; + mContext = VacationCommand; + } +} + +void KSieveUi::Legacy::VacationDataExtractor::numberArgument(unsigned long number, char) +{ + qCDebug(LIBKSIEVE_LOG) << "( \"" << number << "\" )"; + if (mContext != Days) { + return; + } + if (number > INT_MAX) { + mNotificationInterval = INT_MAX; + } else { + mNotificationInterval = number; + } + mContext = VacationCommand; +} + +void KSieveUi::Legacy::VacationDataExtractor::stringListArgumentStart() +{ + +} +void KSieveUi::Legacy::VacationDataExtractor::stringListEntry(const QString &string, bool, const QString &) +{ + qCDebug(LIBKSIEVE_LOG) << "( \"" << string << "\" )"; + if (mContext != Addresses) { + return; + } + mAliases.push_back(string); +} + +void KSieveUi::Legacy::VacationDataExtractor::stringListArgumentEnd() +{ + qCDebug(LIBKSIEVE_LOG); + if (mContext != Addresses) { + return; + } + mContext = VacationCommand; +} + +void KSieveUi::Legacy::VacationDataExtractor::reset() +{ + qCDebug(LIBKSIEVE_LOG); + mContext = None; + mNotificationInterval = 0; + mAliases.clear(); + mMessageText.clear(); +} diff --git a/libksieve/src/ksieveui/vacation/legacy/vacationutils.h b/libksieve/src/ksieveui/vacation/legacy/vacationutils.h new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/legacy/vacationutils.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2013-2015 Montel Laurent + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +#ifndef LEGACY_VACATIONUTILS_H +#define LEGACY_VACATIONUTILS_H +#include +#include + +class QDate; + +namespace KMime +{ +namespace Types +{ +struct AddrSpec; +typedef QVector AddrSpecList; +} +} + +namespace KSieveUi +{ +namespace Legacy +{ +namespace VacationUtils +{ +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +QString __attribute__ ((__deprecated__)) composeScript(const QString &messageText, + const QString &subject, + int notificationInterval, + const KMime::Types::AddrSpecList &aliases, + bool sendForSpam, const QString &excludeDomain, + const QDate &startDate, const QDate &endDate); + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +bool __attribute__ ((__deprecated__)) parseScript(const QString &script, QString &messageText, + QString &subject, + int ¬ificationInterval, KMime::Types::AddrSpecList &aliases, + bool &sendForSpam, QString &domainName, + QDate &startDate, QDate &endDate); + +} +} +} +#endif // LEGACY_VACATIONUTILS_H diff --git a/libksieve/src/ksieveui/vacation/legacy/vacationutils.cpp b/libksieve/src/ksieveui/vacation/legacy/vacationutils.cpp new file mode 100644 --- /dev/null +++ b/libksieve/src/ksieveui/vacation/legacy/vacationutils.cpp @@ -0,0 +1,171 @@ +/* + Copyright (c) 2013-2015 Montel Laurent + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +#include "vacationutils.h" +#include "vacationscriptextractor.h" +#include "sieve-vacation.h" +#include +#include + +#include +#include +#include + +using KMime::Types::AddrSpecList; +using namespace KSieveUi::Legacy::VacationUtils; +using namespace KSieveUi; + +static inline QString dotstuff(QString s) // krazy:exclude=passbyvalue +{ + if (s.startsWith(QLatin1Char('.'))) { + return QLatin1Char('.') + s.replace(QLatin1String("\n."), QStringLiteral("\n..")); + } else { + return s.replace(QLatin1String("\n."), QStringLiteral("\n..")); + } +} + +static inline QString stringReplace(QString s) +{ + s = s.replace(QRegExp(QStringLiteral("[\n\t]+")), QStringLiteral(" ")); + return s.replace(QLatin1Char('\"'), QStringLiteral("\\\"")); +} + + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +bool Legacy::VacationUtils::parseScript(const QString &script, QString &messageText, + QString &subject, + int ¬ificationInterval, AddrSpecList &aliases, + bool &sendForSpam, QString &domainName, + QDate &startDate, QDate &endDate) +{ + if (script.trimmed().isEmpty()) { + return false; + } + + // The trimmed() call below prevents parsing errors. The + // slave somehow omits the last \n, which results in a lone \r at + // the end, leading to a parse error. + const QByteArray scriptUTF8 = script.trimmed().toUtf8(); + qCDebug(LIBKSIEVE_LOG) << "scriptUtf8 = \"" + scriptUTF8 + "\""; + KSieve::Parser parser(scriptUTF8.begin(), + scriptUTF8.begin() + scriptUTF8.length()); + KSieveUi::Legacy::VacationDataExtractor vdx; + KSieveUi::Legacy::SpamDataExtractor sdx; + KSieveUi::Legacy::DomainRestrictionDataExtractor drdx; + KSieveUi::Legacy::DateExtractor dtx; + KSieveExt::MultiScriptBuilder tsb(&vdx, &sdx, &drdx, &dtx); + parser.setScriptBuilder(&tsb); + if (!parser.parse() || !vdx.commandFound()) { + return false; + } + messageText = vdx.messageText().trimmed(); + if (!vdx.subject().isEmpty()) { + subject = vdx.subject().trimmed(); + } + notificationInterval = vdx.notificationInterval(); + aliases.clear(); + foreach(const QString &alias, vdx.aliases()) { + KMime::Types::Mailbox a; + a.fromUnicodeString(alias); + aliases.append(a.addrSpec()); + } + if (!VacationSettings::allowOutOfOfficeUploadButNoSettings()) { + sendForSpam = !sdx.found(); + domainName = drdx.domainName(); + } + startDate = dtx.startDate(); + endDate = dtx.endDate(); + return true; +} + + +/* + +This file only contains legacy code, that can be removed if the lagacy code is not needed anymore. +See README for further information. + +*/ +QString Legacy::VacationUtils::composeScript(const QString &messageText, + const QString &subject, + int notificationInterval, + const AddrSpecList &addrSpecs, + bool sendForSpam, const QString &domain, + const QDate &startDate, const QDate &endDate) +{ + QString addressesArgument; + QStringList aliases; + if (!addrSpecs.empty()) { + addressesArgument += QLatin1String(":addresses [ "); + QStringList sl; + AddrSpecList::const_iterator end = addrSpecs.constEnd(); + for (AddrSpecList::const_iterator it = addrSpecs.begin(); it != end; ++it) { + sl.push_back(QLatin1Char('"') + (*it).asString().replace(QLatin1Char('\\'), QStringLiteral("\\\\")).replace(QLatin1Char('"'), QStringLiteral("\\\"")) + QLatin1Char('"')); + aliases.push_back((*it).asString()); + } + addressesArgument += sl.join(QStringLiteral(", ")) + QLatin1String(" ] "); + } + + QString script = QStringLiteral("require \"vacation\";\n"); + if (startDate.isValid() && endDate.isValid()) { + script += QStringLiteral("require \"relational\";\n" + "require \"date\";\n\n"); + } else { + script += QStringLiteral("\n"); + } + + if (!sendForSpam) + script += QStringLiteral("if header :contains \"X-Spam-Flag\" \"YES\"" + " { keep; stop; }\n"); // FIXME? + + if (!domain.isEmpty()) { // FIXME + script += QStringLiteral("if not address :domain :contains \"from\" \"%1\" { keep; stop; }\n").arg(domain); + } + + if (startDate.isValid() && endDate.isValid()) { + script += QStringLiteral("if not allof(currentdate :value \"ge\" \"date\" \"%1\"," + " currentdate :value \"le\" \"date\" \"%2\")" + " { keep; stop; }\n").arg(startDate.toString(Qt::ISODate), + endDate.toString(Qt::ISODate)); + } + + script += QLatin1String("vacation "); + script += addressesArgument; + if (notificationInterval > 0) { + script += QStringLiteral(":days %1 ").arg(notificationInterval); + } + + if (!subject.trimmed().isEmpty()) { + script += QStringLiteral(":subject \"%1\" ").arg(stringReplace(subject).trimmed()); + } + + script += QStringLiteral("text:\n"); + script += dotstuff(messageText.isEmpty() ? KSieveUi::VacationUtils::defaultMessageText() : messageText); + script += QStringLiteral("\n.\n;\n"); + return script; +} + diff --git a/libksieve/src/ksieveui/vacation/vacationutils.cpp b/libksieve/src/ksieveui/vacation/vacationutils.cpp --- a/libksieve/src/ksieveui/vacation/vacationutils.cpp +++ b/libksieve/src/ksieveui/vacation/vacationutils.cpp @@ -17,6 +17,7 @@ #include "vacationutils.h" #include "vacationscriptextractor.h" +#include "legacy/vacationutils.h" #include "sieve-vacation.h" #include #include @@ -131,6 +132,19 @@ return defaultStartDate().addDays(7); } +//TODO: delete this function after 06.2016 until than all vacation scripts should be updated +VacationUtils::Vacation parseScriptLegacy(const QString &script) +{ + KSieveUi::VacationUtils::Vacation vacation; + vacation.active = true; + vacation.valid = Legacy::VacationUtils::parseScript(script, vacation.messageText, + vacation.subject, + vacation.notificationInterval, vacation.aliases, + vacation.sendForSpam, vacation.excludeDomain, + vacation.startDate, vacation.endDate); + return vacation; +} + VacationUtils::Vacation VacationUtils::parseScript(const QString &script) { KSieveUi::VacationUtils::Vacation vacation; @@ -161,6 +175,10 @@ KSieveExt::MultiScriptBuilder tsb(&vdx , &sdx, &drdx, &dx); parser.setScriptBuilder(&tsb); if (!parser.parse() || !vdx.commandFound()) { + const auto vac = parseScriptLegacy(script); + if (vac.isValid()) { + return vac; + } vacation.active = false; vacation.valid = false; return vacation; @@ -199,6 +217,19 @@ vacation.startTime = dx.startTime(); vacation.endDate = dx.endDate(); vacation.endTime = dx.endTime(); + + if (vacation.sendForSpam && vacation.excludeDomain.isEmpty() && !vacation.startDate.isValid() && !vacation.endDate.isValid()) { + const auto vac = parseScriptLegacy(script); + if (vac.isValid()) { + vacation.sendForSpam = vac.sendForSpam; + vacation.excludeDomain = vac.excludeDomain; + vacation.startDate = vac.startDate; + vacation.startTime = vac.startTime; + vacation.endDate = vac.endDate; + vacation.endTime = vac.endTime; + } + } + return vacation; }