diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv b/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv new file mode 100644 index 0000000000..8d7a1962b4 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv @@ -0,0 +1,9 @@ +require ["date","relational","vacation"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if allof (not header :contains "X-Spam-Flag" "YES") +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + discard; +} \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv new file mode 100644 index 0000000000..def848a2cf --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv @@ -0,0 +1,10 @@ +require ["vacation", "copy"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if false +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + redirect :copy "copy@example.org"; +} +discard; \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv new file mode 100644 index 0000000000..7be2f4d094 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv @@ -0,0 +1,11 @@ +require ["vacation", "copy"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if false +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + redirect "redirect@example.org"; +} + +redirect :copy "argh@example.org"; \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp index 9ed162d04b..758796bf5e 100644 --- a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp +++ b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp @@ -1,310 +1,342 @@ /* Copyright (c) 2015 Sandro Knauß 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 "vacationutilstest.h" #include "vacation/vacationutils.h" #include #include #include #include using namespace KSieveUi; QTEST_KDEMAIN( VacationUtilsTest, NoGUI ) void testAliases(KMime::Types::AddrSpecList l1, KMime::Types::AddrSpecList l2) { QCOMPARE(l1.count(),l2.count()); for (int i=0; i < l1.count(); i++) { QCOMPARE(l1.at(i).asString(),l2.at(i).asString()); } } void testAliases(KMime::Types::AddrSpecList l1, QStringList l2) { QCOMPARE(l1.count(),l2.count()); for (int i=0;i < l1.count(); i++) { QCOMPARE(l1.at(i).asString(),l2.at(i)); } } void VacationUtilsTest::testParseEmptyScript() { const QString script; QCOMPARE(VacationUtils::parseScript(script).isValid(), false); } void VacationUtilsTest::testParseOnlyComment() { QString script(QLatin1String("#comment")); QCOMPARE(VacationUtils::parseScript(script).isValid(), false); script = QLatin1String("#comment\n\n#comment\n"); QCOMPARE(VacationUtils::parseScript(script).isValid(), false); } void VacationUtilsTest::testParseActivate_data() { QTest::addColumn("filename"); QTest::addColumn("found"); QTest::addColumn("active"); QTest::newRow("notfound") << QString::fromLatin1("vacation-notfound.siv") << false << false; QTest::newRow("simple") << QString::fromLatin1("vacation-simple.siv") << true << true; QTest::newRow("multile if") << QString::fromLatin1("vacation-multiple.siv") << true << true; QTest::newRow("deactivate") << QString::fromLatin1("vacation-deactivate.siv") << true << false; QTest::newRow("deactivate-multiple if") << QString::fromLatin1("vacation-deactivate-multiple.siv") << true << false; QTest::newRow("deactivate-complex") << QString::fromLatin1("vacation-deactivate-complex.siv") << true << false; } void VacationUtilsTest::testParseActivate() { QFETCH(QString, filename); QFETCH(bool, found); QFETCH(bool, active); QFile file(QLatin1String(VACATIONTESTDATADIR)+filename); QVERIFY(file.open(QIODevice::ReadOnly)); QString script = QString::fromUtf8(file.readAll()); VacationUtils::Vacation vacation = VacationUtils::parseScript(script); QCOMPARE(vacation.isValid(), found); QCOMPARE(vacation.active, active); } void VacationUtilsTest::testParseScript_data() { QTest::addColumn("activate"); QTest::addColumn("deactivate"); QTest::newRow("simple") << QString::fromLatin1("vacation-simple.siv") << QString::fromLatin1("vacation-deactivate.siv"); QTest::newRow("complex") << QString::fromLatin1("vacation-complex.siv") << QString::fromLatin1("vacation-deactivate-complex.siv"); } void VacationUtilsTest::testParseScript() { QFETCH(QString, activate); QFETCH(QString, deactivate); QFile fileA(QLatin1String(VACATIONTESTDATADIR) + activate); QVERIFY(fileA.open(QIODevice::ReadOnly)); QString scriptA = QString::fromUtf8(fileA.readAll()); QFile fileD(QLatin1String(VACATIONTESTDATADIR) + deactivate); QVERIFY(fileD.open(QIODevice::ReadOnly)); QString scriptD = QString::fromUtf8(fileD.readAll()); VacationUtils::Vacation vacationA = VacationUtils::parseScript(scriptA); VacationUtils::Vacation vacationD = VacationUtils::parseScript(scriptD); QCOMPARE(vacationA.active, true); QCOMPARE(vacationD.active, false); QCOMPARE(vacationD.messageText, vacationA.messageText); QCOMPARE(vacationD.subject, vacationA.subject); QCOMPARE(vacationD.notificationInterval, vacationA.notificationInterval); testAliases(vacationD.aliases, vacationA.aliases); QCOMPARE(vacationD.sendForSpam, vacationA.sendForSpam); QCOMPARE(vacationD.excludeDomain, vacationA.excludeDomain); QCOMPARE(vacationD.startDate, vacationA.startDate); QCOMPARE(vacationD.endDate, vacationA.endDate); QCOMPARE(vacationD.startTime, QTime()); QCOMPARE(vacationD.endTime, QTime()); } +void VacationUtilsTest::testMailAction_data() +{ + QTest::addColumn("filename"); + QTest::addColumn("action"); + QTest::addColumn("recipient"); + + QTest::newRow("keep") << QString::fromLatin1("vacation-complex.siv") << (int)VacationUtils::Keep << QString(); + QTest::newRow("discard") << QString::fromLatin1("vacation-active-discard.siv") << (int)VacationUtils::Discard << QString(); + QTest::newRow("send") << QString::fromLatin1("vacation-deactive-send.siv") << (int)VacationUtils::Sendto << QString::fromLatin1("redirect@example.org"); + QTest::newRow("copy") << QString::fromLatin1("vacation-deactive-copy.siv") << (int)VacationUtils::CopyTo << QString::fromLatin1("copy@example.org"); +} + +void VacationUtilsTest::testMailAction() +{ + QFETCH(QString, filename); + QFETCH(int, action); + QFETCH(QString, recipient); + + QFile file(QLatin1String(VACATIONTESTDATADIR) + filename); + QVERIFY(file.open(QIODevice::ReadOnly)); + QString script = QString::fromUtf8(file.readAll()); + + VacationUtils::Vacation vacation = VacationUtils::parseScript(script); + QCOMPARE((int)vacation.mailAction, action); + QCOMPARE(vacation.mailActionRecipient, recipient); + + const QString composedScript = VacationUtils::composeScript(vacation); + vacation = VacationUtils::parseScript(composedScript); + QCOMPARE((int)vacation.mailAction, action); + QCOMPARE(vacation.mailActionRecipient, recipient); +} + void VacationUtilsTest::testParseScriptComplex() { QFile file(QLatin1String(VACATIONTESTDATADIR "vacation-complex.siv")); QVERIFY(file.open(QIODevice::ReadOnly)); QString script = QString::fromUtf8(file.readAll()); VacationUtils::Vacation vacation = VacationUtils::parseScript(script); QCOMPARE(vacation.active, true); QCOMPARE(vacation.messageText, QLatin1String("dsfgsdfgsdfg")); QCOMPARE(vacation.subject, QLatin1String("XXX")); QCOMPARE(vacation.notificationInterval, 7); testAliases(vacation.aliases, QStringList() << QLatin1String("test@test.de")); QCOMPARE(vacation.sendForSpam, false); QCOMPARE(vacation.excludeDomain, QString()); QCOMPARE(vacation.startDate, QDate(2015, 01, 02)); QCOMPARE(vacation.endDate, QDate(2015, 03, 04)); QCOMPARE(vacation.startTime, QTime()); QCOMPARE(vacation.endTime, QTime()); } void VacationUtilsTest::testParseScriptComplexTime() { QFile file(QLatin1String(VACATIONTESTDATADIR "vacation-complex-time.siv")); QVERIFY(file.open(QIODevice::ReadOnly)); QString script = QString::fromUtf8(file.readAll()); VacationUtils::Vacation vacation = VacationUtils::parseScript(script); QCOMPARE(vacation.active, true); QCOMPARE(vacation.messageText, QLatin1String("dsfgsdfgsdfg")); QCOMPARE(vacation.subject, QLatin1String("XXX")); QCOMPARE(vacation.notificationInterval, 7); testAliases(vacation.aliases, QStringList() << QLatin1String("test@test.de")); QCOMPARE(vacation.sendForSpam, false); QCOMPARE(vacation.excludeDomain, QString()); QCOMPARE(vacation.startDate, QDate(2015, 01, 02)); QCOMPARE(vacation.endDate, QDate(2015, 03, 04)); QCOMPARE(vacation.startTime, QTime(2,0)); QCOMPARE(vacation.endTime, QTime()); QString composedScript = VacationUtils::composeScript(vacation); vacation = VacationUtils::parseScript(composedScript); QCOMPARE(vacation.startTime, QTime(2,0)); QCOMPARE(vacation.endTime, QTime()); } void VacationUtilsTest::testWriteScript() { VacationUtils::Vacation vacation, vacationA; QStringList aliases = QStringList() << QLatin1String("test@test.de"); vacation.valid = true; vacation.messageText = QLatin1String("dsfgsdfgsdfg"); vacation.subject = QLatin1String("XXX"); vacation.notificationInterval = 7; vacation.sendForSpam = false; vacation.excludeDomain = QLatin1String("example.org"); vacation.startDate = QDate(2015, 01, 02); vacation.endDate = QDate(2015, 03, 04); vacation.active = true; foreach(const QString &alias, aliases) { KMime::Types::Mailbox a; a.fromUnicodeString(alias); vacation.aliases.append(a.addrSpec()); } QString script = VacationUtils::composeScript(vacation); vacationA = VacationUtils::parseScript(script); QCOMPARE(vacationA.isValid(), true); QCOMPARE(vacationA.active, vacation.active); QCOMPARE(vacationA.messageText, vacation.messageText); QCOMPARE(vacationA.subject, vacation.subject); QCOMPARE(vacationA.notificationInterval, vacation.notificationInterval); testAliases(vacationA.aliases, vacation.aliases); QCOMPARE(vacationA.sendForSpam, vacation.sendForSpam); QCOMPARE(vacationA.excludeDomain, vacation.excludeDomain); QCOMPARE(vacationA.startDate, vacation.startDate); QCOMPARE(vacationA.endDate, vacation.endDate); QCOMPARE(vacationA.startTime, QTime()); QCOMPARE(vacationA.endTime, QTime()); vacation.active = false; script = VacationUtils::composeScript(vacation); vacationA = VacationUtils::parseScript(script); QCOMPARE(vacationA.isValid(), true); QCOMPARE(vacationA.active, vacation.active); QCOMPARE(vacationA.messageText, vacation.messageText); QCOMPARE(vacationA.subject, vacation.subject); QCOMPARE(vacationA.notificationInterval, vacation.notificationInterval); testAliases(vacationA.aliases, vacation.aliases); QCOMPARE(vacationA.sendForSpam, vacation.sendForSpam); QCOMPARE(vacationA.excludeDomain, vacation.excludeDomain); QCOMPARE(vacationA.startDate, vacation.startDate); QCOMPARE(vacationA.endDate, vacation.endDate); QCOMPARE(vacationA.startTime, QTime()); QCOMPARE(vacationA.endTime, QTime()); } void VacationUtilsTest::testWriteSimpleScript() { VacationUtils::Vacation vacation; vacation.valid = true; vacation.messageText = QLatin1String("dsfgsdfgsdfg"); vacation.subject = QLatin1String("XXX"); vacation.notificationInterval = 7; vacation.active = true; vacation.sendForSpam = true; QString script = VacationUtils::composeScript(vacation); VacationUtils::Vacation vacationA = VacationUtils::parseScript(script); QCOMPARE(vacation.isValid(), true); QCOMPARE(vacationA.active, vacation.active); QCOMPARE(vacationA.messageText, vacation.messageText); QCOMPARE(vacationA.subject, vacation.subject); QCOMPARE(vacationA.notificationInterval, vacation.notificationInterval); vacation.active = false; script = VacationUtils::composeScript(vacation); vacationA = VacationUtils::parseScript(script); QCOMPARE(vacation.isValid(), true); QCOMPARE(vacationA.active, vacation.active); QCOMPARE(vacationA.messageText, vacation.messageText); QCOMPARE(vacationA.subject, vacation.subject); QCOMPARE(vacationA.notificationInterval, vacation.notificationInterval); } void VacationUtilsTest::testUpdateVacationBlock() { QFile fileA(QLatin1String(VACATIONTESTDATADIR "vacation-simple.siv")); QVERIFY(fileA.open(QIODevice::ReadOnly)); QString scriptA = QString::fromUtf8(fileA.readAll()); QFile fileB(QLatin1String(VACATIONTESTDATADIR "vacation-deactivate.siv")); QVERIFY(fileB.open(QIODevice::ReadOnly)); QString scriptB = QString::fromUtf8(fileB.readAll()); const QString attend = QLatin1String("if true\n{\ntestcmd;\n}\n"); const QString require = QLatin1String("require [\"date\", \"test\"];"); const QString scriptAattend = scriptA + QLatin1String("\n") + attend; const QString scriptBattend = scriptB + QLatin1String("\n") + attend; QStringList linesA = scriptA.split(QLatin1Char('\n')); QStringList header; for(int i=0; i<5;i++ ){ header.append(linesA.at(i)); } QStringList vacation; for(int i=5; i 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 VACATIONUTILSTEST_H #define VACATIONUTILSTEST_H #include namespace KSieveUi { class VacationUtilsTest : public QObject { Q_OBJECT private Q_SLOTS: void testParseEmptyScript(); void testParseOnlyComment(); void testParseActivate_data(); void testParseActivate(); void testParseScript_data(); void testParseScript(); void testParseScriptComplex(); void testParseScriptComplexTime(); + void testMailAction_data(); + void testMailAction(); void testWriteScript(); void testWriteSimpleScript(); void testUpdateVacationBlock(); void testMergeRequireLine(); }; } #endif // VACATIONUTILSTEST_H diff --git a/libksieve/ksieveui/vacation/vacation.cpp b/libksieve/ksieveui/vacation/vacation.cpp index c24050b3eb..3ab6fe9b60 100644 --- a/libksieve/ksieveui/vacation/vacation.cpp +++ b/libksieve/ksieveui/vacation/vacation.cpp @@ -1,232 +1,235 @@ /* -*- c++ -*- vacation.cpp KMail, the KDE mail client. Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #include "vacation.h" #include "vacationutils.h" #include "vacationscriptextractor.h" #include "sieve-vacation.h" #include "util/util.h" #include "vacationdialog.h" #include #include #include #include #include #include #include #include using namespace KSieveUi; Vacation::Vacation(QObject * parent, bool checkOnly, const KUrl &url) : QObject( parent ), mSieveJob( 0 ), mDialog( 0 ), mWasActive( false ), mCheckOnly( checkOnly ) { if (url.isEmpty()) { mUrl = findURL(mServerName); } else { mUrl = url; } kDebug() << "Vacation: found url \"" << mUrl.prettyUrl() <<"\""; if ( mUrl.isEmpty() ) // nothing to do... return; mSieveJob = KManageSieve::SieveJob::get( mUrl ); if (checkOnly) { mSieveJob->setInteractive( false ); } connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)), SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)) ); } Vacation::~Vacation() { if ( mSieveJob ) mSieveJob->kill(); mSieveJob = 0; delete mDialog; mDialog = 0; kDebug() << "~Vacation()"; } KUrl Vacation::findURL(QString &serverName) const { const Akonadi::AgentInstance::List instances = Util::imapAgentInstances(); foreach ( const Akonadi::AgentInstance &instance, instances ) { if ( instance.status() == Akonadi::AgentInstance::Broken ) continue; const KUrl url = Util::findSieveUrlForAccount( instance.identifier() ); if ( !url.isEmpty() ) { serverName = instance.name(); return url; } } return KUrl(); } void Vacation::slotGetResult( KManageSieve::SieveJob * job, bool success, const QString & script, bool active ) { kDebug() << success << ", ?," << active << ")" << endl << "script:" << endl << script; mSieveJob = 0; // job deletes itself after returning from this slot! if ( !mCheckOnly && mUrl.protocol() == QLatin1String("sieve") && !job->sieveCapabilities().contains(QLatin1String("vacation")) ) { KMessageBox::sorry( 0, i18n( "Your server did not list \"vacation\" in " "its list of supported Sieve extensions;\n" "without it, KMail cannot install out-of-" "office replies for you.\n" "Please contact your system administrator." ) ); emit result( false ); return; } const bool supportsDate = job->sieveCapabilities().contains(QLatin1String("date")); if ( !mDialog && !mCheckOnly ) mDialog = new VacationDialog( i18n("Configure \"Out of Office\" Replies"), 0, false ); if ( !success ) { active = false; // default to inactive } KSieveUi::VacationUtils::Vacation vacation = KSieveUi::VacationUtils::parseScript(script); if ( !mCheckOnly && ( !success || (!vacation.isValid() && !script.trimmed().isEmpty())) ) { KMessageBox::information( 0, i18n("Someone (probably you) changed the " "vacation script on the server.\n" "KMail is no longer able to determine " "the parameters for the autoreplies.\n" "Default values will be used." ) ); } mWasActive = active; if ( mDialog ) { mDialog->setActivateVacation( active && vacation.active ); + mDialog->setMailAction(vacation.mailAction, vacation.mailActionRecipient); mDialog->setSubject(vacation.subject); mDialog->setMessageText( vacation.messageText ); mDialog->setNotificationInterval( vacation.notificationInterval ); mDialog->setMailAliases( vacation.aliases ); mDialog->setSendForSpam( vacation.sendForSpam ); mDialog->setDomainName( vacation.excludeDomain ); mDialog->enableDomainAndSendForSpam( !VacationSettings::allowOutOfOfficeUploadButNoSettings() ); if (supportsDate) { mDialog->enableDates( supportsDate ); mDialog->setStartDate( vacation.startDate ); mDialog->setEndTime(vacation.endTime); mDialog->setEndDate( vacation.endDate ); mDialog->setEndTime(vacation.endTime); } connect( mDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) ); connect( mDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCancel()) ); mDialog->show(); } emit scriptActive( mWasActive, mServerName ); if ( mCheckOnly && mWasActive ) { if ( KMessageBox::questionYesNo( 0, i18n( "There is still an active out-of-office reply configured.\n" "Do you want to edit it?"), i18n("Out-of-office reply still active"), KGuiItem( i18n( "Edit"), QLatin1String("document-properties") ), KGuiItem( i18n("Ignore"), QLatin1String("dialog-cancel") ) ) == KMessageBox::Yes ) { emit requestEditVacation(); } } } void Vacation::slotDialogOk() { kDebug(); // compose a new script: const bool active = mDialog->activateVacation(); VacationUtils::Vacation vacation; vacation.valid = true; vacation.active = active; vacation.messageText = mDialog->messageText(); vacation.subject = mDialog->subject(); + vacation.mailAction = mDialog->mailAction(); + vacation.mailActionRecipient = mDialog->mailActionRecipient(); vacation.notificationInterval = mDialog->notificationInterval(); vacation.aliases = mDialog->mailAliases(); vacation.sendForSpam = mDialog->sendForSpam(); vacation.excludeDomain = mDialog->domainName(); vacation.startDate = mDialog->startDate(); vacation.startTime = mDialog->startTime(); vacation.endDate = mDialog->endDate(); vacation.endTime = mDialog->endTime(); const QString script = VacationUtils::composeScript(vacation); emit scriptActive( active, mServerName); kDebug() << "script:" << endl << script; // and commit the dialog's settings to the server: mSieveJob = KManageSieve::SieveJob::put( mUrl, script, active, mWasActive ); if ( active ) connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)), SLOT(slotPutActiveResult(KManageSieve::SieveJob*,bool)) ); else connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)), SLOT(slotPutInactiveResult(KManageSieve::SieveJob*,bool)) ); // destroy the dialog: mDialog->delayedDestruct(); mDialog = 0; } void Vacation::slotDialogCancel() { kDebug(); mDialog->delayedDestruct(); mDialog = 0; emit result( false ); } void Vacation::slotPutActiveResult( KManageSieve::SieveJob * job, bool success ) { handlePutResult( job, success, true ); } void Vacation::slotPutInactiveResult( KManageSieve::SieveJob * job, bool success ) { handlePutResult( job, success, false ); } void Vacation::handlePutResult( KManageSieve::SieveJob *, bool success, bool activated ) { if ( success ) KMessageBox::information( 0, activated ? i18n("Sieve script installed successfully on the server.\n" "Out of Office reply is now active.") : i18n("Sieve script installed successfully on the server.\n" "Out of Office reply has been deactivated.") ); kDebug() << "( ???," << success << ", ? )"; mSieveJob = 0; // job deletes itself after returning from this slot! emit result( success ); emit scriptActive( activated, mServerName ); } void Vacation::showVacationDialog() { if (mDialog) { mDialog->show(); mDialog->raise(); mDialog->activateWindow(); } } diff --git a/libksieve/ksieveui/vacation/vacationdialog.cpp b/libksieve/ksieveui/vacation/vacationdialog.cpp index 14b805b06c..ba8226965a 100644 --- a/libksieve/ksieveui/vacation/vacationdialog.cpp +++ b/libksieve/ksieveui/vacation/vacationdialog.cpp @@ -1,220 +1,235 @@ /* vacationdialog.cpp Copyright (c) 2013, 2014 Montel Laurent Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #include "vacationdialog.h" #include "vacationeditwidget.h" #include #include #include #include #include #include #include #include #include using KMime::Types::AddrSpecList; using namespace KSieveUi; VacationDialog::VacationDialog( const QString &caption, QWidget * parent, bool modal ) : KDialog( parent ) { setCaption( caption ); setButtons( Ok|Cancel|Default ); setDefaultButton( Ok ); setModal( modal ); QWidget *w = new QWidget; QVBoxLayout *vbox = new QVBoxLayout; vbox->setMargin(0); w->setLayout(vbox); vbox->addWidget(mVacationEditWidget); mVacationEditWidget = new VacationEditWidget; KSeparator *separator = new KSeparator; vbox->addWidget(separator); setMainWidget( w ); KWindowSystem::setIcons( winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)) ); readConfig(); connect( this, SIGNAL(defaultClicked()), this, SLOT(slotDialogDefaults()) ); } VacationDialog::~VacationDialog() { kDebug() << "~VacationDialog()"; writeConfig(); } void VacationDialog::writeConfig() { KConfigGroup group( KGlobal::config(), "VacationDialog" ); group.writeEntry( "Size", size() ); } void VacationDialog::readConfig() { KConfigGroup group( KGlobal::config(), "VacationDialog" ); const QSize size = group.readEntry( "Size", QSize() ); if ( size.isValid() ) { resize( size ); } else { resize( sizeHint().width(), sizeHint().height() ); } } bool VacationDialog::activateVacation() const { return mVacationEditWidget->activateVacation(); } void VacationDialog::setActivateVacation( bool activate ) { mVacationEditWidget->setActivateVacation(activate); } QString VacationDialog::messageText() const { return mVacationEditWidget->messageText(); } void VacationDialog::setMessageText( const QString &text ) { mVacationEditWidget->setMessageText(text); } QString VacationDialog::subject() const { return mVacationEditWidget->subject(); } void VacationDialog::setSubject(const QString &subject) { return mVacationEditWidget->setSubject(subject); } +VacationUtils::MailAction VacationDialog::mailAction() const +{ + return mVacationEditWidget->mailAction(); +} + +QString VacationDialog::mailActionRecipient() const +{ + return mVacationEditWidget->mailActionRecipient(); +} + +void VacationDialog::setMailAction(VacationUtils::MailAction action, const QString& recipient) +{ + mVacationEditWidget->setMailAction(action, recipient); +} + int VacationDialog::notificationInterval() const { return mVacationEditWidget->notificationInterval(); } void VacationDialog::setNotificationInterval( int days ) { mVacationEditWidget->setNotificationInterval(days); } AddrSpecList VacationDialog::mailAliases() const { return mVacationEditWidget->mailAliases(); } void VacationDialog::setMailAliases( const AddrSpecList &aliases ) { mVacationEditWidget->setMailAliases(aliases); } void VacationDialog::setMailAliases( const QString &aliases ) { mVacationEditWidget->setMailAliases(aliases); } QString VacationDialog::domainName() const { return mVacationEditWidget->domainName(); } void VacationDialog::setDomainName( const QString &domain ) { mVacationEditWidget->setDomainName(domain); } bool VacationDialog::domainCheck() const { return mVacationEditWidget->domainCheck(); } void VacationDialog::setDomainCheck( bool check ) { mVacationEditWidget->setDomainCheck(check); } bool VacationDialog::sendForSpam() const { return mVacationEditWidget->sendForSpam(); } void VacationDialog::setSendForSpam( bool enable ) { mVacationEditWidget->setSendForSpam(enable); } void VacationDialog::enableDomainAndSendForSpam( bool enable ) { mVacationEditWidget->enableDomainAndSendForSpam(enable); } void VacationDialog::slotDialogDefaults() { mVacationEditWidget->setDefault(); } void VacationDialog::enableDates(bool enable) { mVacationEditWidget->enableDates(enable); } QDate VacationDialog::endDate() const { return mVacationEditWidget->endDate(); } void VacationDialog::setEndDate( const QDate &endDate ) { mVacationEditWidget->setEndDate( endDate ); } QTime VacationDialog::endTime() const { return mVacationEditWidget->endTime(); } void VacationDialog::setEndTime(const QTime &endTime) { mVacationEditWidget->setEndTime(endTime); } QDate VacationDialog::startDate() const { return mVacationEditWidget->startDate(); } void VacationDialog::setStartDate( const QDate &startDate ) { mVacationEditWidget->setStartDate( startDate ); } QTime VacationDialog::startTime() const { return mVacationEditWidget->startTime(); } void VacationDialog::setStartTime(const QTime &startTime) { mVacationEditWidget->setStartTime(startTime); } diff --git a/libksieve/ksieveui/vacation/vacationdialog.h b/libksieve/ksieveui/vacation/vacationdialog.h index dceb516b65..285d6dac9e 100644 --- a/libksieve/ksieveui/vacation/vacationdialog.h +++ b/libksieve/ksieveui/vacation/vacationdialog.h @@ -1,94 +1,99 @@ /* -*- c++ -*- vacationdialog.h Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #ifndef KSIEVE_KSIEVEUI_VACATIONDIALOG_H #define KSIEVE_KSIEVEUI_VACATIONDIALOG_H #include +#include "vacationutils.h" template class QList; class KDateTime; namespace KMime { namespace Types { struct AddrSpec; typedef QList AddrSpecList; } } namespace KSieveUi { class VacationEditWidget; class VacationDialog : public KDialog { Q_OBJECT public: explicit VacationDialog( const QString &caption, QWidget * parent=0, bool modal=true ); ~VacationDialog(); void enableDomainAndSendForSpam( bool enable = true ); bool activateVacation() const; void setActivateVacation( bool activate ); bool domainCheck() const; void setDomainCheck( bool check ); QString messageText() const; void setMessageText( const QString &text ); QString subject() const; void setSubject( const QString &subject ); + VacationUtils::MailAction mailAction() const; + QString mailActionRecipient() const; + void setMailAction (KSieveUi::VacationUtils::MailAction action, const QString &recipient); + int notificationInterval() const; void setNotificationInterval( int days ); KMime::Types::AddrSpecList mailAliases() const; void setMailAliases( const KMime::Types::AddrSpecList & aliases ); void setMailAliases( const QString &aliases ); QString domainName() const; void setDomainName( const QString &domain ); bool sendForSpam() const; void setSendForSpam( bool enable ); void enableDates( bool enable = true ); QDate startDate() const; void setStartDate( const QDate &startDate ); QTime startTime() const; void setStartTime( const QTime &startTime ); QDate endDate() const; void setEndDate( const QDate &endDate ); QTime endTime() const; void setEndTime( const QTime &endTime ); private slots: void slotDialogDefaults(); private: void writeConfig(); void readConfig(); VacationEditWidget *mVacationEditWidget; }; } #endif diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.cpp b/libksieve/ksieveui/vacation/vacationeditwidget.cpp index a6b9c16b6c..72782eebd4 100644 --- a/libksieve/ksieveui/vacation/vacationeditwidget.cpp +++ b/libksieve/ksieveui/vacation/vacationeditwidget.cpp @@ -1,388 +1,437 @@ /* Copyright (c) 2013, 2014 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 "vacationeditwidget.h" #include "vacationutils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using KMime::Types::AddrSpecList; using KMime::Types::AddressList; using KMime::Types::MailboxList; using KMime::HeaderParsing::parseAddressList; using namespace KSieveUi; VacationEditWidget::VacationEditWidget(QWidget *parent) : QWidget(parent) { int row = -1; QGridLayout * glay = new QGridLayout( this ); glay->setSpacing( KDialog::spacingHint() ); glay->setMargin( 0 ); glay->setColumnStretch( 1, 1 ); // explanation label: ++row; glay->addWidget( new QLabel( i18n("Configure vacation " "notifications to be sent:"), this ), row, 0, 1, 2 ); // Activate checkbox: ++row; mActiveCheck = new QCheckBox( i18n("&Activate vacation notifications"), this ); glay->addWidget( mActiveCheck, row, 0, 1, 2 ); // Message text edit: ++row; glay->setRowStretch( row, 1 ); mTextEdit = new PimCommon::RichTextEditorWidget( this ); mTextEdit->setObjectName( QLatin1String("mTextEdit") ); mTextEdit->setAcceptRichText( false ); glay->addWidget( mTextEdit, row, 0, 1, 2 ); // Subject ++row; mSubject = new KLineEdit(this); mSubject->setObjectName(QLatin1String("mSubject")); mSubject->setClearButtonShown(true); QLabel *tmpLabel = new QLabel(i18n("&Subject of the vacation mail:"), this); tmpLabel->setBuddy(mSubject); glay->addWidget(tmpLabel, row, 0); glay->addWidget(mSubject, row, 1); // From date QHBoxLayout *timeLayout = new QHBoxLayout(this); mStartDate = new KDateComboBox( this ); mStartDate->setObjectName( QLatin1String( "mStartDate" ) ); mStartDate->setOptions( KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords | KDateComboBox::WarnOnInvalid ); mStartDate->setEnabled( false ); // Disable by default - we need an extension to support this mStartTime = new KTimeComboBox( this ); mStartTime->setObjectName( QLatin1String( "mStartTime" ) ); mStartTime->setOptions( KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::EditTime | KTimeComboBox::WarnOnInvalid ); mStartTime->setEnabled( false ); // Disable by default - we need an extension to support this mStartTimeActive = new QCheckBox(this); connect(mStartTimeActive,SIGNAL(toggled(bool)), mStartTime, SLOT(setEnabled(bool))); timeLayout->addWidget(mStartDate); timeLayout->addWidget(mStartTimeActive); timeLayout->addWidget(mStartTime); ++row; QLabel *label = new QLabel( i18n("&Start:"), this ); label->setBuddy( mStartDate ); glay->addWidget( label, row, 0 ); glay->addLayout(timeLayout, row, 1); // End date timeLayout = new QHBoxLayout(this); mEndDate = new KDateComboBox( this ); mEndDate->setObjectName( QLatin1String( "mEndDate" ) ); mEndDate->setOptions( KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords | KDateComboBox::WarnOnInvalid ); mEndDate->setEnabled( false ); // Disable by default - we need an extension to support this mEndTime = new KTimeComboBox( this ); mEndTime->setObjectName( QLatin1String( "mEndTime" ) ); mEndTime->setOptions( KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::EditTime | KTimeComboBox::WarnOnInvalid ); mEndTime->setEnabled( false ); // Disable by default - we need an extension to support this mEndTimeActive = new QCheckBox(this); connect(mEndTimeActive,SIGNAL(toggled(bool)), mEndTime, SLOT(setEnabled(bool))); timeLayout->addWidget(mEndDate); timeLayout->addWidget(mEndTimeActive); timeLayout->addWidget(mEndTime); ++row; label = new QLabel( i18n("&End:"), this ); label->setBuddy( mEndDate ); glay->addWidget( label, row, 0 ); glay->addLayout(timeLayout, row, 1); // "Resent only after" spinbox and label: ++row; int defDayInterval = 7; //default day interval mIntervalSpin = new KIntSpinBox( 0, 356, 1, defDayInterval, this ); mIntervalSpin->setObjectName( QLatin1String("mIntervalSpin") ); mIntervalSpin->setSuffix( i18np(" day", " days", defDayInterval) ); connect(mIntervalSpin, SIGNAL(valueChanged(int)), SLOT(slotIntervalSpinChanged(int)) ); label = new QLabel( i18n("&Resend notification only after:"), this ); label->setBuddy( mIntervalSpin ); glay->addWidget( label, row, 0 ); glay->addWidget( mIntervalSpin, row, 1 ); // "Send responses for these addresses" lineedit and label: ++row; mMailAliasesEdit = new KLineEdit( this ); mMailAliasesEdit->setObjectName( QLatin1String("mMailAliasesEdit") ); mMailAliasesEdit->setClearButtonShown( true ); tmpLabel = new QLabel( i18n("&Send responses for these addresses:"), this ); tmpLabel->setBuddy( mMailAliasesEdit ); glay->addWidget( tmpLabel, row, 0 ); glay->addWidget( mMailAliasesEdit, row, 1 ); + // Action for incomming mails + mMailAction = new QComboBox(this); + for (int i=0; i<4; i++) { + mMailAction->addItem(VacationUtils::mailAction((VacationUtils::MailAction) i)); + } + mMailAction->setObjectName(QLatin1String("mMailAction")); + connect(mMailAction, SIGNAL(currentIndexChanged(int)), SLOT(mailActionChanged(int))); + + mMailActionRecipient = new KLineEdit(this); + mMailActionRecipient->setObjectName(QLatin1String("mMailActionRecipient")); + mMailActionRecipient->setClearButtonShown(true); + mMailActionRecipient->setEnabled(false); + + QHBoxLayout *hLayout = new QHBoxLayout(this); + + hLayout->addWidget(mMailAction); + hLayout->addWidget(mMailActionRecipient); + + ++row; + tmpLabel = new QLabel(i18n("&Action for incomming mails:"), this); + tmpLabel->setBuddy(mMailAction); + glay->addWidget(tmpLabel, row, 0); + glay->addLayout(hLayout, row, 1); + // "Send responses also to SPAM mail" checkbox: ++row; mSpamCheck = new QCheckBox( i18n("Do not send vacation replies to spam messages"), this ); mSpamCheck->setObjectName( QLatin1String("mSpamCheck") ); mSpamCheck->setChecked( true ); glay->addWidget( mSpamCheck, row, 0, 1, 2 ); // domain checkbox and linedit: ++row; mDomainCheck = new QCheckBox( i18n("Only react to mail coming from domain"), this ); mDomainCheck->setObjectName( QLatin1String("mDomainCheck") ); mDomainCheck->setChecked( false ); mDomainEdit = new KLineEdit( this ); mDomainEdit->setObjectName( QLatin1String("mDomainEdit") ); mDomainEdit->setClearButtonShown( true ); mDomainEdit->setEnabled( false ); mDomainEdit->setValidator( new QRegExpValidator( QRegExp( QLatin1String("[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*") ), mDomainEdit ) ); glay->addWidget( mDomainCheck, row, 0 ); glay->addWidget( mDomainEdit, row, 1 ); connect( mDomainCheck, SIGNAL(toggled(bool)), mDomainEdit, SLOT(setEnabled(bool)) ); } VacationEditWidget::~VacationEditWidget() { } bool VacationEditWidget::activateVacation() const { return mActiveCheck->isChecked(); } void VacationEditWidget::setActivateVacation( bool activate ) { mActiveCheck->setChecked( activate ); } QString VacationEditWidget::messageText() const { return mTextEdit->toPlainText().trimmed(); } void VacationEditWidget::setMessageText( const QString &text ) { mTextEdit->setPlainText( text ); const int height = ( mTextEdit->fontMetrics().lineSpacing() + 1 ) * 11; mTextEdit->setMinimumHeight( height ); } int VacationEditWidget::notificationInterval() const { return mIntervalSpin->value(); } void VacationEditWidget::setNotificationInterval( int days ) { mIntervalSpin->setValue( days ); } AddrSpecList VacationEditWidget::mailAliases() const { QByteArray text = mMailAliasesEdit->text().toLatin1(); // ### IMAA: !ok AddressList al; const char * s = text.begin(); parseAddressList( s, text.end(), al ); AddrSpecList asl; AddressList::const_iterator end(al.constEnd()); for ( AddressList::const_iterator it = al.constBegin() ; it != end; ++it ) { const MailboxList & mbl = (*it).mailboxList; for ( MailboxList::const_iterator jt = mbl.constBegin() ; jt != mbl.constEnd() ; ++jt ) asl.push_back( (*jt).addrSpec() ); } return asl; } void VacationEditWidget::setMailAliases( const AddrSpecList &aliases ) { QStringList sl; AddrSpecList::const_iterator end(aliases.constEnd()); for ( AddrSpecList::const_iterator it = aliases.constBegin() ; it != end; ++it ) sl.push_back( (*it).asString() ); mMailAliasesEdit->setText( sl.join(QLatin1String(", ")) ); } void VacationEditWidget::setMailAliases( const QString &aliases ) { mMailAliasesEdit->setText( aliases ); } void VacationEditWidget::slotIntervalSpinChanged ( int value ) { mIntervalSpin->setSuffix( i18np(" day", " days", value) ); } QString VacationEditWidget::domainName() const { return mDomainCheck->isChecked() ? mDomainEdit->text() : QString() ; } void VacationEditWidget::setDomainName( const QString &domain ) { if ( !domain.isEmpty() ) { mDomainEdit->setText( domain ); mDomainCheck->setChecked( true ); } } bool VacationEditWidget::domainCheck() const { return mDomainCheck->isChecked(); } void VacationEditWidget::setDomainCheck( bool check ) { mDomainCheck->setChecked( check ); } bool VacationEditWidget::sendForSpam() const { return !mSpamCheck->isChecked(); } void VacationEditWidget::setSendForSpam( bool enable ) { mSpamCheck->setChecked( !enable ); } QDate VacationEditWidget::endDate() const { if ( mEndDate->isEnabled() ) { return mEndDate->date(); } else { return QDate(); } } void VacationEditWidget::setEndDate( const QDate &endDate ) { mEndDate->setDate( endDate ); } QTime VacationEditWidget::endTime() const { if ( mEndTime->isEnabled() ) { return mEndTime->time(); } else { return QTime(); } } void VacationEditWidget::setEndTime( const QTime &endTime ) { mEndTimeActive->setChecked(endTime.isValid()); mEndTime->setEnabled(endTime.isValid()); mEndTime->setTime( endTime ); } QDate VacationEditWidget::startDate() const { if ( mStartDate->isEnabled() ) { return mStartDate->date(); } else { return QDate(); } } void VacationEditWidget::setStartDate( const QDate &startDate ) { mStartDate->setDate( startDate ); } QTime VacationEditWidget::startTime() const { if ( mStartTime->isEnabled() ) { return mStartTime->time(); } else { return QTime(); } } void VacationEditWidget::setStartTime( const QTime &startTime ) { mStartTimeActive->setChecked(startTime.isValid()); mStartTime->setEnabled(startTime.isValid()); mStartTime->setTime( startTime ); } void VacationEditWidget::setSubject(const QString &subject) { mSubject->setText(subject); } QString VacationEditWidget::subject() const { if (mSubject->isEnabled()) { return mSubject->text(); } else { return QString(); } } +void VacationEditWidget::mailActionChanged(int action) +{ + bool enable = (action == VacationUtils::CopyTo || action == VacationUtils::Sendto); + mMailActionRecipient->setEnabled(enable); +} + + +void VacationEditWidget::setMailAction(VacationUtils::MailAction action, const QString &recipient) +{ + mMailAction->setCurrentIndex(action); + mMailActionRecipient->setText(recipient); +} + +VacationUtils::MailAction VacationEditWidget::mailAction() const +{ + return (VacationUtils::MailAction) mMailAction->currentIndex(); +} + +QString VacationEditWidget::mailActionRecipient() const +{ + return mMailActionRecipient->text(); +} + + void VacationEditWidget::enableDates( bool enable ) { mStartDate->setEnabled( enable ); mEndDate->setEnabled( enable ); } void VacationEditWidget::enableDomainAndSendForSpam( bool enable ) { mDomainCheck->setEnabled( enable ); mDomainEdit->setEnabled( enable && mDomainCheck->isChecked() ); mSpamCheck->setEnabled( enable ); } void VacationEditWidget::setDefault() { setActivateVacation( true ); setMessageText( VacationUtils::defaultMessageText() ); setSubject(VacationUtils::defaultSubject()); setNotificationInterval( VacationUtils::defaultNotificationInterval() ); setMailAliases( VacationUtils::defaultMailAliases() ); setSendForSpam( VacationUtils::defaultSendForSpam() ); setDomainName( VacationUtils::defaultDomainName() ); + setMailAction(VacationUtils::defaultMailAction(), QString()); setDomainCheck( false ); } diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.h b/libksieve/ksieveui/vacation/vacationeditwidget.h index 35ebb13c54..7b0f1380b1 100644 --- a/libksieve/ksieveui/vacation/vacationeditwidget.h +++ b/libksieve/ksieveui/vacation/vacationeditwidget.h @@ -1,116 +1,125 @@ /* Copyright (c) 2013, 2014 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 VACATIONEDITWIDGET_H #define VACATIONEDITWIDGET_H #include +#include "vacationutils.h" class KIntSpinBox; class KLineEdit; class KDateComboBox; class KTimeComboBox; +class QComboBox; class QDate; class QTime; namespace PimCommon { class RichTextEditorWidget; } class QCheckBox; template class QList; namespace KMime { namespace Types { struct AddrSpec; typedef QList AddrSpecList; } } namespace KSieveUi { class VacationEditWidget : public QWidget { Q_OBJECT public: explicit VacationEditWidget(QWidget *parent=0); ~VacationEditWidget(); void enableDates( bool enable = true ); void enableDomainAndSendForSpam( bool enable = true ); bool activateVacation() const; void setActivateVacation( bool activate ); bool domainCheck() const; void setDomainCheck( bool check ); QString messageText() const; void setMessageText( const QString &text ); int notificationInterval() const; void setNotificationInterval( int days ); KMime::Types::AddrSpecList mailAliases() const; void setMailAliases( const KMime::Types::AddrSpecList & aliases ); void setMailAliases( const QString &aliases ); QString domainName() const; void setDomainName( const QString &domain ); QString subject() const; void setSubject(const QString &subject); bool sendForSpam() const; void setSendForSpam( bool enable ); QDate startDate() const; void setStartDate( const QDate &startDate ); QTime startTime() const; void setStartTime( const QTime &startTime ); QDate endDate() const; void setEndDate( const QDate &endDate ); QTime endTime() const; void setEndTime( const QTime &endTime ); + VacationUtils::MailAction mailAction() const; + QString mailActionRecipient() const; + void setMailAction(VacationUtils::MailAction action, const QString &recipient); + void setDefault(); private Q_SLOTS: void slotIntervalSpinChanged( int value ); + void mailActionChanged(int index); protected: QCheckBox *mActiveCheck; KIntSpinBox *mIntervalSpin; KLineEdit *mMailAliasesEdit; PimCommon::RichTextEditorWidget *mTextEdit; QCheckBox *mSpamCheck; QCheckBox *mDomainCheck; KLineEdit *mDomainEdit; KLineEdit *mSubject; + QComboBox *mMailAction; + KLineEdit *mMailActionRecipient; KDateComboBox *mStartDate; KTimeComboBox *mStartTime; QCheckBox *mStartTimeActive; KDateComboBox *mEndDate; KTimeComboBox *mEndTime; QCheckBox *mEndTimeActive; }; } #endif // VACATIONEDITWIDGET_H diff --git a/libksieve/ksieveui/vacation/vacationpagewidget.cpp b/libksieve/ksieveui/vacation/vacationpagewidget.cpp index 31e9d49233..e6c7e51337 100644 --- a/libksieve/ksieveui/vacation/vacationpagewidget.cpp +++ b/libksieve/ksieveui/vacation/vacationpagewidget.cpp @@ -1,189 +1,192 @@ /* Copyright (c) 2013, 2014 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 "vacationpagewidget.h" #include "vacationeditwidget.h" #include "vacationwarningwidget.h" #include "vacationcreatescriptjob.h" #include "vacationutils.h" #include "multiimapvacationmanager.h" #include #include "sieve-vacation.h" #include #include #include #include #include #include #include using namespace KSieveUi; VacationPageWidget::VacationPageWidget(QWidget *parent) : QWidget(parent), mPageScript(Script), mWasActive(false) { QVBoxLayout *lay = new QVBoxLayout; lay->setMargin(0); mStackWidget = new QStackedWidget; lay->addWidget(mStackWidget); //Main Page QWidget *mainPage = new QWidget; QVBoxLayout *vbox = new QVBoxLayout; mainPage->setLayout(vbox); mVacationWarningWidget = new VacationWarningWidget; vbox->addWidget(mVacationWarningWidget); mVacationEditWidget = new VacationEditWidget; vbox->addWidget(mVacationEditWidget); mStackWidget->addWidget(mainPage); QWidget *w = new QWidget; vbox = new QVBoxLayout; QLabel *lab = new QLabel(i18n( "Your server did not list \"vacation\" in " "its list of supported Sieve extensions;" "without it, KMail cannot install out-of-" "office replies for you." "Please contact your system administrator." ) ); vbox->addWidget(lab); vbox->setAlignment(lab, Qt::AlignVCenter); lab->setWordWrap(true); w->setLayout(vbox); mStackWidget->addWidget(w); mStackWidget->setCurrentIndex(Script); setLayout(lay); } VacationPageWidget::~VacationPageWidget() { } void VacationPageWidget::setServerUrl(const KUrl &url) { mUrl = url; mVacationEditWidget->setEnabled(false); } void VacationPageWidget::setVacationManager(MultiImapVacationManager *vacationManager) { mVacationManager = vacationManager; connect(mVacationManager, SIGNAL(scriptAvailable(QString,QStringList,QString,QString,bool)), SLOT(slotGetResult(QString,QStringList,QString,QString,bool))); mVacationManager->checkVacation(mServerName, mUrl); } void VacationPageWidget::setServerName(const QString &serverName) { mServerName = serverName; } void VacationPageWidget::slotGetResult(const QString &serverName, const QStringList &sieveCapabilities, const QString &scriptName, const QString &script, bool active) { if (serverName != mServerName) { return; } kDebug() << serverName << sieveCapabilities << endl << scriptName << "(" << active << ")" << endl << "script:" << endl << script; if ( mUrl.protocol() == QLatin1String("sieve") && !sieveCapabilities.contains(QLatin1String("vacation")) ) { mStackWidget->setCurrentIndex(ScriptNotSupported); return; } mUrl.setFileName(scriptName); // Whether the server supports the "date" extension const bool supportsSieveDate = mUrl.protocol() == QLatin1String("sieve") && sieveCapabilities.contains(QLatin1String("date")); KSieveUi::VacationUtils::Vacation vacation = KSieveUi::VacationUtils::parseScript(script); if (!vacation.isValid() && !script.trimmed().isEmpty() ) { mVacationWarningWidget->setVisible(true); } mWasActive = active; mVacationEditWidget->setEnabled(true); mVacationEditWidget->setActivateVacation( active && vacation.active ); mVacationEditWidget->setMessageText( vacation.messageText ); mVacationEditWidget->setSubject( vacation.subject ); + mVacationEditWidget->setMailAction(vacation.mailAction, vacation.mailActionRecipient); mVacationEditWidget->setNotificationInterval( vacation.notificationInterval ); mVacationEditWidget->setMailAliases( vacation.aliases ); mVacationEditWidget->setSendForSpam( vacation.sendForSpam ); mVacationEditWidget->setDomainName( vacation.excludeDomain ); mVacationEditWidget->enableDomainAndSendForSpam( !VacationSettings::allowOutOfOfficeUploadButNoSettings() ); mVacationEditWidget->enableDates( supportsSieveDate ); if ( supportsSieveDate ) { mVacationEditWidget->setStartDate( vacation.startDate ); mVacationEditWidget->setStartTime(vacation.startTime); mVacationEditWidget->setEndDate( vacation.endDate ); mVacationEditWidget->setEndTime(vacation.endTime); } //emit scriptActive( mWasActive, mServerName ); } KSieveUi::VacationCreateScriptJob *VacationPageWidget::writeScript() { if (mPageScript == Script) { KSieveUi::VacationCreateScriptJob *createJob = new KSieveUi::VacationCreateScriptJob; createJob->setServerUrl(mUrl); createJob->setServerName(mServerName); const bool active = mVacationEditWidget->activateVacation(); VacationUtils::Vacation vacation; vacation.valid = true; vacation.active = active; vacation.messageText = mVacationEditWidget->messageText(); vacation.subject = mVacationEditWidget->subject(); + vacation.mailAction = mVacationEditWidget->mailAction(); + vacation.mailActionRecipient = mVacationEditWidget->mailActionRecipient(); vacation.notificationInterval = mVacationEditWidget->notificationInterval(); vacation.aliases = mVacationEditWidget->mailAliases(); vacation.sendForSpam = mVacationEditWidget->sendForSpam(); vacation.excludeDomain = mVacationEditWidget->domainName(); vacation.startDate = mVacationEditWidget->startDate(); vacation.startTime = mVacationEditWidget->startTime(); vacation.endDate = mVacationEditWidget->endDate(); vacation.endTime = mVacationEditWidget->endTime(); const QString script = VacationUtils::composeScript(vacation); createJob->setStatus(active, mWasActive); //Q_EMIT scriptActive( active, mServerName); createJob->setScript(script); return createJob; } return 0; } void VacationPageWidget::setDefault() { if (mVacationEditWidget->isEnabled()) mVacationEditWidget->setDefault(); } diff --git a/libksieve/ksieveui/vacation/vacationscriptextractor.cpp b/libksieve/ksieveui/vacation/vacationscriptextractor.cpp index 39e8ead43f..50a833bec4 100644 --- a/libksieve/ksieveui/vacation/vacationscriptextractor.cpp +++ b/libksieve/ksieveui/vacation/vacationscriptextractor.cpp @@ -1,219 +1,244 @@ /* Copyright (c) 2013, 2014 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; VacationDataExtractor::VacationDataExtractor() : KSieve::ScriptBuilder(), mContext( None ), mNotificationInterval( 0 ) , mActive(true) , mInIfBlock(false) + , mFoundInBlock(false) , mBlockLevel(0) , mLineStart(0) , mLineEnd(0) + , mMailAction(VacationUtils::Keep) + , mMailActionContext(None) { } VacationDataExtractor::~VacationDataExtractor() { } void VacationDataExtractor::commandStart( const QString & identifier, int lineNumber ) { if (identifier == QLatin1String("if") && mContext == None) { mContext = IfBlock; mLineStart = lineNumber; mInIfBlock = true; } + + if (commandFound() && (!mFoundInBlock || mBlockLevel > 0 )) { + if (identifier == QLatin1String("discard")) { + mMailAction = VacationUtils::Discard; + } else if (identifier == QLatin1String("redirect")) { + mMailAction = VacationUtils::Sendto; + mMailActionContext = RedirectCommand; + } + } + if ( identifier != QLatin1String("vacation") ) return; if (mContext != IfBlock) { mLineStart = lineNumber; } reset(); mContext = VacationCommand; + mFoundInBlock = (mBlockLevel > 0); } void VacationDataExtractor::commandEnd(int lineNumber) { if ( mContext != None && mContext != IfBlock && mContext != VacationEnd) { mContext = VacationEnd; mLineEnd = lineNumber; } + mMailActionContext = None; } void VacationDataExtractor::error( const KSieve::Error & e ) { kDebug() << e.asString() << "@" << e.line() << "," << e.column(); } void VacationDataExtractor::finished() { } void VacationDataExtractor::testStart(const QString &test) { if (mContext == IfBlock) { if (test == QLatin1String("true") || test == QLatin1String("false")) { mActive = (test == QLatin1String("true")); mIfComment = QString(); } } } void VacationDataExtractor::hashComment(const QString &comment) { if (mContext == IfBlock) { mIfComment += comment; } } void VacationDataExtractor::blockStart(int lineNumber) { mBlockLevel++; } void VacationDataExtractor::blockEnd(int lineNumber) { mBlockLevel--; if(mBlockLevel == 0 && !commandFound()) { //We are in main level again, and didn't found vacation in block mActive = true; mIfComment = QString(); } else if (mInIfBlock && mBlockLevel == 0 && commandFound()) { mLineEnd = lineNumber; mInIfBlock = false; } } void VacationDataExtractor::taggedArgument( const QString & tag ) { + if (mMailActionContext == RedirectCommand) { + if (tag == QLatin1String("copy")) { + mMailAction = VacationUtils::CopyTo; + } + } 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 VacationDataExtractor::stringArgument( const QString & string, bool, const QString & ) { + if (mMailActionContext == RedirectCommand) { + mMailActionRecipient = 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 VacationDataExtractor::numberArgument( unsigned long number, char ) { if ( mContext != Days ) return; if ( number > INT_MAX ) mNotificationInterval = INT_MAX; else mNotificationInterval = number; mContext = VacationCommand; } void VacationDataExtractor::stringListArgumentStart() { } void VacationDataExtractor::stringListEntry( const QString & string, bool, const QString & ) { if ( mContext != Addresses ) return; mAliases.push_back( string ); } void VacationDataExtractor::stringListArgumentEnd() { if ( mContext != Addresses ) return; mContext = VacationCommand; } void VacationDataExtractor::reset() { mContext = None; + mMailAction = VacationUtils::Keep; + mMailActionRecipient = QString(); mNotificationInterval = 0; mAliases.clear(); mMessageText.clear(); } RequireExtractor::RequireExtractor() : KSieve::ScriptBuilder() , mContext( None ) , mLineStart(0) , mLineEnd(0) { } RequireExtractor::~RequireExtractor() { } void RequireExtractor::commandStart(const QString &identifier, int lineNumber) { if (identifier == QLatin1String("require") && mContext == None) { mContext = RequireCommand; mLineStart = lineNumber; } } void RequireExtractor::commandEnd(int lineNumber) { if (mContext == RequireCommand) { mContext = EndState; mLineEnd = lineNumber; } } void RequireExtractor::error(const KSieve::Error &e) { kDebug() << e.asString() << "@" << e.line() << "," << e.column(); } void RequireExtractor::finished() { } void RequireExtractor::stringArgument(const QString &string, bool, const QString &) { mRequirements << string; } void RequireExtractor::stringListEntry(const QString &string, bool, const QString &) { mRequirements << string; } \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/vacationscriptextractor.h b/libksieve/ksieveui/vacation/vacationscriptextractor.h index a7663e6481..632f51dfbd 100644 --- a/libksieve/ksieveui/vacation/vacationscriptextractor.h +++ b/libksieve/ksieveui/vacation/vacationscriptextractor.h @@ -1,551 +1,560 @@ /* Copyright (c) 2013, 2014 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 VACATIONSCRIPTEXTRACTOR_H #define VACATIONSCRIPTEXTRACTOR_H #include "sieve-vacation.h" #include "util/util.h" +#include "vacationutils.h" #include #include #include #include #include #include #include #include #include namespace KSieveExt { class MultiScriptBuilder : public KSieve::ScriptBuilder { std::vector mBuilders; public: MultiScriptBuilder() : KSieve::ScriptBuilder() {} MultiScriptBuilder( KSieve::ScriptBuilder * sb1 ) : KSieve::ScriptBuilder(), mBuilders( 1 ) { mBuilders[0] = sb1; assert( sb1 ); } MultiScriptBuilder( KSieve::ScriptBuilder * sb1, KSieve::ScriptBuilder * sb2 ) : KSieve::ScriptBuilder(), mBuilders( 2 ) { mBuilders[0] = sb1; mBuilders[1] = sb2; assert( sb1 ); assert( sb2 ); } MultiScriptBuilder( KSieve::ScriptBuilder * sb1, KSieve::ScriptBuilder * sb2, KSieve::ScriptBuilder * sb3 ) : KSieve::ScriptBuilder(), mBuilders( 3 ) { mBuilders[0] = sb1; mBuilders[1] = sb2; mBuilders[2] = sb3; assert( sb1 ); assert( sb2 ); assert( sb3 ); } MultiScriptBuilder( KSieve::ScriptBuilder * sb1, KSieve::ScriptBuilder * sb2, KSieve::ScriptBuilder * sb3, KSieve::ScriptBuilder * sb4 ) : KSieve::ScriptBuilder(), mBuilders( 4 ) { mBuilders[0] = sb1; mBuilders[1] = sb2; mBuilders[2] = sb3; mBuilders[3] = sb4; assert( sb1 ); assert( sb2 ); assert( sb3 ); assert( sb4 ); } ~MultiScriptBuilder() {} private: #ifdef FOREACH #undef FOREACH #endif #define FOREACH for ( std::vector::const_iterator it = mBuilders.begin(), end = mBuilders.end() ; it != end ; ++it ) (*it)-> void commandStart( const QString & identifier, int lineNumber ) { FOREACH commandStart( identifier, lineNumber ); } void commandEnd(int lineNumber) { FOREACH commandEnd(lineNumber); } void testStart( const QString & identifier ) { FOREACH testStart( identifier ); } void testEnd() { FOREACH testEnd(); } void testListStart() { FOREACH testListStart(); } void testListEnd() { FOREACH testListEnd(); } void blockStart(int lineNumber) { FOREACH blockStart(lineNumber); } void blockEnd(int lineNumber) { FOREACH blockEnd(lineNumber); } void hashComment( const QString & comment ) { FOREACH hashComment( comment ); } void bracketComment( const QString & comment ) { FOREACH bracketComment( comment ); } void lineFeed() { FOREACH lineFeed(); } void error( const KSieve::Error & e ) { FOREACH error( e ); } void finished() { FOREACH finished(); } void taggedArgument( const QString & tag ) { FOREACH taggedArgument( tag ); } void stringArgument( const QString & string, bool multiline, const QString & fixme ) { FOREACH stringArgument( string, multiline, fixme ); } void numberArgument( unsigned long number, char quantifier ) { FOREACH numberArgument( number, quantifier ); } void stringListArgumentStart() { FOREACH stringListArgumentStart(); } void stringListEntry( const QString & string, bool multiline, const QString & fixme) { FOREACH stringListEntry( string, multiline, fixme ); } void stringListArgumentEnd() { FOREACH stringListArgumentEnd(); } #undef FOREACH }; } namespace KSieveUi { class GenericInformationExtractor : public KSieve::ScriptBuilder { public: enum BuilderMethod { Any, TaggedArgument, StringArgument, NumberArgument, CommandStart, CommandEnd, TestStart, TestEnd, TestListStart, TestListEnd, BlockStart, BlockEnd, StringListArgumentStart, StringListEntry, StringListArgumentEnd }; struct StateNode { // expectation: int depth; BuilderMethod method; const char * string; // actions: int if_found; int if_not_found; const char * save_tag; }; const std::vector mNodes; std::map mResults; std::set mRecursionGuard; unsigned int mState; int mNestingDepth; int mLineNumber; public: GenericInformationExtractor( const std::vector & nodes ) : KSieve::ScriptBuilder(), mNodes( nodes ), mState( 0 ), mNestingDepth( 0 ), mLineNumber(0) {} const std::map & results() const { return mResults; } private: virtual void process( BuilderMethod method, const QString & string=QString() ) { doProcess( method, string ); mRecursionGuard.clear(); } void doProcess( BuilderMethod method, const QString & string ) { mRecursionGuard.insert( mState ); bool found = true; const StateNode & expected = mNodes[mState]; if ( expected.depth != -1 && mNestingDepth != expected.depth ) found = false; if ( expected.method != Any && method != expected.method ) found = false; if ( const char * str = expected.string ) if ( string.toLower() != QString::fromUtf8( str ).toLower() ) found = false; /*kDebug() << ( found ?"found:" :"not found:" ) << mState << "->" << ( found ? expected.if_found : expected.if_not_found );*/ mState = found ? expected.if_found : expected.if_not_found ; assert( mState < mNodes.size() ); if ( found ) if ( const char * save_tag = expected.save_tag ) { mResults[QString::fromLatin1(save_tag)] = string; } if ( !found && !mRecursionGuard.count( mState ) ) { doProcess( method, string ); } } void commandStart( const QString & identifier, int lineNumber ) { process( CommandStart, identifier ); } void commandEnd(int lineNumber) { process( CommandEnd ); } void testStart( const QString & identifier ) { process( TestStart, identifier ); } void testEnd() { process( TestEnd ); } void testListStart() { process( TestListStart ); } void testListEnd() { process( TestListEnd ); } void blockStart(int lineNumber) { process( BlockStart ); ++mNestingDepth; } void blockEnd(int lineNumber) { --mNestingDepth; process( BlockEnd ); } void hashComment( const QString & ) { } void bracketComment( const QString & ) { } void lineFeed() { ++mLineNumber; } void error( const KSieve::Error & ) { kDebug() ; mState = 0; } void finished() { } void taggedArgument( const QString & tag ) { process( TaggedArgument, tag ); } void stringArgument( const QString & string, bool, const QString & ) { process( StringArgument, string ); } void numberArgument( unsigned long number, char ) { process( NumberArgument, QString::number( number ) ); } void stringListArgumentStart() { process( StringListArgumentStart ); } void stringListEntry( const QString & string, bool, const QString & ) { process( StringListEntry, string ); } void stringListArgumentEnd() { process( StringListArgumentEnd ); } }; typedef GenericInformationExtractor GIE; static const GenericInformationExtractor::StateNode spamNodes[] = { { 0, GIE::CommandStart, "if", 1, 0, 0 }, // 0 { 0, GIE::TestStart, "allof", 2, 3, 0 }, // 1 { 0, GIE::TestListStart, 0, 3, 0, 0 }, // 2 { 0, GIE::TestStart, "not", 4, 3, 0 }, // 3 { 0, GIE::TestStart, "header", 5, 3, 0 }, // 4 { 0, GIE::TaggedArgument, "contains", 6, 0, 0 }, // 5 // accept both string and string-list: { 0, GIE::StringArgument, "x-spam-flag", 12, 7, "x-spam-flag" }, // 6 { 0, GIE::StringListArgumentStart, 0, 8, 0, 0 }, // 7 { 0, GIE::StringListEntry, "x-spam-flag", 9, 10, "x-spam-flag" }, // 8 { 0, GIE::StringListEntry, 0, 9, 11, 0 }, // 9 { 0, GIE::StringListArgumentEnd, 0, 0, 8, 0 }, // 10 { 0, GIE::StringListArgumentEnd, 0, 12, 0, 0 }, // 11 // accept both string and string-list: { 0, GIE::StringArgument, "yes", 18, 13, "spam-flag-yes" }, // 12 { 0, GIE::StringListArgumentStart, 0, 14, 0, 0 }, // 13 { 0, GIE::StringListEntry, "yes", 15, 16, "spam-flag-yes" }, // 14 { 0, GIE::StringListEntry, 0, 15, 17, 0 }, // 15 { 0, GIE::StringListArgumentEnd, 0, 0, 14, 0 }, // 16 { 0, GIE::StringListArgumentEnd, 0, 18, 0, 0 }, // 17 { 0, GIE::TestEnd, 0, 21, 20, 0 }, // 18 { 0, GIE::Any, 0, 21, 0, 0 }, // 19 { 0, GIE::TestListEnd, 0, 21, 19, 0 }, // 20 // block of command, find "stop", take nested if's into account: { 0, GIE::BlockStart, 0, 22, 18, 0 }, // 21 { 1, GIE::CommandStart, "vacation", 24, 22, "vacation" }, // 22 { 1, GIE::Any, 0, 24, 0, 0 }, // 23 { 0, GIE::BlockEnd, 0, 25, 23, 0 }, // 24 { -1, GIE::Any, 0, 25, 25, 0 }, // 25 end state }; static const unsigned int numSpamNodes = sizeof spamNodes / sizeof *spamNodes ; class SpamDataExtractor : public GenericInformationExtractor { public: SpamDataExtractor() : GenericInformationExtractor( std::vector( spamNodes, spamNodes + numSpamNodes ) ) { } bool found() const { return mResults.count( QLatin1String("x-spam-flag") ) && mResults.count( QLatin1String("spam-flag-yes") ) && mResults.count( QLatin1String("vacation") ) ; } }; // 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, 0 }, // 0 { 0, GIE::TestStart, "allof", 2, 3, 0 }, // 1 { 0, GIE::TestListStart, 0, 3, 0, 0 }, // 2 { 0, GIE::TestStart, "address", 4, 3, 0 }, // 3 // :domain and :contains in arbitrary order: { 0, GIE::TaggedArgument, "domain", 5, 6, 0 }, // 4 { 0, GIE::TaggedArgument, "contains", 8, 0, 0 }, // 5 { 0, GIE::TaggedArgument, "contains", 7, 0, 0 }, // 6 { 0, GIE::TaggedArgument, "domain", 8, 0, 0 }, // 7 // accept both string and string-list: { 0, GIE::StringArgument, "from", 14, 9, "from" }, // 8 { 0, GIE::StringListArgumentStart, 0, 10, 0, 0 }, // 9 { 0, GIE::StringListEntry, "from", 11, 12, "from" }, // 10 { 0, GIE::StringListEntry, 0, 11, 13, 0 }, // 11 { 0, GIE::StringListArgumentEnd, 0, 0, 10, 0 }, // 12 { 0, GIE::StringListArgumentEnd, 0, 14, 0, 0 }, // 13 // string: save, string-list: save last { 0, GIE::StringArgument, 0, 18, 15, "domainName" }, // 14 { 0, GIE::StringListArgumentStart, 0, 16, 0, 0 }, // 15 { 0, GIE::StringListEntry, 0, 16, 17, "domainName" }, // 16 { 0, GIE::StringListArgumentEnd, 0, 18, 0, 0 }, // 17 { 0, GIE::TestEnd, 0, 18, 20, 0 }, // 18 { 0, GIE::Any, 0, 18, 0, 0 }, // 19 // block of commands, find "stop", take nested if's into account: { 0, GIE::BlockStart, 0, 21, 19, 0 }, // 20 { 1, GIE::CommandStart, "vacation", 23, 21, "vacation" }, // 21 { 1, GIE::Any, 0, 23, 0, 0 }, // 22 { 0, GIE::BlockEnd, 0, 24, 22, 0 }, // 23 { -1, GIE::Any, 0, 24, 24, 0 } // 24 end state }; static const unsigned int numDomainNodes = sizeof domainNodes / sizeof *domainNodes ; class DomainRestrictionDataExtractor : public GenericInformationExtractor { public: DomainRestrictionDataExtractor() : GenericInformationExtractor( std::vector( domainNodes, domainNodes+numDomainNodes ) ) { } QString domainName() /*not const, since map::op[] isn't const*/ { return mResults.count( QLatin1String("vacation") ) && mResults.count( QLatin1String("from") ) ? mResults[QLatin1String("domainName")] : QString(); } }; // if not allof (currentdate :value "ge" date "YYYY-MM-DD", // currentfate :value "le" date "YYYY-MM-DD) { keep; stop; } static const GenericInformationExtractor::StateNode datesNodes[] = { { 0, GIE::CommandStart, "if", 1, 0, 0 }, // 0 { 0, GIE::TestStart, "allof", 2, 0, 0 }, // 1 // handle startDate and endDate in arbitrary order { 0, GIE::TestListStart, 0, 3, 0, 0 }, // 2 { 0, GIE::TestStart, "currentdate", 4, 3, 0 }, // 3 { 0, GIE::TaggedArgument, "value", 5, 4, 0 }, // 4 { 0, GIE::StringArgument, "ge", 6, 10, 0 }, // 5 { 0, GIE::StringArgument, "date", 7, 8, 0 }, // 6 { 0, GIE::StringArgument, 0, 15, 0, "startDate" }, // 7 { 0, GIE::StringArgument, "iso8601", 9, 0, 0 }, // 8 { 0, GIE::StringArgument, 0, 15, 0, "startDateTime" },// 9 { 0, GIE::StringArgument, "le", 11, 0, 0 }, // 10 { 0, GIE::StringArgument, "date", 12, 13, 0 }, // 11 { 0, GIE::StringArgument, 0, 15, 0, "endDate" }, // 12 { 0, GIE::StringArgument, "iso8601", 14, 0, 0 }, // 13 { 0, GIE::StringArgument, 0, 15, 0, "endDateTime" }, // 14 { 0, GIE::TestEnd, 0, 16, 0, 0 }, // 15 { 0, GIE::TestStart, "currentdate", 17, 16, 0 }, // 16 { 0, GIE::TaggedArgument, "value", 18, 17, 0 }, // 17 { 0, GIE::StringArgument, "le", 19, 23, 0 }, // 18 { 0, GIE::StringArgument, "date", 20, 21, 0 }, // 19 { 0, GIE::StringArgument, 0, 28, 0, "endDate" }, // 20 { 0, GIE::StringArgument, "iso8601", 22, 0, 0 }, // 21 { 0, GIE::StringArgument, 0, 28, 0, "endDateTime" }, // 22 { 0, GIE::StringArgument, "ge", 24, 0, 0 }, // 23 { 0, GIE::StringArgument, "date", 25, 26, 0 }, // 24 { 0, GIE::StringArgument, 0, 28, 0, "startDate" }, // 25 { 0, GIE::StringArgument, "iso8601", 27, 0, 0 }, // 26 { 0, GIE::StringArgument, 0, 28, 0, "startDateTime" }, // 27 { 0, GIE::TestEnd, 0, 32, 0, 0 }, // 28 { 0, GIE::TestStart, 0, 31, 30, 0 }, // 29 { -1, GIE::Any, 0, 32, 0, 0 }, // 30 { 0, GIE::TestEnd, 0, 32, 30, 0 }, // 31 { 0, GIE::TestListEnd, 0, 33, 29, 0 }, // 32 { 0, GIE::TestEnd, 0, 34, 0, 0 }, // 33 // block of commands, find "stop", take nested if's into account: { 0, GIE::BlockStart, 0, 36, 33, 0 }, // 34 { -1, GIE::Any, 0, 36, 0, 0 }, // 35 { 1, GIE::CommandStart, "vacation", 38, 35, "vacation" }, // 36 { -1, GIE::Any, 0, 38, 0, 0 }, // 37 { 0, GIE::BlockEnd, 0, 39, 37, 0 }, // 38 { -1, GIE::Any, 0, 39, 39, 0 } // 39 end state }; static const unsigned int numDatesNodes = sizeof datesNodes / sizeof *datesNodes; class DateExtractor : public GenericInformationExtractor { public: DateExtractor() : GenericInformationExtractor( std::vector( datesNodes, datesNodes+numDatesNodes ) ) { } QDate endDate() { if (mResults.count(QLatin1String("endDateTime")) == 1) { return datetime(QLatin1String("endDateTime")).date(); } else { return date(QLatin1String("endDate")); } } QDate startDate() { if (mResults.count(QLatin1String("startDateTime")) == 1) { return datetime(QLatin1String("startDateTime")).date(); } else { return date(QLatin1String("startDate")); } } QTime endTime() { return datetime(QLatin1String("endDateTime")).time(); } QTime startTime() { return datetime(QLatin1String("startDateTime")).time(); } private: QDate date(const QString &name ) { if (mResults.count( name ) == 0) { return QDate(); } else { return QDate::fromString( mResults[name], Qt::ISODate ); } } QDateTime datetime(const QString &name ) { if (mResults.count(name) == 0) { return QDateTime(); } else { return QDateTime::fromString( mResults[name], Qt::ISODate ); } } }; class VacationDataExtractor : public KSieve::ScriptBuilder { enum Context { None = 0, // command itself: VacationCommand, // tagged args: Days, Addresses, Subject, VacationEnd, - IfBlock + IfBlock, + RedirectCommand }; public: VacationDataExtractor(); virtual ~VacationDataExtractor(); bool commandFound() const { return mContext == VacationEnd; } bool active() const { return mActive; } int notificationInterval() const { return mNotificationInterval; } const QString & messageText() const { return mMessageText; } const QStringList & aliases() const { return mAliases; } const QString &ifComment() const { return mIfComment; } + VacationUtils::MailAction mailAction() const {return mMailAction;} + const QString &mailActionRecipient() const {return mMailActionRecipient;} const QString &subject() const { return mSubject; } int lineStart() const {return mLineStart;} int lineEnd() const {return mLineEnd;} private: void commandStart( const QString & identifier, int lineNumber ); void commandEnd(int lineNumber); void testStart( const QString &); void testEnd() {} void testListStart() {} void testListEnd() {} void blockStart(int lineNumber); void blockEnd(int lineNumber); void hashComment( const QString & ); void bracketComment( const QString &c ) {} void lineFeed() {} void error( const KSieve::Error & e ); void finished(); void taggedArgument( const QString & tag ); void stringArgument( const QString & string, bool, const QString & ); void numberArgument( unsigned long number, char ); void stringListArgumentStart(); void stringListEntry( const QString & string, bool, const QString & ); void stringListArgumentEnd(); private: Context mContext; int mNotificationInterval; QString mMessageText; QString mSubject; QStringList mAliases; bool mActive; bool mInIfBlock; + bool mFoundInBlock; int mBlockLevel; QString mIfComment; int mLineStart; int mLineEnd; + Context mMailActionContext; + VacationUtils::MailAction mMailAction; + QString mMailActionRecipient; + void reset(); }; class RequireExtractor : public KSieve::ScriptBuilder { enum Context { None = 0, // command itself: RequireCommand, EndState }; public: RequireExtractor(); virtual ~RequireExtractor(); bool commandFound() const { return mContext == EndState; } const QStringList &requirements() const { return mRequirements; } int lineStart() const {return mLineStart;} int lineEnd() const {return mLineEnd;} private: void commandStart( const QString & identifier, int lineNumber ); void commandEnd(int lineNumber); void testStart( const QString &) {} void testEnd() {} void testListStart() {} void testListEnd() {} void blockStart(int lineNumber){}; void blockEnd(int lineNumber){}; void hashComment( const QString & ) {} void bracketComment( const QString & ) {} void lineFeed() {} void error( const KSieve::Error & e ); void finished(); void taggedArgument( const QString & tag ) {} void numberArgument( unsigned long number, char ) {} void stringArgument( const QString & string, bool, const QString & ); void stringListArgumentStart(){} void stringListEntry( const QString & string, bool, const QString & ); void stringListArgumentEnd(){} private: Context mContext; QStringList mRequirements; int mLineStart; int mLineEnd; }; } #endif // VACATIONSCRIPTEXTRACTOR_H diff --git a/libksieve/ksieveui/vacation/vacationutils.cpp b/libksieve/ksieveui/vacation/vacationutils.cpp index d34ab19448..44e067f0fd 100644 --- a/libksieve/ksieveui/vacation/vacationutils.cpp +++ b/libksieve/ksieveui/vacation/vacationutils.cpp @@ -1,425 +1,470 @@ /* Copyright (c) 2013, 2014 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 "vacationutils.h" #include "vacationscriptextractor.h" #include "sieve-vacation.h" #include #include #include #include #include #include using KMime::Types::AddrSpecList; static inline QString dotstuff( QString s ) { // krazy:exclude=passbyvalue if ( s.startsWith( QLatin1Char('.') ) ) return QLatin1Char('.') + s.replace( QLatin1String("\n."), QLatin1String("\n..") ); else return s.replace( QLatin1String("\n."), QLatin1String("\n..") ); } static inline QString stringReplace(QString s) { s = s.replace(QRegExp(QLatin1String("[\n\t]+")),QLatin1String(" ")); return s.replace(QLatin1Char('\"'),QLatin1String("\\\"")); } +QString KSieveUi::VacationUtils::mailAction(KSieveUi::VacationUtils::MailAction action) +{ + switch (action) { + case Keep: + return i18n("Keep"); + case Discard: + return i18n("Discard"); + case Sendto: + return i18n("Redirect to"); + case CopyTo: + return i18n("Copy to"); + default: + kWarning() << "Unknown mail action" << action; + return i18n("Unkown action"); + } +} + +KSieveUi::VacationUtils::MailAction KSieveUi::VacationUtils::defaultMailAction() +{ + return KSieveUi::VacationUtils::Keep; +} + QString KSieveUi::VacationUtils::defaultSubject() { return i18n("Out of office till %1", QLocale().toString(QDate::currentDate().addDays(1))); } QString KSieveUi::VacationUtils::defaultMessageText() { return i18n( "I am out of office till %1.\n" "\n" "In urgent cases, please contact Mrs. \"vacation replacement\"\n" "\n" "email: \"email address of vacation replacement\"\n" "phone: +49 711 1111 11\n" "fax.: +49 711 1111 12\n" "\n" "Yours sincerely,\n" "-- \"enter your name and email address here\"\n", KGlobal::locale()->formatDate( QDate::currentDate().addDays( 1 ) ) ); } int KSieveUi::VacationUtils::defaultNotificationInterval() { return 7; // days } KMime::Types::AddrSpecList KSieveUi::VacationUtils::defaultMailAliases() { KMime::Types::AddrSpecList sl; KPIMIdentities::IdentityManager manager( true ); KPIMIdentities::IdentityManager::ConstIterator end(manager.end()); for ( KPIMIdentities::IdentityManager::ConstIterator it = manager.begin(); it != end ; ++it ) { if ( !(*it).primaryEmailAddress().isEmpty() ) { KMime::Types::Mailbox a; a.fromUnicodeString((*it).primaryEmailAddress()); sl.push_back(a.addrSpec()); } foreach(const QString &email, (*it).emailAliases()) { KMime::Types::Mailbox a; a.fromUnicodeString(email); sl.push_back(a.addrSpec()); } } return sl; } bool KSieveUi::VacationUtils::defaultSendForSpam() { return VacationSettings::outOfOfficeReactToSpam(); } QString KSieveUi::VacationUtils::defaultDomainName() { return VacationSettings::outOfOfficeDomain(); } QDate KSieveUi::VacationUtils::defaultStartDate() { return QDate::currentDate(); } QDate KSieveUi::VacationUtils::defaultEndDate() { return defaultStartDate().addDays(7); } KSieveUi::VacationUtils::Vacation KSieveUi::VacationUtils::parseScript(const QString &script) { KSieveUi::VacationUtils::Vacation vacation; if ( script.trimmed().isEmpty() ) { vacation.valid = false; vacation.active = false; + vacation.mailAction = VacationUtils::defaultMailAction(); vacation.messageText = VacationUtils::defaultMessageText(); vacation.subject = VacationUtils::defaultSubject(); vacation.notificationInterval = VacationUtils::defaultNotificationInterval(); vacation.aliases = VacationUtils::defaultMailAliases(); vacation.sendForSpam = VacationUtils::defaultSendForSpam(); vacation.excludeDomain = VacationUtils::defaultDomainName(); return vacation; } // 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(); //kDebug() << "scriptUtf8 = \"" + scriptUTF8 +"\""; KSieve::Parser parser( scriptUTF8.begin(), scriptUTF8.begin() + scriptUTF8.length() ); VacationDataExtractor vdx; SpamDataExtractor sdx; DomainRestrictionDataExtractor drdx; DateExtractor dx; KSieveExt::MultiScriptBuilder tsb( &vdx , &sdx, &drdx, &dx ); parser.setScriptBuilder( &tsb ); parser.parse(); if ( !parser.parse() || !vdx.commandFound() ) { vacation.active = false; vacation.valid = false; return vacation; } vacation.valid = true; vacation.active = vdx.active(); + vacation.mailAction = vdx.mailAction(); + vacation.mailActionRecipient = vdx.mailActionRecipient(); vacation.messageText = vdx.messageText().trimmed(); if (!vdx.subject().isEmpty()) { vacation.subject = vdx.subject().trimmed(); } vacation.notificationInterval = vdx.notificationInterval(); vacation.aliases = KMime::Types::AddrSpecList(); foreach(const QString &alias, vdx.aliases()) { KMime::Types::Mailbox a; a.fromUnicodeString(alias); vacation.aliases.append(a.addrSpec()); } if (!vacation.active && !vdx.ifComment().isEmpty()) { const QByteArray newScript = QString::fromAscii("if ").toUtf8() + vdx.ifComment().toUtf8() + QString::fromLatin1("{vacation;}").toUtf8(); tsb = KSieveExt::MultiScriptBuilder( &sdx, &drdx, &dx ); KSieve::Parser parser( newScript.begin(), newScript.begin() + newScript.length() ); parser.setScriptBuilder( &tsb ); if ( !parser.parse() ) { vacation.valid = false; return vacation; } } vacation.sendForSpam = !sdx.found(); vacation.excludeDomain = drdx.domainName(); vacation.startDate = dx.startDate(); vacation.startTime = dx.startTime(); vacation.endDate = dx.endDate(); vacation.endTime = dx.endTime(); return vacation; } QString composeOldScript( 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('\\'), QLatin1String("\\\\") ).replace( QLatin1Char('"'), QLatin1String("\\\"") ) + QLatin1Char('"') ); aliases.push_back( (*it).asString() ); } addressesArgument += sl.join( QLatin1String(", ") ) + QLatin1String(" ] "); } QString script; if ( startDate.isValid() && endDate.isValid() ) { script = QString::fromLatin1("require [\"vacation\", \"relational\", \"date\"];\n\n" ); } else { script = QString::fromLatin1("require \"vacation\";\n\n" ); } if ( !sendForSpam ) script += QString::fromLatin1( "if header :contains \"X-Spam-Flag\" \"YES\"" " { keep; stop; }\n" ); // FIXME? if ( !domain.isEmpty() ) // FIXME script += QString::fromLatin1( "if not address :domain :contains \"from\" \"%1\" { keep; stop; }\n" ).arg( domain ); if ( startDate.isValid() && endDate.isValid() ) { script += QString::fromLatin1( "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 += QString::fromLatin1(":days %1 ").arg( notificationInterval ); if (!subject.trimmed().isEmpty()) { script += QString::fromLatin1(":subject \"%1\" ").arg(stringReplace(subject).trimmed()); } script += QString::fromLatin1("text:\n"); script += dotstuff( messageText.isEmpty() ? KSieveUi::VacationUtils::defaultMessageText() : messageText ); script += QString::fromLatin1( "\n.\n;\n" ); return script; } QString KSieveUi::VacationUtils::composeScript(const Vacation &vacation) { QStringList condition; + QStringList require; + + require << QLatin1String("vacation"); + + if (vacation.startDate.isValid() || vacation.endDate.isValid()) { + require << QLatin1String("date"); + require << QLatin1String("relational"); + } if (vacation.startDate.isValid()) { if (vacation.startTime.isValid()) { KDateTime start(vacation.startDate, vacation.startTime); condition.append(QString::fromLatin1("currentdate :value \"ge\" \"iso8601\" \"%1\"") .arg(start.toString(KDateTime::ISODate))); } else { condition.append(QString::fromLatin1("currentdate :value \"ge\" \"date\" \"%1\"") .arg(vacation.startDate.toString(Qt::ISODate))); } } if (vacation.endDate.isValid()) { if (vacation.endTime.isValid()) { KDateTime end(vacation.endDate, vacation.endTime); condition.append(QString::fromLatin1("currentdate :value \"le\" \"iso8601\" \"%1\"") .arg(end.toString(KDateTime::ISODate))); } else { condition.append(QString::fromLatin1("currentdate :value \"le\" \"date\" \"%1\"") .arg(vacation.endDate.toString(Qt::ISODate))); } } if (!vacation.sendForSpam) { condition.append(QString::fromLatin1("not header :contains \"X-Spam-Flag\" \"YES\"")); } if (!vacation.excludeDomain.isEmpty()) { condition.append(QString::fromLatin1("address :domain :contains \"from\" \"%1\"").arg( vacation.excludeDomain )); } QString addressesArgument; QStringList aliases; if ( !vacation.aliases.empty() ) { addressesArgument += QLatin1String(":addresses [ "); QStringList sl; AddrSpecList::const_iterator end = vacation.aliases.constEnd(); for ( AddrSpecList::const_iterator it = vacation.aliases.begin() ; it != end; ++it ) { sl.push_back( QLatin1Char('"') + (*it).asString().replace( QLatin1Char('\\'), QLatin1String("\\\\") ).replace( QLatin1Char('"'), QLatin1String("\\\"") ) + QLatin1Char('"') ); aliases.push_back( (*it).asString() ); } addressesArgument += sl.join( QLatin1String(", ") ) + QLatin1String(" ] "); } QString sVacation(QLatin1String("vacation ")); sVacation += addressesArgument; if ( vacation.notificationInterval > 0 ) sVacation += QString::fromLatin1(":days %1 ").arg(vacation.notificationInterval); if (!vacation.subject.trimmed().isEmpty()) { sVacation += QString::fromLatin1(":subject \"%1\" ").arg(stringReplace(vacation.subject).trimmed()); } sVacation += QString::fromLatin1("text:\n"); sVacation += dotstuff( vacation.messageText.isEmpty() ? VacationUtils::defaultMessageText() : vacation.messageText ); sVacation += QString::fromLatin1( "\n.\n;" ); + switch (vacation.mailAction) { + case VacationUtils::Keep: + break; + case VacationUtils::Discard: + sVacation += QLatin1String("\ndiscard;"); + break; + case VacationUtils::Sendto: + sVacation += QLatin1String("\nredirect \"") + vacation.mailActionRecipient + QLatin1String("\";"); + break; + case VacationUtils::CopyTo: + require << QLatin1String("copy"); + sVacation += QLatin1String("\nredirect :copy \"") + vacation.mailActionRecipient + QLatin1String("\";"); + break; + } + QString script; - if ( vacation.startDate.isValid() || vacation.endDate.isValid() ) { - script = QString::fromLatin1("require [\"vacation\", \"relational\", \"date\"];\n\n" ); - } else { - script = QString::fromLatin1("require \"vacation\";\n\n" ); - } + script = QLatin1String("require [\"%1\"];\n\n"); + script = script.arg(require.join(QLatin1String("\", \""))); if (condition.count() == 0) { if (vacation.active) { script += sVacation; } else { script += QString::fromLatin1("if false\n{\n\t"); script += sVacation; script += QLatin1String("\n}"); } } else { if (vacation.active) { script += QString::fromLatin1("if allof(%1)\n{\n\t").arg(condition.join(QLatin1String(", "))); } else { script += QString::fromLatin1("if false # allof(%1)\n{\n\t").arg(condition.join(QLatin1String(", "))); } script += sVacation; script += QLatin1String("\n}"); } script += QLatin1String("\n"); return script; } QString KSieveUi::VacationUtils::mergeRequireLine(const QString &script, const QString scriptUpdate) { const QByteArray scriptUTF8 = script.trimmed().toUtf8(); const QByteArray scriptUpdateUTF8 = scriptUpdate.trimmed().toUtf8(); if (scriptUTF8.isEmpty()) { return scriptUpdate; } if (scriptUpdateUTF8.isEmpty()) { return script; } KSieve::Parser parser( scriptUTF8.begin(), scriptUTF8.begin() + scriptUTF8.length() ); KSieve::Parser parserUpdate( scriptUpdateUTF8.begin(), scriptUpdateUTF8.begin() + scriptUpdateUTF8.length() ); RequireExtractor rx, rxUpdate; parser.setScriptBuilder(&rx); parserUpdate.setScriptBuilder(&rxUpdate); int insert(0); QStringList lines = script.split(QLatin1Char('\n')); QSet requirements; if (parser.parse() && rx.commandFound()) { insert = rx.lineStart(); const int endOld(rx.lineEnd()); for (int i=insert; i<=endOld; i++) { lines.removeAt(insert); } requirements = rx.requirements().toSet(); } if (parserUpdate.parse() && rxUpdate.commandFound()) { requirements += rxUpdate.requirements().toSet(); } if (requirements.count() > 1) { QStringList req = requirements.toList(); req.sort(); lines.insert(insert, QString::fromLatin1("require [\"%1\"];").arg(req.join(QLatin1String("\", \"")))); } else if (requirements.count() == 1) { lines.insert(insert, QString::fromLatin1("require \"%1\";").arg(requirements.toList().first())); } return lines.join(QLatin1String("\n")); } QString KSieveUi::VacationUtils::updateVacationBlock(const QString &oldScript, const QString &newScript) { const QByteArray oldScriptUTF8 = oldScript.trimmed().toUtf8(); const QByteArray newScriptUTF8 = newScript.trimmed().toUtf8(); if (oldScriptUTF8.isEmpty()) { return newScript; } if (newScriptUTF8.isEmpty()) { return oldScript; } KSieve::Parser parserOld( oldScriptUTF8.begin(), oldScriptUTF8.begin() + oldScriptUTF8.length() ); KSieve::Parser parserNew( newScriptUTF8.begin(), newScriptUTF8.begin() + newScriptUTF8.length() ); VacationDataExtractor vdxOld, vdxNew; RequireExtractor rx; KSieveExt::MultiScriptBuilder tsb( &vdxOld , &rx ); parserOld.setScriptBuilder(&tsb); parserNew.setScriptBuilder(&vdxNew); int startOld(0); QStringList lines = oldScript.split(QLatin1Char('\n')); QString script; if (parserOld.parse() && vdxOld.commandFound()) { startOld = vdxOld.lineStart(); const int endOld(vdxOld.lineEnd()); for (int i=startOld; i<=endOld; i++) { lines.removeAt(startOld); } } else { if (rx.commandFound()) { // after require startOld = rx.lineEnd() + 1; } else { startOld = 0; } } if (parserNew.parse() && vdxNew.commandFound()) { const int startNew(vdxNew.lineStart()); const int endNew(vdxNew.lineEnd()); QStringList linesNew = newScript.split(QLatin1Char('\n')); for(int i=endNew;i>=startNew;i--) { lines.insert(startOld, linesNew.at(i)); } } return lines.join(QLatin1String("\n")); } diff --git a/libksieve/ksieveui/vacation/vacationutils.h b/libksieve/ksieveui/vacation/vacationutils.h index 066bcc6358..b492a60072 100644 --- a/libksieve/ksieveui/vacation/vacationutils.h +++ b/libksieve/ksieveui/vacation/vacationutils.h @@ -1,65 +1,78 @@ /* Copyright (c) 2013, 2014 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 VACATIONUTILS_H #define VACATIONUTILS_H #include #include #include #include namespace KSieveUi { namespace VacationUtils { + +enum MailAction { + Keep, + Discard, + Sendto, + CopyTo, +}; + QString defaultMessageText(); QString defaultSubject(); +MailAction defaultMailAction(); int defaultNotificationInterval(); KMime::Types::AddrSpecList defaultMailAliases(); bool defaultSendForSpam(); QString defaultDomainName(); QDate defaultStartDate(); QDate defaultEndDate(); struct Vacation { - Vacation():valid(false), active(false), notificationInterval(1), sendForSpam(true) {} + Vacation():valid(false), active(false), notificationInterval(1), sendForSpam(true), mailAction(Keep) {} bool isValid() const {return valid;} + MailAction mailAction; + QString mailActionRecipient; bool valid; QString messageText; QString subject; bool active; int notificationInterval; KMime::Types::AddrSpecList aliases; bool sendForSpam; QString excludeDomain; QDate startDate; QTime startTime; QDate endDate; QTime endTime; }; QString composeScript(const Vacation &vacation); KSieveUi::VacationUtils::Vacation parseScript(const QString &script); QString mergeRequireLine(const QString &script1, const QString script2); QString updateVacationBlock(const QString &oldScript, const QString &newScript); +QString mailAction(MailAction action); + } } #endif // VACATIONUTILS_H