Page MenuHomePhorge

D31.id61.diff
No OneTemporary

D31.id61.diff

Index: libksieve/ksieve/scriptbuilder.h
===================================================================
--- libksieve/ksieve/scriptbuilder.h
+++ libksieve/ksieve/scriptbuilder.h
@@ -51,8 +51,8 @@
virtual void stringListEntry( const QString & string, bool multiLine, const QString & embeddedHashComment ) = 0;
virtual void stringListArgumentEnd() = 0;
- virtual void commandStart( const QString & identifier ) = 0;
- virtual void commandEnd() = 0;
+ virtual void commandStart( const QString & identifier, int lineNumber ) = 0;
+ virtual void commandEnd(int lineNumber) = 0;
virtual void testStart( const QString & identifier ) = 0;
virtual void testEnd() = 0;
@@ -60,8 +60,8 @@
virtual void testListStart() = 0;
virtual void testListEnd() = 0;
- virtual void blockStart() = 0;
- virtual void blockEnd() = 0;
+ virtual void blockStart(int lineNumber) = 0;
+ virtual void blockEnd(int lineNumber) = 0;
/** A hash comment always includes an implicit lineFeed() at it's end. */
virtual void hashComment( const QString & comment ) = 0;
Index: libksieve/ksieveui/CMakeLists.txt
===================================================================
--- libksieve/ksieveui/CMakeLists.txt
+++ libksieve/ksieveui/CMakeLists.txt
@@ -153,6 +153,7 @@
widgets/managesievewidget.cpp
debug/sievedebugdialog.cpp
util/util.cpp
+ managescriptsjob/checkkep14supportjob.cpp
managescriptsjob/generateglobalscriptjob.cpp
managescriptsjob/parseuserscriptjob.cpp
templates/sievetemplatewidget.cpp
Index: libksieve/ksieveui/managescriptsjob/checkkep14supportjob.h
===================================================================
--- libksieve/ksieveui/managescriptsjob/checkkep14supportjob.h
+++ libksieve/ksieveui/managescriptsjob/checkkep14supportjob.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2013, 2014 Montel Laurent <montel@kde.org>
+ Copyright (c) 2015 Sandro Knauß <knauss@kolabsys.com>
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
@@ -15,10 +15,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef VACATIONCREATESCRIPTJOB_H
-#define VACATIONCREATESCRIPTJOB_H
+#ifndef CHECKKEP14SUPPORTJOB_H
+#define CHECKKEP14SUPPORTJOB_H
#include <QObject>
+#include <QStringList>
#include "ksieveui_export.h"
@@ -29,37 +30,36 @@
}
namespace KSieveUi {
-class KSIEVEUI_EXPORT VacationCreateScriptJob : public QObject
+class KSIEVEUI_EXPORT CheckKep14SupportJob : public QObject
{
Q_OBJECT
public:
- explicit VacationCreateScriptJob(QObject *parent=0);
- ~VacationCreateScriptJob();
+ explicit CheckKep14SupportJob(QObject *parent=0);
+ ~CheckKep14SupportJob();
void start();
void setServerUrl(const KUrl &url);
- void setScript(const QString &script);
- void setServerName(const QString &servername);
- void setStatus(bool activate, bool wasActive);
+ void setServerName(const QString &name);
+ QString serverName();
-Q_SIGNALS:
- void result(bool);
- void scriptActive(bool activated, const QString &serverName);
+ QStringList availableScripts();
+ bool hasKep14Support();
+ KUrl serverUrl();
-private slots:
- void slotPutActiveResult(KManageSieve::SieveJob *job, bool success);
- void slotPutInactiveResult(KManageSieve::SieveJob *job, bool success);
+Q_SIGNALS:
+ void result(CheckKep14SupportJob*, bool);
private:
- void handlePutResult(KManageSieve::SieveJob *, bool success, bool activated);
KUrl mUrl;
- QString mScript;
- QString mServerName;
- bool mActivate;
- bool mWasActive;
KManageSieve::SieveJob *mSieveJob;
+ QStringList mAvailableScripts;
+ bool mKep14Support;
+ QString mServerName;
+
+private slots:
+ void slotCheckKep14Support(KManageSieve::SieveJob *job, bool success, const QStringList &availableScripts, const QString &activeScript);
};
}
-#endif // VACATIONCREATESCRIPTJOB_H
+#endif // CHECKKEP14SUPPORTJOB_H
Index: libksieve/ksieveui/managescriptsjob/checkkep14supportjob.cpp
===================================================================
--- /dev/null
+++ libksieve/ksieveui/managescriptsjob/checkkep14supportjob.cpp
@@ -0,0 +1,93 @@
+/*
+ Copyright (c) 2015 Sandro Knauß <knauss@kolabsys.com>
+
+ 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 "checkkep14supportjob.h"
+#include <util/util.h>
+#include <kmanagesieve/sievejob.h>
+
+#include <KMessageBox>
+#include <KLocalizedString>
+#include <KDebug>
+
+using namespace KSieveUi;
+
+CheckKep14SupportJob::CheckKep14SupportJob(QObject *parent)
+ : QObject(parent),
+ mSieveJob(0)
+{
+
+}
+
+CheckKep14SupportJob::~CheckKep14SupportJob()
+{
+
+}
+
+void CheckKep14SupportJob::start()
+{
+ if (mUrl.isEmpty()) {
+ qDebug() << " server url is empty";
+ deleteLater();
+ return;
+ }
+ mSieveJob = KManageSieve::SieveJob::list(mUrl);
+ connect(mSieveJob, SIGNAL(gotList(KManageSieve::SieveJob*,bool,QStringList,QString)),
+ this, SLOT(slotCheckKep14Support(KManageSieve::SieveJob*,bool,QStringList,QString)));
+}
+
+void CheckKep14SupportJob::setServerUrl(const KUrl &url)
+{
+ mUrl = url;
+}
+
+KUrl CheckKep14SupportJob::serverUrl()
+{
+ return mUrl;
+}
+
+void CheckKep14SupportJob::setServerName(const QString &name)
+{
+ mServerName = name;
+}
+
+QString CheckKep14SupportJob::serverName()
+{
+ return mServerName;
+}
+
+
+QStringList CheckKep14SupportJob::availableScripts()
+{
+ return mAvailableScripts;
+}
+
+bool CheckKep14SupportJob::hasKep14Support()
+{
+ return mKep14Support;
+}
+
+void CheckKep14SupportJob::slotCheckKep14Support(KManageSieve::SieveJob *job, bool success, const QStringList &availableScripts, const QString &activeScript)
+{
+ if (!success) {
+ emit result(this, false);
+ return;
+ }
+
+ mKep14Support = Util::hasKep14Support(job->sieveCapabilities(), availableScripts, activeScript);
+ mAvailableScripts = availableScripts;
+ emit result(this, true);
+}
Index: libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.h
===================================================================
--- libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.h
+++ libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.h
@@ -33,6 +33,7 @@
~GenerateGlobalScriptJob();
void start();
+ void kill();
void addUserActiveScripts(const QStringList &lstScript);
@@ -50,7 +51,7 @@
void writeUserScript();
QStringList mListUserActiveScripts;
KUrl mCurrentUrl;
- KManageSieve::SieveJob *mMasterjob;
+ KManageSieve::SieveJob *mMasterJob;
KManageSieve::SieveJob *mUserJob;
};
}
Index: libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.cpp
===================================================================
--- libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.cpp
+++ libksieve/ksieveui/managescriptsjob/generateglobalscriptjob.cpp
@@ -25,19 +25,30 @@
GenerateGlobalScriptJob::GenerateGlobalScriptJob(const KUrl &url, QObject *parent)
: QObject(parent),
mCurrentUrl(url),
- mMasterjob(0),
+ mMasterJob(0),
mUserJob(0)
{
}
GenerateGlobalScriptJob::~GenerateGlobalScriptJob()
{
- if (mMasterjob)
- mMasterjob->kill();
- if (mUserJob)
+ kill();
+}
+
+void GenerateGlobalScriptJob::kill()
+{
+ if (mMasterJob) {
+ mMasterJob->kill();
+ }
+ mMasterJob = 0;
+
+ if (mUserJob) {
mUserJob->kill();
+ }
+ mUserJob = 0;
}
+
void GenerateGlobalScriptJob::addUserActiveScripts(const QStringList &lstScript)
{
mListUserActiveScripts = lstScript;
@@ -49,7 +60,7 @@
Q_EMIT error(i18n("Path is not specified."));
return;
}
- writeMasterScript();
+ writeUserScript();
}
void GenerateGlobalScriptJob::writeMasterScript()
@@ -79,8 +90,8 @@
KUrl url(mCurrentUrl);
url.setFileName(QLatin1String("MASTER"));
- mMasterjob = KManageSieve::SieveJob::put(url, masterScript, true, true );
- connect( mMasterjob, SIGNAL(result(KManageSieve::SieveJob*,bool,QString,bool)),
+ mMasterJob = KManageSieve::SieveJob::put(url, masterScript, true, true );
+ connect( mMasterJob, SIGNAL(result(KManageSieve::SieveJob*,bool,QString,bool)),
this, SLOT(slotPutMasterResult(KManageSieve::SieveJob*,bool)) );
}
@@ -90,7 +101,7 @@
Q_EMIT error(i18n("Error when we wrote \"MASTER\" script on server."));
return;
}
- mMasterjob = 0;
+ mMasterJob = 0;
writeUserScript();
}
@@ -107,7 +118,7 @@
"require [\"include\"];\n");
Q_FOREACH (const QString &activeScript, mListUserActiveScripts) {
- userScript += QString::fromLatin1("\ninclude :personal \"%1\"").arg(activeScript);
+ userScript += QString::fromLatin1("\ninclude :personal \"%1\";").arg(activeScript);
}
KUrl url(mCurrentUrl);
Index: libksieve/ksieveui/managescriptsjob/parseuserscriptjob.h
===================================================================
--- libksieve/ksieveui/managescriptsjob/parseuserscriptjob.h
+++ libksieve/ksieveui/managescriptsjob/parseuserscriptjob.h
@@ -19,6 +19,7 @@
#define PARSEUSERSCRIPTJOB_H
#include <QObject>
+#include <QStringList>
#include <KUrl>
#include "ksieveui_export.h"
class QDomDocument;
@@ -31,28 +32,36 @@
class KSIEVEUI_EXPORT ParseUserScriptJob : public QObject
{
Q_OBJECT
+
+ friend class ParseUserJobTest;
public:
- explicit ParseUserScriptJob(QObject *parent=0);
+ explicit ParseUserScriptJob(const KUrl &url,QObject *parent=0);
~ParseUserScriptJob();
void start();
- void scriptUrl(const KUrl &url);
- static QStringList parsescript(const QString &script, bool &result);
+ KUrl scriptUrl() const;
+ QStringList activeScriptList() const;
+ QString error() const;
+ void kill();
private Q_SLOTS:
void slotGetResult( KManageSieve::SieveJob *, bool, const QString &, bool );
Q_SIGNALS:
- void success(const QStringList &activeScriptList);
- void error(const QString &msgError);
+ void finished(ParseUserScriptJob* job);
private:
+ void emitSuccess(const QStringList &activeScriptList);
+ void emitError(const QString &msgError);
static QString loadInclude(const QDomElement &element);
static QStringList extractActiveScript(const QDomDocument &doc);
+ static QStringList parsescript(const QString &script, bool &result);
KUrl mCurrentUrl;
KManageSieve::SieveJob *mSieveJob;
+ QStringList mActiveScripts;
+ QString mError;
};
}
Index: libksieve/ksieveui/managescriptsjob/parseuserscriptjob.cpp
===================================================================
--- libksieve/ksieveui/managescriptsjob/parseuserscriptjob.cpp
+++ libksieve/ksieveui/managescriptsjob/parseuserscriptjob.cpp
@@ -24,32 +24,33 @@
using namespace KSieveUi;
-ParseUserScriptJob::ParseUserScriptJob(QObject *parent)
+ParseUserScriptJob::ParseUserScriptJob(const KUrl &url, QObject *parent)
: QObject(parent),
mSieveJob(0)
+ , mCurrentUrl(url)
{
}
ParseUserScriptJob::~ParseUserScriptJob()
{
- if ( mSieveJob )
- mSieveJob->kill();
- mSieveJob = 0;
+ kill();
}
-void ParseUserScriptJob::scriptUrl(const KUrl &url)
+KUrl ParseUserScriptJob::scriptUrl() const
{
- mCurrentUrl = url;
+ return mCurrentUrl;
}
void ParseUserScriptJob::start()
{
if (mCurrentUrl.isEmpty()) {
- Q_EMIT error(i18n("Path is not specified."));
+ emitError(i18n("Path is not specified."));
return;
}
if ( mSieveJob )
mSieveJob->kill();
+ mActiveScripts = QStringList();
+ mError = QString();
mSieveJob = KManageSieve::SieveJob::get( mCurrentUrl );
connect( mSieveJob, SIGNAL(result(KManageSieve::SieveJob*,bool,QString,bool)),
this, SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)) );
@@ -59,15 +60,27 @@
{
mSieveJob = 0;
if (script.isEmpty()) {
- Q_EMIT error(i18n("Script is empty."));
+ emitError(i18n("Script is empty."));
return;
}
bool result;
const QStringList lst = parsescript(script, result);
if (result)
- Q_EMIT success(lst);
+ emitSuccess(lst);
else
- Q_EMIT error(i18n("Script parsing error"));
+ emitError(i18n("Script parsing error"));
+}
+
+void ParseUserScriptJob::emitError(const QString &msgError)
+{
+ mError = msgError;
+ emit finished(this);
+}
+
+void ParseUserScriptJob::emitSuccess(const QStringList &activeScriptList)
+{
+ mActiveScripts = activeScriptList;
+ emit finished(this);
}
QStringList ParseUserScriptJob::parsescript(const QString &script, bool &result)
@@ -80,6 +93,24 @@
return lst;
}
+QStringList ParseUserScriptJob::activeScriptList() const
+{
+ return mActiveScripts;
+}
+
+QString ParseUserScriptJob::error() const
+{
+ return mError;
+}
+
+void ParseUserScriptJob::kill()
+{
+ if ( mSieveJob )
+ mSieveJob->kill();
+ mSieveJob = 0;
+}
+
+
QStringList ParseUserScriptJob::extractActiveScript(const QDomDocument &doc)
{
QStringList lstScript;
Index: libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.h
===================================================================
--- libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.h
+++ libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.h
@@ -19,7 +19,9 @@
#define PARSEUSERJOBTEST_H
#include <QObject>
-class ParseUserTest : public QObject
+
+namespace KSieveUi {
+class ParseUserJobTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
@@ -29,5 +31,5 @@
void testParseUserDuplicateActiveScriptJob();
void testParseUserErrorScriptJob();
};
-
+}
#endif // PARSEUSERJOBTEST_H
Index: libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.cpp
===================================================================
--- libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.cpp
+++ libksieve/ksieveui/managescriptsjob/tests/parseuserjobtest.cpp
@@ -18,19 +18,20 @@
#include "ksieveui/managescriptsjob/parseuserscriptjob.h"
#include <qtest_kde.h>
+using namespace KSieveUi;
-QTEST_KDEMAIN( ParseUserTest, NoGUI )
+QTEST_KDEMAIN( ParseUserJobTest, NoGUI )
-void ParseUserTest::testParseEmptyUserJob()
+void ParseUserJobTest::testParseEmptyUserJob()
{
const QString script;
bool result;
- const QStringList lst = KSieveUi::ParseUserScriptJob::parsescript(script, result);
+ const QStringList lst = ParseUserScriptJob::parsescript(script, result);
QCOMPARE(lst.count(), 0);
QCOMPARE(result, true);
}
-void ParseUserTest::testParseUserTwoActiveScriptJob()
+void ParseUserJobTest::testParseUserTwoActiveScriptJob()
{
const QString script = QLatin1String("# USER Management Script\n"
"#\n"
@@ -44,12 +45,12 @@
"include :personal \"file1\";\n"
"include :personal \"file2\";\n");
bool result;
- const QStringList lst = KSieveUi::ParseUserScriptJob::parsescript(script, result);
+ const QStringList lst = ParseUserScriptJob::parsescript(script, result);
QCOMPARE(lst.count(), 2);
QCOMPARE(result, true);
}
-void ParseUserTest::testParseUserNoActiveScriptJob()
+void ParseUserJobTest::testParseUserNoActiveScriptJob()
{
const QString script = QLatin1String("# USER Management Script\n"
"#\n"
@@ -61,12 +62,12 @@
"\n"
"require [\"include\"];\n");
bool result;
- const QStringList lst = KSieveUi::ParseUserScriptJob::parsescript(script, result);
+ const QStringList lst = ParseUserScriptJob::parsescript(script, result);
QCOMPARE(lst.count(), 0);
QCOMPARE(result, true);
}
-void ParseUserTest::testParseUserDuplicateActiveScriptJob()
+void ParseUserJobTest::testParseUserDuplicateActiveScriptJob()
{
const QString script = QLatin1String("# USER Management Script\n"
"#\n"
@@ -80,12 +81,12 @@
"include :personal \"file1\";\n"
"include :personal \"file1\";\n");
bool result;
- const QStringList lst = KSieveUi::ParseUserScriptJob::parsescript(script, result);
+ const QStringList lst = ParseUserScriptJob::parsescript(script, result);
QCOMPARE(lst.count(), 1);
QCOMPARE(result, true);
}
-void ParseUserTest::testParseUserErrorScriptJob()
+void ParseUserJobTest::testParseUserErrorScriptJob()
{
const QString script = QLatin1String("# USER Management Script\n"
"#\n"
@@ -97,7 +98,7 @@
"\n"
"errorscript\n");
bool result;
- const QStringList lst = KSieveUi::ParseUserScriptJob::parsescript(script, result);
+ const QStringList lst = ParseUserScriptJob::parsescript(script, result);
QCOMPARE(lst.count(), 0);
QCOMPARE(result, false);
}
Index: libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.h
===================================================================
--- libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.h
+++ libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.h
@@ -33,14 +33,14 @@
void taggedArgument( const QString &tag );
void stringArgument( const QString &string, bool multiLine, const QString & /*fixme*/ );
void numberArgument( unsigned long number, char quantifier );
- void commandStart( const QString &identifier );
- void commandEnd();
+ void commandStart( const QString &identifier, int lineNumber);
+ void commandEnd(int lineNumber);
void testStart( const QString &identifier );
void testEnd();
void testListStart();
void testListEnd();
- void blockStart();
- void blockEnd();
+ void blockStart(int lineNumber);
+ void blockEnd(int lineNumber);
void stringListArgumentStart();
void stringListArgumentEnd();
void stringListEntry( const QString &string, bool multiline, const QString &hashComment );
Index: libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.cpp
===================================================================
--- libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.cpp
+++ libksieve/ksieveui/scriptsparsing/xmlprintingscriptbuilder.cpp
@@ -50,7 +50,7 @@
write( QLatin1String("num"), ( quantifier ? QString::fromLatin1("quantifier=\"%1\"").arg( quantifier ) : QString()) , QString::number( number ) );
}
-void XMLPrintingScriptBuilder::commandStart( const QString &identifier )
+void XMLPrintingScriptBuilder::commandStart( const QString &identifier, int lineNumber )
{
if ( identifier == QLatin1String("else") ||
identifier == QLatin1String("break") ||
@@ -66,7 +66,7 @@
}
}
-void XMLPrintingScriptBuilder::commandEnd()
+void XMLPrintingScriptBuilder::commandEnd(int lineNumber)
{
if (mIsAction) {
write( QLatin1String("</action>") );
@@ -96,12 +96,12 @@
write( QLatin1String("</testlist>") );
}
-void XMLPrintingScriptBuilder::blockStart()
+void XMLPrintingScriptBuilder::blockStart(int lineNumber)
{
write( QLatin1String("<block>") );
}
-void XMLPrintingScriptBuilder::blockEnd()
+void XMLPrintingScriptBuilder::blockEnd(int lineNumber)
{
write( QLatin1String("</block>") );
}
Index: libksieve/ksieveui/util/util.h
===================================================================
--- libksieve/ksieveui/util/util.h
+++ libksieve/ksieveui/util/util.h
@@ -45,6 +45,7 @@
class KUrl;
class QString;
+class QStringList;
namespace KSieveUi
{
@@ -75,6 +76,17 @@
* be available at all.
*/
KSIEVEUI_EXPORT bool allowOutOfOfficeSettings();
+
+ /**
+ * Checks if a server has KEP:14 support
+ */
+ bool hasKep14Support(const QStringList &sieveCapabilities, const QStringList &availableScripts, const QString &activeScript);
+
+ /**
+ * Is the given scriptName a protected KEP:14 name, that a normal user should not touch directly.
+ * it tests against MASTER, USER and MANAGEMENT script
+ */
+ bool isKep14ProtectedName(const QString &scriptName);
}
}
Index: libksieve/ksieveui/util/util.cpp
===================================================================
--- libksieve/ksieveui/util/util.cpp
+++ libksieve/ksieveui/util/util.cpp
@@ -166,3 +166,45 @@
{
return VacationSettings::self()->allowOutOfOfficeSettings();
}
+
+bool Util::hasKep14Support(const QStringList &sieveCapabilities, const QStringList &availableScripts, const QString &activeScript)
+{
+ const bool hasIncludeCapability = sieveCapabilities.contains(QLatin1String("include"));
+ if (!hasIncludeCapability) {
+ return false;
+ }
+
+ bool masterIsActive = !activeScript.isEmpty();
+ if (masterIsActive) {
+ const QString scriptName = activeScript.split(QLatin1Char('.')).first().toLower();
+ masterIsActive = (scriptName == QLatin1String("master") || scriptName == QLatin1String("user"));
+ }
+ if (!masterIsActive) {
+ return false;
+ }
+
+ bool hasUserScript = false;
+ foreach(const QString &script, availableScripts) {
+ if (script.isEmpty()) {
+ continue;
+ }
+ const QString name = script.split(QLatin1Char('.')).first().toLower();
+ if (name == QLatin1String("user")) {
+ hasUserScript = true;
+ break;
+ }
+ }
+
+ return hasIncludeCapability && masterIsActive && hasUserScript;
+}
+
+bool Util::isKep14ProtectedName(const QString &name)
+{
+ QString n = name.split(QLatin1Char('.')).first().toLower();
+ if (n == QLatin1String("master") ||
+ n == QLatin1String("user") ||
+ n == QLatin1String("management")) {
+ return true;
+ }
+ return false;
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/multiimapvacationdialog.h
===================================================================
--- libksieve/ksieveui/vacation/multiimapvacationdialog.h
+++ libksieve/ksieveui/vacation/multiimapvacationdialog.h
@@ -26,11 +26,12 @@
class QStackedWidget;
namespace KSieveUi {
class VacationCreateScriptJob;
+class MultiImapVacationManager;
class KSIEVEUI_EXPORT MultiImapVacationDialog : public KDialog
{
Q_OBJECT
public:
- explicit MultiImapVacationDialog(QWidget *parent=0);
+ explicit MultiImapVacationDialog(MultiImapVacationManager *manager, QWidget *parent=0);
~MultiImapVacationDialog();
QList<VacationCreateScriptJob *> listCreateJob() const;
@@ -49,6 +50,7 @@
QList<VacationCreateScriptJob *> mListCreateJob;
KTabWidget *mTabWidget;
QStackedWidget *mStackedWidget;
+ MultiImapVacationManager* mVacationManager;
};
}
Index: libksieve/ksieveui/vacation/multiimapvacationdialog.cpp
===================================================================
--- libksieve/ksieveui/vacation/multiimapvacationdialog.cpp
+++ libksieve/ksieveui/vacation/multiimapvacationdialog.cpp
@@ -18,6 +18,7 @@
#include "multiimapvacationdialog.h"
#include "vacationpagewidget.h"
+#include "multiimapvacationmanager.h"
#include "ksieveui/util/util.h"
#include <Akonadi/AgentInstance>
@@ -34,8 +35,9 @@
using namespace KSieveUi;
-MultiImapVacationDialog::MultiImapVacationDialog(QWidget *parent)
+MultiImapVacationDialog::MultiImapVacationDialog(MultiImapVacationManager *manager, QWidget *parent)
: KDialog(parent)
+ , mVacationManager(manager)
{
setCaption( i18n("Configure \"Out of Office\" Replies") );
@@ -87,17 +89,12 @@
void MultiImapVacationDialog::init()
{
bool foundOneImap = false;
- const Akonadi::AgentInstance::List instances = KSieveUi::Util::imapAgentInstances();
- foreach ( const Akonadi::AgentInstance &instance, instances ) {
- if ( instance.status() == Akonadi::AgentInstance::Broken )
- continue;
-
- const KUrl url = KSieveUi::Util::findSieveUrlForAccount( instance.identifier() );
- if ( !url.isEmpty() ) {
- const QString serverName = instance.name();
- createPage(serverName, url);
- foundOneImap = true;
- }
+
+ QMap <QString, KUrl> list = mVacationManager->serverList();
+ foreach (const QString &serverName, list.keys()) {
+ const KUrl url = list.value(serverName);
+ createPage(serverName, url);
+ foundOneImap = true;
}
if (foundOneImap) {
setButtons( Ok | Cancel | Default );
@@ -115,6 +112,7 @@
VacationPageWidget *page = new VacationPageWidget;
page->setServerUrl(url);
page->setServerName(serverName);
+ page->setVacationManager(mVacationManager);
mTabWidget->addTab(page,serverName);
}
Index: libksieve/ksieveui/vacation/multiimapvacationmanager.h
===================================================================
--- libksieve/ksieveui/vacation/multiimapvacationmanager.h
+++ libksieve/ksieveui/vacation/multiimapvacationmanager.h
@@ -19,10 +19,15 @@
#define MULTIIMAPVACATIONMANAGER_H
#include <QObject>
+#include <QMap>
#include "ksieveui_export.h"
+class KUrl;
+
namespace KSieveUi {
+class CheckKep14SupportJob;
+class VacationCheckJob;
class KSIEVEUI_EXPORT MultiImapVacationManager : public QObject
{
Q_OBJECT
@@ -31,18 +36,24 @@
~MultiImapVacationManager();
void checkVacation();
+ QMap<QString, KUrl> serverList();
+ void checkVacation(const QString &serverName, const KUrl &url);
+
+ bool kep14Support(QString serverName);
Q_SIGNALS:
void scriptActive(bool active, const QString &serverName);
- void requestEditVacation();
+ void scriptAvailable(const QString &serverName, const QStringList &sieveCapabilities, const QString &scriptName, const QString &script, bool active);
private slots:
- void slotScriptActive(bool active, const QString &serverName);
+ void slotScriptActive(VacationCheckJob* job, QString scriptName, bool active);
+ void slotCheckKep14Ended(CheckKep14SupportJob *job, bool success);
private:
int mNumberOfJobs;
- bool mQuestionAsked;
bool mCheckInProgress;
+
+ QMap<QString, bool> mKep14Support; //if the server has KEP:14 support
};
}
#endif // MULTIIMAPVACATIONMANAGER_H
Index: libksieve/ksieveui/vacation/multiimapvacationmanager.cpp
===================================================================
--- libksieve/ksieveui/vacation/multiimapvacationmanager.cpp
+++ libksieve/ksieveui/vacation/multiimapvacationmanager.cpp
@@ -18,17 +18,21 @@
#include "multiimapvacationmanager.h"
#include "vacationcheckjob.h"
#include "util/util.h"
+#include <managescriptsjob/checkkep14supportjob.h>
+#include <managescriptsjob/parseuserscriptjob.h>
+#include <kmanagesieve/sievejob.h>
#include <Akonadi/AgentInstance>
#include <KMessageBox>
#include <KLocalizedString>
+#include <KDebug>
+
using namespace KSieveUi;
MultiImapVacationManager::MultiImapVacationManager(QObject *parent)
: QObject(parent),
mNumberOfJobs(0),
- mQuestionAsked(false),
mCheckInProgress(false)
{
}
@@ -38,14 +42,9 @@
}
-void MultiImapVacationManager::checkVacation()
+QMap <QString, KUrl> MultiImapVacationManager::serverList()
{
- if (mCheckInProgress)
- return;
- mNumberOfJobs = 0;
- mCheckInProgress = true;
- mQuestionAsked = false;
-
+ QMap <QString, KUrl> list;
const Akonadi::AgentInstance::List instances = KSieveUi::Util::imapAgentInstances();
foreach ( const Akonadi::AgentInstance &instance, instances ) {
if ( instance.status() == Akonadi::AgentInstance::Broken )
@@ -53,32 +52,84 @@
const KUrl url = KSieveUi::Util::findSieveUrlForAccount( instance.identifier() );
if ( !url.isEmpty() ) {
- const QString serverName = instance.name();
- ++mNumberOfJobs;
- VacationCheckJob *job = new VacationCheckJob(url, serverName, this);
- connect(job, SIGNAL(scriptActive(bool,QString)), this, SLOT(slotScriptActive(bool,QString)));
+ list.insert(instance.name(), url);
}
}
+ return list;
}
-void MultiImapVacationManager::slotScriptActive(bool active, const QString &serverName)
+void MultiImapVacationManager::checkVacation(const QString &serverName, const KUrl &url)
{
- --mNumberOfJobs;
- Q_EMIT scriptActive(active, serverName);
-
- if (active) {
- if (!mQuestionAsked) {
- mQuestionAsked = true;
- 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 ) {
- Q_EMIT requestEditVacation();
- }
- }
+ ++mNumberOfJobs;
+ if (!mKep14Support.contains(serverName)) {
+ CheckKep14SupportJob *checkKep14Job = new CheckKep14SupportJob(this);
+ checkKep14Job->setProperty(QLatin1String("triggerScript").latin1(), true);
+ checkKep14Job->setServerName(serverName);
+ checkKep14Job->setServerUrl(url);
+ connect(checkKep14Job, SIGNAL(result(CheckKep14SupportJob*,bool)), SLOT(slotCheckKep14Ended(CheckKep14SupportJob*,bool)));
+ checkKep14Job->start();
+ }
+
+ VacationCheckJob *job = new VacationCheckJob(url, serverName, this);
+ job->setKep14Support(mKep14Support[serverName]);
+ connect(job, SIGNAL(scriptActive(VacationCheckJob*,QString,bool)), this, SLOT(slotScriptActive(VacationCheckJob*,QString,bool)));
+ job->start();
+}
+
+void MultiImapVacationManager::checkVacation()
+{
+ if (mCheckInProgress)
+ return;
+ mNumberOfJobs = 0;
+ mCheckInProgress = true;
+
+ QMap <QString, KUrl> list = serverList();
+ foreach ( const QString &serverName, list.keys() ) {
+ const KUrl url = list.value(serverName);
+ checkVacation(serverName, url);
}
+}
- if (mNumberOfJobs == 0)
+void MultiImapVacationManager::slotScriptActive(VacationCheckJob* job, QString scriptName, bool active)
+{
+ --mNumberOfJobs;
+ if (mNumberOfJobs == 0) {
mCheckInProgress = false;
+ }
+
+ job->deleteLater();
+
+ if (job->noScriptFound()) {
+ emit scriptActive(false, job->serverName());
+ return;
+ }
+ emit scriptActive(active, job->serverName());
+ emit scriptAvailable(job->serverName(), job->sieveCapabilities(), scriptName, job->script(), active);
+}
+
+void MultiImapVacationManager::slotCheckKep14Ended(CheckKep14SupportJob *job, bool success)
+{
+ job->deleteLater();
+ if (!success) {
+ --mNumberOfJobs;
+ return;
+ }
+
+ mKep14Support.insert(job->serverName(), job->hasKep14Support());
+
+ VacationCheckJob *checkJob = new VacationCheckJob(job->serverUrl(), job->serverName(), this);
+ checkJob->setKep14Support(job->hasKep14Support());
+ connect(checkJob, SIGNAL(scriptActive(VacationCheckJob*,QString,bool)),
+ SLOT(slotScriptActive(VacationCheckJob*,QString,bool)));
+ checkJob->start();
+}
+
+bool MultiImapVacationManager::kep14Support(QString serverName)
+{
+ if (mKep14Support.contains(serverName)) {
+ return mKep14Support[serverName];
+ } else {
+ kWarning() << "We don't know the KEP:14 support for this server." << serverName;
+ }
+ return false;
}
Index: libksieve/ksieveui/vacation/tests/CMakeLists.txt
===================================================================
--- libksieve/ksieveui/vacation/tests/CMakeLists.txt
+++ libksieve/ksieveui/vacation/tests/CMakeLists.txt
@@ -1,5 +1,7 @@
include_directories(${CMAKE_SOURCE_DIR}/libksieve
${CMAKE_SOURCE_DIR}/libksieve/ksieveui
+ ${CMAKE_BINARY_DIR}/libksieve
+ ${CMAKE_BINARY_DIR}/libksieve/ksieveui
)
@@ -10,3 +12,25 @@
KDE4_ADD_EXECUTABLE(vacationmultiservertest ${vacation_multi_server_SRCS} )
TARGET_LINK_LIBRARIES(vacationmultiservertest ${KDE4_KDEUI_LIBS} ksieveui ksieve)
+set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
+
+macro( add_vacation_test _source )
+ set( _test ${_source}test.cpp
+ ../${_source}.cpp
+ ../vacationscriptextractor.cpp
+ ${CMAKE_BINARY_DIR}/libksieve/ksieveui/sieve-vacation.cpp
+ ${CMAKE_SOURCE_DIR}/libksieve/parser/lexer.cpp
+ ${CMAKE_SOURCE_DIR}/libksieve/parser/parser.cpp
+ ${CMAKE_SOURCE_DIR}/libksieve/parser/utf8validator.cpp
+ )
+ get_filename_component( _name ${_source} NAME_WE )
+ kde4_add_unit_test( ${_name} TESTNAME vacation-${_name} ${_test} )
+ set_target_properties(${_name} PROPERTIES COMPILE_FLAGS -DVACATIONTESTDATADIR="\\"${CMAKE_CURRENT_SOURCE_DIR}/data/\\"")
+ target_link_libraries( ${_name}
+ ksieveui
+ kmanagesieve
+ ksieve
+ ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${KDE4_KDEUI_LIBS} ${KDEPIMLIBS_KMIME_LIBS} ${KDEPIMLIBS_KPIMIDENTITIES_LIBS})
+endmacro()
+
+add_vacation_test( vacationutils )
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-complex.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-complex.siv
@@ -0,0 +1,8 @@
+require ["date","relational","vacation"];
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+if allof (currentdate :zone "+0100" :value "ge" "date" "2015-01-02", currentdate :zone "+0100" :value "le" "date" "2015-03-04", not header :contains "X-Spam-Flag" "YES")
+{
+ vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg";
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-deactivate-complex.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-deactivate-complex.siv
@@ -0,0 +1,8 @@
+require ["date","relational","vacation"];
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+if false # allof (currentdate :zone "+0100" :value "ge" "date" "2015-01-02", currentdate :zone "+0100" :value "le" "date" "2015-03-04", not header :contains "X-Spam-Flag" "YES")
+{
+ vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg";
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-deactivate-multiple.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-deactivate-multiple.siv
@@ -0,0 +1,19 @@
+require ["vacation"];
+
+if true
+{
+ testcommand;
+}
+
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+if false # true
+{
+ vacation :subject "XXX" "dsfgsdfgsdfg";
+}
+
+if true
+{
+ testcommand;
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-deactivate.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-deactivate.siv
@@ -0,0 +1,9 @@
+require ["vacation"];
+
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+if false # true
+{
+ vacation :subject "XXX" "dsfgsdfgsdfg";
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-multiple.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-multiple.siv
@@ -0,0 +1,16 @@
+require ["vacation"];
+
+if false
+{
+ testcommand;
+}
+
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+vacation :subject "XXX" "dsfgsdfgsdfg";
+
+if false
+{
+ testcommand;
+}
Index: libksieve/ksieveui/vacation/tests/data/vacation-notfound.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-notfound.siv
@@ -0,0 +1,15 @@
+#blabla
+
+testcommand;
+
+if true {
+ testcmd2;
+}
+
+if false {
+ testcmd3;
+}
+
+if true {
+ testcmd4;
+}
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/data/vacation-simple.siv
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/data/vacation-simple.siv
@@ -0,0 +1,6 @@
+require ["vacation"];
+
+# EDITOR Roundcube (Managesieve)
+# EDITOR_VERSION 8.2
+# rule:[Urlaub]
+vacation :subject "XXX" "dsfgsdfgsdfg";
\ No newline at end of file
Index: libksieve/ksieveui/vacation/tests/main.cpp
===================================================================
--- libksieve/ksieveui/vacation/tests/main.cpp
+++ libksieve/ksieveui/vacation/tests/main.cpp
@@ -20,6 +20,7 @@
#include <KCmdLineArgs>
#include "vacation/multiimapvacationdialog.h"
+#include <vacation/multiimapvacationmanager.h>
#include <QDebug>
@@ -30,7 +31,8 @@
KApplication app;
app.setQuitOnLastWindowClosed( false );
- KSieveUi::MultiImapVacationDialog dlg;
+ KSieveUi::MultiImapVacationManager manager;
+ KSieveUi::MultiImapVacationDialog dlg(&manager);
dlg.show();
app.exec();
Index: libksieve/ksieveui/vacation/tests/vacationutilstest.h
===================================================================
--- libksieve/ksieveui/vacation/tests/vacationutilstest.h
+++ libksieve/ksieveui/vacation/tests/vacationutilstest.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2013, 2014 Montel Laurent <montel@kde.org>
+ Copyright (c) 2015 Sandro Knauß <knauss@kolabsys.com>
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
@@ -15,19 +15,27 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef PARSEUSERJOBTEST_H
-#define PARSEUSERJOBTEST_H
+#ifndef VACATIONUTILSTEST_H
+#define VACATIONUTILSTEST_H
#include <QObject>
-class ParseUserTest : public QObject
+
+namespace KSieveUi {
+class VacationUtilsTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
- void testParseEmptyUserJob();
- void testParseUserTwoActiveScriptJob();
- void testParseUserNoActiveScriptJob();
- void testParseUserDuplicateActiveScriptJob();
- void testParseUserErrorScriptJob();
+ void testParseEmptyScript();
+ void testParseOnlyComment();
+ void testParseActivate_data();
+ void testParseActivate();
+ void testParseScript_data();
+ void testParseScript();
+ void testParseScriptComplex();
+ void testWriteScript();
+ void testWriteSimpleScript();
+ void testUpdateVacationBlock();
+ void testMergeRequireLine();
};
-
-#endif // PARSEUSERJOBTEST_H
+}
+#endif // VACATIONUTILSTEST_H
Index: libksieve/ksieveui/vacation/tests/vacationutilstest.cpp
===================================================================
--- /dev/null
+++ libksieve/ksieveui/vacation/tests/vacationutilstest.cpp
@@ -0,0 +1,303 @@
+/*
+ Copyright (c) 2015 Sandro Knauß <knauss@kolabsys.com>
+
+ 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 <kmime/kmime_header_parsing.h>
+
+#include <QFile>
+#include <qtest_kde.h>
+#include <KDebug>
+
+using namespace KSieveUi;
+
+QTEST_KDEMAIN( VacationUtilsTest, NoGUI )
+
+void VacationUtilsTest::testParseEmptyScript()
+{
+ const QString script;
+ QCOMPARE(VacationUtils::foundVacationScript(script), false);
+}
+
+void VacationUtilsTest::testParseOnlyComment()
+{
+ QString script(QLatin1String("#comment"));
+ QCOMPARE(VacationUtils::foundVacationScript(script), false);
+ script = QLatin1String("#comment\n\n#comment\n");
+ QCOMPARE(VacationUtils::foundVacationScript(script), false);
+}
+
+void VacationUtilsTest::testParseActivate_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<bool>("found");
+ QTest::addColumn<bool>("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());
+ QCOMPARE(VacationUtils::foundVacationScript(script), found);
+
+ QString messageText;
+ QString subject;
+ int notificationInterval;
+ QStringList aliases;
+ bool sendForSpam;
+ QString domainName;
+ QDate startDate;
+ QDate endDate;
+ bool scriptActive = !active;
+
+ bool ret = VacationUtils::parseScript(script, scriptActive, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate);
+ QCOMPARE(ret, found);
+ QCOMPARE(scriptActive, active);
+}
+
+void VacationUtilsTest::testParseScript_data()
+{
+ QTest::addColumn<QString>("activate");
+ QTest::addColumn<QString>("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());
+
+ QString messageTextA, messageTextD;
+ QString subjectA, subjectD;
+ int notificationIntervalA, notificationIntervalD;
+ QStringList aliasesA, aliasesD;
+ bool sendForSpamA, sendForSpamD;
+ QString domainNameA, domainNameD;
+ QDate startDateA, startDateD;
+ QDate endDateA, endDateD;
+ bool scriptActiveA, scriptActiveD;
+ VacationUtils::parseScript(scriptA, scriptActiveA, messageTextA, subjectA, notificationIntervalA, aliasesA, sendForSpamA, domainNameA, startDateA, endDateA);
+ VacationUtils::parseScript(scriptD, scriptActiveD, messageTextD, subjectD, notificationIntervalD, aliasesD, sendForSpamD, domainNameD, startDateD, endDateD);
+ QCOMPARE(scriptActiveA, true);
+ QCOMPARE(scriptActiveD, false);
+ QCOMPARE(messageTextD, messageTextA);
+ QCOMPARE(subjectD, subjectA);
+ QCOMPARE(notificationIntervalD, notificationIntervalA);
+ QCOMPARE(aliasesD, aliasesA);
+ QCOMPARE(sendForSpamD, sendForSpamA);
+ QCOMPARE(domainNameD, domainNameA);
+ QCOMPARE(startDateD, startDateA);
+ QCOMPARE(endDateD, endDateA);
+}
+
+void VacationUtilsTest::testParseScriptComplex()
+{
+ QFile file(QLatin1String(VACATIONTESTDATADIR "vacation-complex.siv"));
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QString script = QString::fromUtf8(file.readAll());
+
+ QString messageText;
+ QString subject;
+ int notificationInterval;
+ QStringList aliases;
+ bool sendForSpam;
+ QString domainName;
+ QDate startDate;
+ QDate endDate;
+ bool scriptActive;
+ VacationUtils::parseScript(script, scriptActive, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate);
+ QCOMPARE(scriptActive, true);
+ QCOMPARE(messageText, QLatin1String("dsfgsdfgsdfg"));
+ QCOMPARE(subject, QLatin1String("XXX"));
+ QCOMPARE(notificationInterval, 7);
+ QCOMPARE(aliases, QStringList() << QLatin1String("test@test.de"));
+ QCOMPARE(sendForSpam, false);
+ QCOMPARE(domainName, QString());
+ QCOMPARE(startDate, QDate(2015, 01, 02));
+ QCOMPARE(endDate, QDate(2015, 03, 04));
+}
+
+void VacationUtilsTest::testWriteScript()
+{
+ QString messageText(QLatin1String("dsfgsdfgsdfg"));
+ QString subject(QLatin1String("XXX"));
+ int notificationInterval(7);
+ QStringList aliases = QStringList() << QLatin1String("test@test.de");
+ QList<KMime::Types::AddrSpec> addesses;
+ bool sendForSpam(false);
+ QString domainName(QLatin1String("example.org"));
+ QDate startDate(2015, 01, 02);
+ QDate endDate(2015, 03, 04);
+ bool scriptActive(true);
+
+ QString messageTextA;
+ QString subjectA;
+ int notificationIntervalA;
+ QStringList aliasesA;
+ bool sendForSpamA;
+ QString domainNameA;
+ QDate startDateA;
+ QDate endDateA;
+ bool scriptActiveA;
+
+ foreach(const QString &alias, aliases) {
+ KMime::Types::Mailbox a;
+ a.fromUnicodeString(alias);
+ addesses.append(a.addrSpec());
+ }
+
+ QString script = VacationUtils::composeScript(messageText, scriptActive, subject, notificationInterval, addesses, sendForSpam, domainName, startDate, endDate);
+ bool ret = VacationUtils::parseScript(script, scriptActiveA, messageTextA, subjectA, notificationIntervalA, aliasesA, sendForSpamA, domainNameA, startDateA, endDateA);
+ QCOMPARE(ret, true);
+ QCOMPARE(scriptActiveA, scriptActive);
+ QCOMPARE(messageTextA, messageText);
+ QCOMPARE(subjectA, subject);
+ QCOMPARE(notificationIntervalA, notificationInterval);
+ QCOMPARE(aliasesA, aliases);
+ QCOMPARE(sendForSpamA, sendForSpam);
+ QCOMPARE(domainNameA, domainName);
+ QCOMPARE(startDateA, startDate);
+ QCOMPARE(endDateA, endDate);
+
+ scriptActive = false;
+ script = VacationUtils::composeScript(messageText, scriptActive, subject, notificationInterval, addesses, sendForSpam, domainName, startDate, endDate);
+ ret = VacationUtils::parseScript(script, scriptActiveA, messageTextA, subjectA, notificationIntervalA, aliasesA, sendForSpamA, domainNameA, startDateA, endDateA);
+ QCOMPARE(ret, true);
+ QCOMPARE(scriptActiveA, scriptActive);
+ QCOMPARE(messageTextA, messageText);
+ QCOMPARE(subjectA, subject);
+ QCOMPARE(notificationIntervalA, notificationInterval);
+ QCOMPARE(aliasesA, aliases);
+ QCOMPARE(sendForSpamA, sendForSpam);
+ QCOMPARE(domainNameA, domainName);
+ QCOMPARE(startDateA, startDate);
+ QCOMPARE(endDateA, endDate);
+}
+
+
+void VacationUtilsTest::testWriteSimpleScript()
+{
+ QString messageText(QLatin1String("dsfgsdfgsdfg"));
+ QString subject(QLatin1String("XXX"));
+ int notificationInterval(7);
+ bool scriptActive(true);
+
+ QString messageTextA;
+ QString subjectA;
+ int notificationIntervalA;
+ QStringList aliasesA;
+ bool sendForSpamA;
+ QString domainNameA;
+ QDate startDateA;
+ QDate endDateA;
+ bool scriptActiveA;
+
+ QString script = VacationUtils::composeScript(messageText, scriptActive, subject, notificationInterval, QList<KMime::Types::AddrSpec>(), true, QString(), QDate(), QDate());
+ bool ret = VacationUtils::parseScript(script, scriptActiveA, messageTextA, subjectA, notificationIntervalA, aliasesA, sendForSpamA, domainNameA, startDateA, endDateA);
+ QCOMPARE(ret, true);
+ QCOMPARE(scriptActiveA, scriptActive);
+ QCOMPARE(messageTextA, messageText);
+ QCOMPARE(subjectA, subject);
+ QCOMPARE(notificationIntervalA, notificationInterval);
+
+ scriptActive = false;
+ script = VacationUtils::composeScript(messageText, scriptActive, subject, notificationInterval, QList<KMime::Types::AddrSpec>(), true, QString(), QDate(), QDate());
+ ret = VacationUtils::parseScript(script, scriptActiveA, messageTextA, subjectA, notificationIntervalA, aliasesA, sendForSpamA, domainNameA, startDateA, endDateA);
+ QCOMPARE(ret, true);
+ QCOMPARE(scriptActiveA, scriptActive);
+ QCOMPARE(messageTextA, messageText);
+ QCOMPARE(subjectA, subject);
+ QCOMPARE(notificationIntervalA, 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<linesA.count(); i++ ){
+ vacation.append(linesA.at(i));
+ }
+
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptA, QString()), scriptA);
+ QCOMPARE(VacationUtils::updateVacationBlock(QString(), scriptB), scriptB);
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptA, scriptB), scriptB);
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptB, scriptA), scriptA);
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptAattend, scriptB), scriptBattend);
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptBattend, scriptA), scriptAattend);
+ QCOMPARE(VacationUtils::updateVacationBlock(scriptA, attend), header.join(QLatin1String("\n")));
+ QStringList output = vacation;
+ output << attend;
+ QCOMPARE(VacationUtils::updateVacationBlock(attend, scriptA), output.join(QLatin1String("\n")));
+ output.insert(0,require);
+ QCOMPARE(VacationUtils::updateVacationBlock(require+ QLatin1String("\n") + attend, scriptA), output.join(QLatin1String("\n")));
+}
+
+void VacationUtilsTest::testMergeRequireLine()
+{
+ QString sEmpty=QLatin1String("require;");
+ QString sOne=QLatin1String("require \"test\";");
+ QString sList1=QLatin1String("require [\"test\"];");
+ QString sList2=QLatin1String("require [\"test\", \"test2\"];");
+ QString sList3=QLatin1String("require [\"test3\",\n \"test4\"];\ntestcmd;");
+
+ QCOMPARE(VacationUtils::mergeRequireLine(sEmpty, sOne), sOne);
+ QCOMPARE(VacationUtils::mergeRequireLine(sOne, sEmpty), sOne);
+ QCOMPARE(VacationUtils::mergeRequireLine(sOne, sList1), sOne);
+ QCOMPARE(VacationUtils::mergeRequireLine(sOne, sList2), sList2);
+ QCOMPARE(VacationUtils::mergeRequireLine(sOne, sList3), QLatin1String("require [\"test\", \"test3\", \"test4\"];") );
+ QCOMPARE(VacationUtils::mergeRequireLine(sList3, sOne), QLatin1String("require [\"test\", \"test3\", \"test4\"];\ntestcmd;") );
+}
Index: libksieve/ksieveui/vacation/vacation.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacation.cpp
+++ libksieve/ksieveui/vacation/vacation.cpp
@@ -115,18 +115,20 @@
QString domainName = VacationUtils::defaultDomainName();
QDate startDate = VacationUtils::defaultStartDate();
QDate endDate = VacationUtils::defaultEndDate();
+ bool sActive = true;
+
if ( !success ) active = false; // default to inactive
- if ( !mCheckOnly && ( !success || !KSieveUi::VacationUtils::parseScript( script, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate ) ) )
+ if ( !mCheckOnly && ( !success || !KSieveUi::VacationUtils::parseScript( script, sActive, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate ) ) )
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;
+ mWasActive = active && sActive;
if ( mDialog ) {
- mDialog->setActivateVacation( active );
+ mDialog->setActivateVacation( active && sActive );
mDialog->setSubject(subject);
mDialog->setMessageText( messageText );
mDialog->setNotificationInterval( notificationInterval );
@@ -161,7 +163,8 @@
void Vacation::slotDialogOk() {
kDebug();
// compose a new script:
- const QString script = VacationUtils::composeScript( mDialog->messageText(),
+ const bool active = mDialog->activateVacation();
+ const QString script = VacationUtils::composeScript( mDialog->messageText(), active,
mDialog->subject(),
mDialog->notificationInterval(),
mDialog->mailAliases(),
@@ -169,7 +172,6 @@
mDialog->domainName(),
mDialog->startDate(),
mDialog->endDate() );
- const bool active = mDialog->activateVacation();
emit scriptActive( active, mServerName);
kDebug() << "script:" << endl << script;
Index: libksieve/ksieveui/vacation/vacationcheckjob.h
===================================================================
--- libksieve/ksieveui/vacation/vacationcheckjob.h
+++ libksieve/ksieveui/vacation/vacationcheckjob.h
@@ -19,6 +19,7 @@
#define VACATIONCHECKJOB_H
#include <QObject>
+#include <QStringList>
#include <KUrl>
namespace KManageSieve {
@@ -26,23 +27,46 @@
}
namespace KSieveUi {
+class ParseUserScriptJob;
class VacationCheckJob : public QObject
{
Q_OBJECT
public:
explicit VacationCheckJob(const KUrl &url, const QString &serverName, QObject *parent=0);
~VacationCheckJob();
+ void setKep14Support(bool kep14Support);
+ void start();
+ void kill();
+ bool noScriptFound();
+ QString script();
+ QStringList sieveCapabilities();
+ QString serverName();
Q_SIGNALS:
- void scriptActive(bool active, const QString &serverName);
+ void scriptActive(VacationCheckJob* job, const QString &sscriptName, bool active);
private slots:
void slotGetResult(KManageSieve::SieveJob *job, bool success, const QString &script, bool active);
+ void slotGotActiveScripts(ParseUserScriptJob *job);
+ void slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &availableScripts, const QString &activeScript);
+ void emitError(const QString &errorMessage);
+ void searchVacationScript();
+ void getNextScript();
+ bool isVacationScipt(const QString &script) const;
+ bool isLastScript() const;
private:
QString mServerName;
KUrl mUrl;
KManageSieve::SieveJob * mSieveJob;
+ ParseUserScriptJob *mParseJob;
+ bool mKep14Support;
+ QStringList mAvailableScripts;
+ QStringList mActiveScripts;
+ int mScriptPos;
+ bool mNoScriptFound;
+ QString mScript;
+ QStringList mSieveCapabilities;
};
}
Index: libksieve/ksieveui/vacation/vacationcheckjob.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationcheckjob.cpp
+++ libksieve/ksieveui/vacation/vacationcheckjob.cpp
@@ -16,32 +16,196 @@
*/
#include "vacationcheckjob.h"
+#include "vacationutils.h"
+#include <managescriptsjob/parseuserscriptjob.h>
+#include <util/util.h>
#include <kmanagesieve/sievejob.h>
+#include <KDebug>
+
using namespace KSieveUi;
VacationCheckJob::VacationCheckJob(const KUrl &url, const QString &serverName, QObject *parent)
: QObject(parent),
mServerName(serverName),
mUrl(url)
+ , mKep14Support(false)
+ , mSieveJob(0)
+ , mParseJob(0)
+ , mNoScriptFound(0)
{
- mSieveJob = KManageSieve::SieveJob::get( mUrl );
- mSieveJob->setInteractive( false );
- connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
- SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)) );
}
VacationCheckJob::~VacationCheckJob()
{
+ kill();
+}
+
+void VacationCheckJob::kill()
+{
if ( mSieveJob )
mSieveJob->kill();
mSieveJob = 0;
+
+ if (mParseJob) {
+ mParseJob->kill();
+ }
+ mParseJob = 0;
+}
+
+
+void VacationCheckJob::setKep14Support(bool kep14Support)
+{
+ mKep14Support = kep14Support;
}
-void VacationCheckJob::slotGetResult(KManageSieve::SieveJob */*job*/, bool success, const QString &/*script*/, bool active)
+void VacationCheckJob::start()
{
+ if (mKep14Support) {
+ KUrl url = mUrl;
+ url.setFileName(QLatin1String("USER"));
+ mParseJob = new ParseUserScriptJob(url);
+ connect(mParseJob, SIGNAL(finished(ParseUserScriptJob*)), SLOT(slotGotActiveScripts(ParseUserScriptJob*)));
+ mParseJob->start();
+ mSieveJob = KManageSieve::SieveJob::list(url);
+ connect(mSieveJob, SIGNAL(gotList(KManageSieve::SieveJob*,bool,QStringList,QString)),
+ this, SLOT(slotGotList(KManageSieve::SieveJob*,bool,QStringList,QString)));
+ } else {
+ mSieveJob = KManageSieve::SieveJob::get(mUrl);
+ mSieveJob->setInteractive(false);
+ connect(mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
+ SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)));
+ }
+}
+
+void VacationCheckJob::slotGetResult(KManageSieve::SieveJob */*job*/, bool success, const QString &script, bool active)
+{
+ mScript = script;
+ mSieveCapabilities = mSieveJob->sieveCapabilities();
mSieveJob = 0;
- if ( !success )
- active = false; // default to inactive
- emit scriptActive( active, mServerName );
+
+ if (mKep14Support) {
+ if (isVacationScipt(script)) {
+ const QString &scriptName = mAvailableScripts[mScriptPos-1];
+ emit scriptActive(this, scriptName, mActiveScripts.contains(scriptName) && VacationUtils::vacationScriptActive(script));
+ kDebug() << "vacation script found :)";
+ } else if (isLastScript()) {
+ mNoScriptFound = true;
+ emit scriptActive(this, QString(), false);
+ kDebug() << "no vacation script found :(";
+ } else {
+ getNextScript();
+ }
+ } else {
+ if ( !success ) {
+ active = false; // default to inactive
+ mNoScriptFound = true;
+ }
+ if (active) {
+ mActiveScripts << mUrl.fileName();
+ }
+ emit scriptActive(this, mUrl.fileName(), active);
+ }
}
+
+void VacationCheckJob::slotGotActiveScripts(ParseUserScriptJob *job)
+{
+ mParseJob = 0;
+ if (!job->error().isEmpty()) {
+ emitError(QLatin1String("ParseUserScriptJob failed:")+job->error());
+ return;
+ }
+ mActiveScripts = job->activeScriptList();
+
+ if (!mSieveJob) {
+ searchVacationScript();
+ }
+}
+
+void VacationCheckJob::slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &availableScripts, const QString &activeScript)
+{
+ mSieveJob = 0;
+ if (!success) {
+ emitError(QLatin1String("SieveJob list failed."));
+ return;
+ }
+
+ mAvailableScripts = availableScripts;
+
+ if (!mParseJob) {
+ searchVacationScript();
+ }
+}
+
+void VacationCheckJob::emitError(const QString &errorMessage)
+{
+ qWarning() << errorMessage;
+ //TODO: emit error
+}
+
+void VacationCheckJob::searchVacationScript()
+{
+ QStringList scriptList = mActiveScripts;
+
+ // Reorder script list
+ foreach(const QString &script, mAvailableScripts) {
+ if (!scriptList.contains(script)) {
+ scriptList.append(script);
+ }
+ }
+
+ mAvailableScripts = scriptList;
+ mScriptPos = 0;
+ getNextScript();
+}
+
+void VacationCheckJob::getNextScript()
+{
+ if (isLastScript()) {
+ //TODO: no script found
+ mNoScriptFound = true;
+ emit scriptActive(this, QString(), false);
+ kDebug() << "no vacation script found :(";
+ }
+ KUrl url = mUrl;
+ url.setFileName(mAvailableScripts[mScriptPos]);
+ mScriptPos += 1;
+ if (Util::isKep14ProtectedName(url.fileName())) {
+ getNextScript();
+ }
+ mSieveJob = KManageSieve::SieveJob::get(url);
+ mSieveJob->setInteractive(false);
+ connect(mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
+ SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)));
+}
+
+bool VacationCheckJob::isLastScript() const
+{
+ return mScriptPos >= mAvailableScripts.count();
+}
+
+bool VacationCheckJob::isVacationScipt(const QString &script) const
+{
+ return KSieveUi::VacationUtils::foundVacationScript(script);
+}
+
+bool VacationCheckJob::noScriptFound()
+{
+ return mNoScriptFound;
+}
+
+QString VacationCheckJob::serverName()
+{
+ return mServerName;
+}
+
+QString VacationCheckJob::script()
+{
+ return mScript;
+}
+
+QStringList VacationCheckJob::sieveCapabilities()
+{
+ return mSieveCapabilities;
+}
+
Index: libksieve/ksieveui/vacation/vacationcreatescriptjob.h
===================================================================
--- libksieve/ksieveui/vacation/vacationcreatescriptjob.h
+++ libksieve/ksieveui/vacation/vacationcreatescriptjob.h
@@ -29,6 +29,8 @@
}
namespace KSieveUi {
+class ParseUserScriptJob;
+class GenerateGlobalScriptJob;
class KSIEVEUI_EXPORT VacationCreateScriptJob : public QObject
{
Q_OBJECT
@@ -37,28 +39,39 @@
~VacationCreateScriptJob();
void start();
+ void kill();
void setServerUrl(const KUrl &url);
void setScript(const QString &script);
void setServerName(const QString &servername);
+ const QString &serverName() const;
void setStatus(bool activate, bool wasActive);
+ void setKep14Support(bool kep14Support);
Q_SIGNALS:
void result(bool);
void scriptActive(bool activated, const QString &serverName);
private slots:
- void slotPutActiveResult(KManageSieve::SieveJob *job, bool success);
- void slotPutInactiveResult(KManageSieve::SieveJob *job, bool success);
+ void slotPutResult(KManageSieve::SieveJob *job, bool success);
+ void slotGetScript(KManageSieve::SieveJob *job, bool success, const QString &oldScript, bool active);
+ void slotGotActiveScripts(ParseUserScriptJob *job);
+ void slotGenerateDone(const QString &error=QString());
private:
- void handlePutResult(KManageSieve::SieveJob *, bool success, bool activated);
+ void handleResult();
KUrl mUrl;
QString mScript;
QString mServerName;
bool mActivate;
- bool mWasActive;
+ bool mScriptActive;
+ bool mKep14Support;
+ bool mUserJobRunning;
+ bool mScriptJobRunning;
+ bool mSuccess;
KManageSieve::SieveJob *mSieveJob;
+ ParseUserScriptJob *mParseUserJob;
+ GenerateGlobalScriptJob *mCreateJob;
};
}
Index: libksieve/ksieveui/vacation/vacationcreatescriptjob.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationcreatescriptjob.cpp
+++ libksieve/ksieveui/vacation/vacationcreatescriptjob.cpp
@@ -16,6 +16,9 @@
*/
#include "vacationcreatescriptjob.h"
+#include "vacationutils.h"
+#include <managescriptsjob/parseuserscriptjob.h>
+#include <managescriptsjob/generateglobalscriptjob.h>
#include <kmanagesieve/sievejob.h>
#include <KMessageBox>
@@ -27,21 +30,46 @@
VacationCreateScriptJob::VacationCreateScriptJob(QObject *parent)
: QObject(parent),
mActivate(false),
- mWasActive(false),
- mSieveJob(0)
+ mScriptActive(false)
+ , mKep14Support(false)
+ , mUserJobRunning(false)
+ , mScriptJobRunning(false)
+ , mSuccess(true)
+ , mSieveJob(0)
+ , mParseUserJob(0)
+ , mCreateJob(0)
{
}
VacationCreateScriptJob::~VacationCreateScriptJob()
{
+ kill();
+}
+
+void VacationCreateScriptJob::kill()
+{
+ if (mSieveJob) {
+ mSieveJob->kill();
+ }
+ mSieveJob = 0;
+
+ if (mParseUserJob) {
+ mParseUserJob->kill();
+ }
+ mParseUserJob = 0;
+ if (mCreateJob) {
+ mCreateJob->kill();
+ }
+ mParseUserJob = 0;
}
+
void VacationCreateScriptJob::setStatus(bool activate, bool wasActive)
{
mActivate = activate;
- mWasActive = wasActive;
+ mScriptActive = wasActive;
}
void VacationCreateScriptJob::setServerName(const QString &servername)
@@ -49,20 +77,14 @@
mServerName = servername;
}
-void VacationCreateScriptJob::start()
+const QString &VacationCreateScriptJob::serverName() const
{
- if (mUrl.isEmpty()) {
- qDebug()<<" server url is empty";
- deleteLater();
- return;
- }
- mSieveJob = KManageSieve::SieveJob::put( mUrl, mScript, mActivate, mWasActive );
- if ( mActivate )
- 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)) );
+ return mServerName;
+}
+
+void VacationCreateScriptJob::setKep14Support(bool kep14Support)
+{
+ mKep14Support = kep14Support;
}
void VacationCreateScriptJob::setServerUrl(const KUrl &url)
@@ -75,28 +97,104 @@
mScript = script;
}
-void VacationCreateScriptJob::slotPutActiveResult( KManageSieve::SieveJob * job, bool success )
+void VacationCreateScriptJob::start()
+{
+ if (mUrl.isEmpty()) {
+ qDebug()<<" server url is empty";
+ deleteLater();
+ return;
+ }
+
+ mUserJobRunning = false;
+ mScriptJobRunning = true;
+ mSieveJob = KManageSieve::SieveJob::get(mUrl);
+ mSieveJob->setInteractive(false);
+ connect(mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
+ SLOT(slotGetScript(KManageSieve::SieveJob*,bool,QString,bool)));
+
+ if (mKep14Support && mActivate && !mScriptActive) {
+ mUserJobRunning = true;
+ KUrl url = mUrl;
+ url.setFileName(QLatin1String("USER"));
+ mParseUserJob = new ParseUserScriptJob(url, this);
+ connect(mParseUserJob, SIGNAL(finished(ParseUserScriptJob*)), SLOT(slotGotActiveScripts(ParseUserScriptJob*)));
+ mParseUserJob->start();
+ }
+}
+
+void VacationCreateScriptJob::slotGetScript(KManageSieve::SieveJob *job, bool success, const QString &oldScript, bool active)
{
- handlePutResult( job, success, true );
+ mSieveJob = 0;
+ QString script = mScript;
+ if (success || !oldScript.trimmed().isEmpty()) {
+ script = VacationUtils::mergeRequireLine(oldScript, mScript);
+ script = VacationUtils::updateVacationBlock(oldScript,mScript);
+ }
+ if (mKep14Support) {
+ mSieveJob = KManageSieve::SieveJob::put( mUrl, mScript, false, false );
+ } else {
+ mSieveJob = KManageSieve::SieveJob::put( mUrl, mScript, mActivate, false ); //Never deactivate
+ }
+ connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
+ SLOT(slotPutResult(KManageSieve::SieveJob*,bool)) );
}
-void VacationCreateScriptJob::slotPutInactiveResult( KManageSieve::SieveJob * job, bool success )
+void VacationCreateScriptJob::slotPutResult( KManageSieve::SieveJob * job, bool success )
{
- handlePutResult( job, success, false );
+ mSieveJob = 0;
+ mScriptJobRunning = false;
+ if (!success) {
+ mSuccess = false;
+ }
+ handleResult();
}
-void VacationCreateScriptJob::handlePutResult( KManageSieve::SieveJob *, bool success, bool activated )
+void VacationCreateScriptJob::handleResult()
{
- if ( success )
- KMessageBox::information( 0, activated
+ if (mUserJobRunning || mScriptJobRunning) { // Not both jobs are done
+ return;
+ }
+
+ if ( mSuccess )
+ KMessageBox::information( 0, mActivate
? i18n("Sieve script installed successfully on the server \'%1\'.\n"
"Out of Office reply is now active.", mServerName)
: i18n("Sieve script installed successfully on the server \'%1\'.\n"
"Out of Office reply has been deactivated.", mServerName) );
- kDebug() << "( ???," << success << ", ? )";
- mSieveJob = 0; // job deletes itself after returning from this slot!
- Q_EMIT result( success );
- Q_EMIT scriptActive( activated, mServerName );
+ kDebug() << "( ???," << mSuccess << ", ? )";
+ Q_EMIT result( mSuccess );
+ Q_EMIT scriptActive( mActivate, mServerName );
deleteLater();
}
+
+void VacationCreateScriptJob::slotGotActiveScripts(ParseUserScriptJob *job)
+{
+ mParseUserJob = 0;
+ if (!job->error().isEmpty()) {
+ slotGenerateDone(job->error());
+ return;
+ }
+
+ QStringList list = job->activeScriptList();
+
+ if (!list.contains(mUrl.fileName())) {
+ list.prepend(mUrl.fileName());
+ mCreateJob = new GenerateGlobalScriptJob(mUrl, this);
+ mCreateJob->addUserActiveScripts(list);
+ connect( mCreateJob, SIGNAL(success()), SLOT(slotGenerateDone()));
+ connect( mCreateJob, SIGNAL(error(QString)), SLOT(slotGenerateDone(QString)));
+ mCreateJob->start();
+ }
+}
+
+void VacationCreateScriptJob::slotGenerateDone(const QString &error)
+{
+ mCreateJob = 0;
+ mUserJobRunning = false;
+ if (!error.isEmpty()) {
+ qWarning() << error;
+ mSuccess = false;
+ }
+ handleResult();
+}
Index: libksieve/ksieveui/vacation/vacationmanager.h
===================================================================
--- libksieve/ksieveui/vacation/vacationmanager.h
+++ libksieve/ksieveui/vacation/vacationmanager.h
@@ -41,17 +41,19 @@
void slotEditVacation(const QString &serverName);
Q_SIGNALS:
- void updateVacationScriptStatus(bool, const QString&);
+ void updateVacationScriptStatus(bool active, const QString &serverName);
void editVacation();
private slots:
void slotDialogCanceled();
void slotDialogOk();
+ void slotUpdateVacationScriptStatus(bool active, const QString &serverName);
private:
QPointer<KSieveUi::MultiImapVacationDialog> mMultiImapVacationDialog;
QPointer<KSieveUi::MultiImapVacationManager> mCheckVacation;
QWidget *mWidget;
+ bool mQuestionAsked;
};
}
Index: libksieve/ksieveui/vacation/vacationmanager.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationmanager.cpp
+++ libksieve/ksieveui/vacation/vacationmanager.cpp
@@ -30,38 +30,53 @@
VacationManager::VacationManager(QWidget *parent)
: QObject(parent),
mWidget(parent)
+ , mMultiImapVacationDialog(0)
+ , mQuestionAsked(false)
{
+ mCheckVacation = new KSieveUi::MultiImapVacationManager( this );
+ connect( mCheckVacation, SIGNAL(scriptActive(bool,QString)), SIGNAL(updateVacationScriptStatus(bool,QString)) );
+ connect( mCheckVacation, SIGNAL(scriptActive(bool,QString)), SLOT(slotUpdateVacationScriptStatus(bool,QString)) );
}
VacationManager::~VacationManager()
{
+ mCheckVacation = 0;
+ mMultiImapVacationDialog = 0;
}
void VacationManager::checkVacation()
{
- delete mCheckVacation;
-
- mCheckVacation = new KSieveUi::MultiImapVacationManager( this );
- connect( mCheckVacation, SIGNAL(scriptActive(bool,QString)), SIGNAL(updateVacationScriptStatus(bool,QString)) );
- connect( mCheckVacation, SIGNAL(requestEditVacation()), SIGNAL(editVacation()) );
mCheckVacation->checkVacation();
}
+void VacationManager::slotUpdateVacationScriptStatus(bool active, const QString &serverName)
+{
+ if (active) {
+ if (!mQuestionAsked) {
+ mQuestionAsked = true;
+ 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 ) {
+ slotEditVacation(serverName);
+ }
+ }
+ }
+}
+
+
void VacationManager::slotEditVacation(const QString &serverName)
{
if ( mMultiImapVacationDialog ) {
- mMultiImapVacationDialog->show();
mMultiImapVacationDialog->raise();
mMultiImapVacationDialog->activateWindow();
- if (!serverName.isEmpty()) {
- mMultiImapVacationDialog->switchToServerNamePage(serverName);
- }
- return;
+ } else {
+ mMultiImapVacationDialog = new KSieveUi::MultiImapVacationDialog(mCheckVacation, mWidget);
+ connect( mMultiImapVacationDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) );
+ connect( mMultiImapVacationDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCanceled()) );
}
- mMultiImapVacationDialog = new KSieveUi::MultiImapVacationDialog(mWidget);
- connect( mMultiImapVacationDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) );
- connect( mMultiImapVacationDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCanceled()) );
mMultiImapVacationDialog->show();
if (!serverName.isEmpty()) {
mMultiImapVacationDialog->switchToServerNamePage(serverName);
@@ -80,6 +95,7 @@
QList<KSieveUi::VacationCreateScriptJob *> listJob = mMultiImapVacationDialog->listCreateJob();
Q_FOREACH (KSieveUi::VacationCreateScriptJob *job, listJob) {
connect(job, SIGNAL(scriptActive(bool,QString)), SIGNAL(updateVacationScriptStatus(bool,QString)));
+ job->setKep14Support(mCheckVacation->kep14Support(job->serverName()));
job->start();
}
mMultiImapVacationDialog->delayedDestruct();
Index: libksieve/ksieveui/vacation/vacationpagewidget.h
===================================================================
--- libksieve/ksieveui/vacation/vacationpagewidget.h
+++ libksieve/ksieveui/vacation/vacationpagewidget.h
@@ -29,6 +29,8 @@
class VacationEditWidget;
class VacationWarningWidget;
class VacationCreateScriptJob;
+class MultiImapVacationManager;
+class ParseUserScriptJob;
class VacationPageWidget : public QWidget
{
Q_OBJECT
@@ -40,11 +42,15 @@
void setServerName(const QString &serverName);
KSieveUi::VacationCreateScriptJob *writeScript();
void setDefault();
+ void setVacationManager(MultiImapVacationManager *vacationManager);
private slots:
- void slotGetResult(KManageSieve::SieveJob *job, bool success, const QString &script, bool active);
+ void slotGetResult(const QString &serverName, const QStringList &sieveCapabilities, const QString &scriptName, const QString &script, bool active);
private:
+
+ void fillWithDefaults();
+
enum PageType {
Script = 0,
ScriptNotSupported = 1
@@ -56,7 +62,7 @@
QStackedWidget *mStackWidget;
VacationEditWidget *mVacationEditWidget;
VacationWarningWidget *mVacationWarningWidget;
- KManageSieve::SieveJob *mSieveJob;
+ MultiImapVacationManager *mVacationManager;
bool mWasActive;
};
}
Index: libksieve/ksieveui/vacation/vacationpagewidget.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationpagewidget.cpp
+++ libksieve/ksieveui/vacation/vacationpagewidget.cpp
@@ -20,6 +20,8 @@
#include "vacationwarningwidget.h"
#include "vacationcreatescriptjob.h"
#include "vacationutils.h"
+#include "multiimapvacationmanager.h"
+#include <managescriptsjob/parseuserscriptjob.h>
#include "sieve-vacation.h"
#include <kmime/kmime_header_parsing.h>
@@ -37,7 +39,6 @@
VacationPageWidget::VacationPageWidget(QWidget *parent)
: QWidget(parent),
mPageScript(Script),
- mSieveJob(0),
mWasActive(false)
{
QVBoxLayout *lay = new QVBoxLayout;
@@ -79,18 +80,20 @@
VacationPageWidget::~VacationPageWidget()
{
- if ( mSieveJob )
- mSieveJob->kill();
- mSieveJob = 0;
}
void VacationPageWidget::setServerUrl(const KUrl &url)
{
mUrl = url;
mVacationEditWidget->setEnabled(false);
- mSieveJob = KManageSieve::SieveJob::get( url );
- connect( mSieveJob, SIGNAL(gotScript(KManageSieve::SieveJob*,bool,QString,bool)),
- SLOT(slotGetResult(KManageSieve::SieveJob*,bool,QString,bool)) );
+}
+
+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)
@@ -98,24 +101,28 @@
mServerName = serverName;
}
-void VacationPageWidget::slotGetResult( KManageSieve::SieveJob * job, bool success, const QString & script, bool active )
+void VacationPageWidget::slotGetResult(const QString &serverName, const QStringList &sieveCapabilities, const QString &scriptName, const QString &script, bool active)
{
- kDebug() << success
- << ", ?," << active << ")" << endl
+ if (serverName != mServerName) {
+ return;
+ }
+
+ kDebug() << serverName << sieveCapabilities << endl
+ << scriptName << "(" << active << ")" << endl
<< "script:" << endl
<< script;
- mSieveJob = 0; // job deletes itself after returning from this slot!
if ( mUrl.protocol() == QLatin1String("sieve") &&
- !job->sieveCapabilities().contains(QLatin1String("vacation")) ) {
+ !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") && job->sieveCapabilities().contains(QLatin1String("date"));
+ const bool supportsSieveDate = mUrl.protocol() == QLatin1String("sieve") && sieveCapabilities.contains(QLatin1String("date"));
- mVacationEditWidget->setEnabled(true);
QString messageText = VacationUtils::defaultMessageText();
QString subject = VacationUtils::defaultSubject();
int notificationInterval = VacationUtils::defaultNotificationInterval();
@@ -124,14 +131,17 @@
QString domainName = VacationUtils::defaultDomainName();
QDate startDate = VacationUtils::defaultStartDate();
QDate endDate = VacationUtils::defaultEndDate();
- if ( !success )
- active = false; // default to inactive
+ bool scriptActive = true;
- if ( ( !success || !KSieveUi::VacationUtils::parseScript( script, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate ) ) )
+ const bool bParse = KSieveUi::VacationUtils::parseScript(script, scriptActive, messageText, subject, notificationInterval, aliases, sendForSpam, domainName, startDate, endDate);
+
+ if (!bParse) {
mVacationWarningWidget->setVisible(true);
+ }
mWasActive = active;
- mVacationEditWidget->setActivateVacation( active );
+ mVacationEditWidget->setEnabled(true);
+ mVacationEditWidget->setActivateVacation( active && scriptActive );
mVacationEditWidget->setMessageText( messageText );
mVacationEditWidget->setSubject( subject );
mVacationEditWidget->setNotificationInterval( notificationInterval );
@@ -149,13 +159,16 @@
//emit scriptActive( mWasActive, mServerName );
}
+
+
KSieveUi::VacationCreateScriptJob *VacationPageWidget::writeScript()
{
if (mPageScript == Script) {
KSieveUi::VacationCreateScriptJob *createJob = new KSieveUi::VacationCreateScriptJob;
createJob->setServerUrl(mUrl);
createJob->setServerName(mServerName);
- const QString script = VacationUtils::composeScript( mVacationEditWidget->messageText(),
+ const bool active = mVacationEditWidget->activateVacation();
+ const QString script = VacationUtils::composeScript( mVacationEditWidget->messageText(), active,
mVacationEditWidget->subject(),
mVacationEditWidget->notificationInterval(),
mVacationEditWidget->mailAliases(),
@@ -163,7 +176,6 @@
mVacationEditWidget->domainName(),
mVacationEditWidget->startDate(),
mVacationEditWidget->endDate() );
- const bool active = mVacationEditWidget->activateVacation();
createJob->setStatus(active, mWasActive);
//Q_EMIT scriptActive( active, mServerName);
createJob->setScript(script);
Index: libksieve/ksieveui/vacation/vacationscriptextractor.h
===================================================================
--- libksieve/ksieveui/vacation/vacationscriptextractor.h
+++ libksieve/ksieveui/vacation/vacationscriptextractor.h
@@ -80,14 +80,14 @@
#undef FOREACH
#endif
#define FOREACH for ( std::vector<KSieve::ScriptBuilder*>::const_iterator it = mBuilders.begin(), end = mBuilders.end() ; it != end ; ++it ) (*it)->
- void commandStart( const QString & identifier ) { FOREACH commandStart( identifier ); }
- void commandEnd() { FOREACH commandEnd(); }
+ 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() { FOREACH blockStart(); }
- void blockEnd() { FOREACH blockEnd(); }
+ 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(); }
@@ -143,9 +143,11 @@
unsigned int mState;
int mNestingDepth;
+ int mLineNumber;
+
public:
GenericInformationExtractor( const std::vector<StateNode> & nodes )
- : KSieve::ScriptBuilder(), mNodes( nodes ), mState( 0 ), mNestingDepth( 0 ) {}
+ : KSieve::ScriptBuilder(), mNodes( nodes ), mState( 0 ), mNestingDepth( 0 ), mLineNumber(0) {}
const std::map<QString,QString> & results() const { return mResults; }
@@ -180,17 +182,17 @@
doProcess( method, string );
}
}
- void commandStart( const QString & identifier ) { kDebug() ; process( CommandStart, identifier ); }
- void commandEnd() { kDebug() ; process( CommandEnd ); }
- void testStart( const QString & identifier ) { kDebug() ; process( TestStart, identifier ); }
+ void commandStart( const QString & identifier, int lineNumber ) { kDebug() << identifier ; process( CommandStart, identifier ); }
+ void commandEnd(int lineNumber) { kDebug() ; process( CommandEnd ); }
+ void testStart( const QString & identifier ) { kDebug() << identifier ; process( TestStart, identifier ); }
void testEnd() { kDebug() ; process( TestEnd ); }
void testListStart() { kDebug() ; process( TestListStart ); }
void testListEnd() { kDebug() ; process( TestListEnd ); }
- void blockStart() { kDebug() ; process( BlockStart ); ++mNestingDepth; }
- void blockEnd() { kDebug() ; --mNestingDepth; process( BlockEnd ); }
+ void blockStart(int lineNumber) { kDebug() ; process( BlockStart ); ++mNestingDepth; }
+ void blockEnd(int lineNumber) { kDebug() ; --mNestingDepth; process( BlockEnd ); }
void hashComment( const QString & ) { kDebug() ; }
void bracketComment( const QString & ) { kDebug() ; }
- void lineFeed() { kDebug() ; }
+ void lineFeed() { kDebug() << ++mLineNumber; }
void error( const KSieve::Error & ) {
kDebug() ;
mState = 0;
@@ -208,34 +210,39 @@
typedef GenericInformationExtractor GIE;
static const GenericInformationExtractor::StateNode spamNodes[] = {
{ 0, GIE::CommandStart, "if", 1, 0, 0 }, // 0
- { 0, GIE::TestStart, "header", 2, 0, 0 }, // 1
- { 0, GIE::TaggedArgument, "contains", 3, 0, 0 }, // 2
+ { 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", 9, 4, "x-spam-flag" }, // 3
- { 0, GIE::StringListArgumentStart, 0, 5, 0, 0 }, // 4
- { 0, GIE::StringListEntry, "x-spam-flag", 6, 7, "x-spam-flag" }, // 5
- { 0, GIE::StringListEntry, 0, 6, 8, 0 }, // 6
- { 0, GIE::StringListArgumentEnd, 0, 0, 5, 0 }, // 7
- { 0, GIE::StringListArgumentEnd, 0, 9, 0, 0 }, // 8
+ { 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", 15, 10, "spam-flag-yes" }, // 9
- { 0, GIE::StringListArgumentStart, 0, 11, 0, 0 }, // 10
- { 0, GIE::StringListEntry, "yes", 12, 13, "spam-flag-yes" }, // 11
- { 0, GIE::StringListEntry, 0, 12, 14, 0 }, // 12
- { 0, GIE::StringListArgumentEnd, 0, 0, 11, 0 }, // 13
- { 0, GIE::StringListArgumentEnd, 0, 15, 0, 0 }, // 14
+ { 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, 16, 0, 0 }, // 15
+ { 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, 17, 0, 0 }, // 16
- { 1, GIE::CommandStart, "stop", 20, 19, "stop" }, // 17
- { -1, GIE::Any, 0, 17, 0, 0 }, // 18
- { 0, GIE::BlockEnd, 0, 0, 18, 0 }, // 19
+ { 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, 20, 20, 0 }, // 20 end state
+ { -1, GIE::Any, 0, 25, 25, 0 }, // 25 end state
};
static const unsigned int numSpamNodes = sizeof spamNodes / sizeof *spamNodes ;
@@ -250,7 +257,7 @@
bool found() const {
return mResults.count( QLatin1String("x-spam-flag") ) &&
mResults.count( QLatin1String("spam-flag-yes") ) &&
- mResults.count( QLatin1String("stop") ) ;
+ mResults.count( QLatin1String("vacation") ) ;
}
};
@@ -259,39 +266,40 @@
// '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, "not", 2, 0, 0, }, // 1
- { 0, GIE::TestStart, "address", 3, 0, 0 }, // 2
+ { 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", 4, 5, 0 }, // 3
- { 0, GIE::TaggedArgument, "contains", 7, 0, 0 }, // 4
- { 0, GIE::TaggedArgument, "contains", 6, 0, 0 }, // 5
- { 0, GIE::TaggedArgument, "domain", 7, 0, 0 }, // 6
+ { 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", 13, 8, "from" }, // 7
- { 0, GIE::StringListArgumentStart, 0, 9, 0, 0 }, // 8
- { 0, GIE::StringListEntry, "from", 10, 11, "from" }, // 9
- { 0, GIE::StringListEntry, 0, 10, 12, 0 }, // 10
- { 0, GIE::StringListArgumentEnd, 0, 0, 9, 0 }, // 11
- { 0, GIE::StringListArgumentEnd, 0, 13, 0, 0 }, // 12
+ { 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, 17, 14, "domainName" }, // 13
- { 0, GIE::StringListArgumentStart, 0, 15, 0, 0 }, // 14
- { 0, GIE::StringListEntry, 0, 15, 16, "domainName" }, // 15
- { 0, GIE::StringListArgumentEnd, 0, 17, 0, 0 }, // 16
+ { 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, 0, 0 }, // 17
- { 0, GIE::TestEnd, 0, 19, 0, 0 }, // 18
+ { 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, 20, 0, 0 }, // 19
- { 1, GIE::CommandStart, "stop", 23, 22, "stop" }, // 20
- { -1, GIE::Any, 0, 20, 0, 0 }, // 21
- { 0, GIE::BlockEnd, 0, 0, 21, 0 }, // 22
+ { 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, 23, 23, 0 } // 23 end state
+ { -1, GIE::Any, 0, 24, 24, 0 } // 24 end state
};
static const unsigned int numDomainNodes = sizeof domainNodes / sizeof *domainNodes ;
@@ -304,7 +312,7 @@
}
QString domainName() /*not const, since map::op[] isn't const*/ {
- return mResults.count( QLatin1String("stop") ) && mResults.count( QLatin1String("from") )
+ return mResults.count( QLatin1String("vacation") ) && mResults.count( QLatin1String("from") )
? mResults[QLatin1String("domainName")] : QString();
}
};
@@ -313,42 +321,44 @@
// 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, "not", 2, 0, 0 }, // 1
- { 0, GIE::TestStart, "allof", 3, 0, 0 }, // 2
+ { 0, GIE::TestStart, "allof", 2, 0, 0 }, // 1
// handle startDate and endDate in arbitrary order
- { 0, GIE::TestListStart, 0, 4, 0, 0 }, // 3
- { 0, GIE::TestStart, "currentdate", 5, 0, 0 }, // 4
- { 0, GIE::TaggedArgument, "value", 6, 0, 0 }, // 5
- { 0, GIE::StringArgument, "ge", 7, 9, 0 }, // 6
- { 0, GIE::StringArgument, "date", 8, 0, 0 }, // 7
- { 0, GIE::StringArgument, 0, 12, 0, "startDate" }, // 8
- { 0, GIE::StringArgument, "le", 10, 0, 0 }, // 9
- { 0, GIE::StringArgument, "date", 11, 0, 0 }, // 10
- { 0, GIE::StringArgument, 0, 12, 0, "endDate" }, // 11
- { 0, GIE::TestEnd, 0, 13, 0, 0 }, // 12
-
- { 0, GIE::TestStart, "currentdate", 14, 0, 0 }, // 13
- { 0, GIE::TaggedArgument, "value", 15, 0, 0 }, // 14
- { 0, GIE::StringArgument, "le", 16, 18, 0 }, // 15
- { 0, GIE::StringArgument, "date", 17, 0, 0 }, // 16
- { 0, GIE::StringArgument, 0, 21, 0, "endDate" }, // 17
- { 0, GIE::StringArgument, "ge", 19, 0, 0 }, // 18
- { 0, GIE::StringArgument, "date", 20, 0, 0 }, // 19
- { 0, GIE::StringArgument, 0, 21, 0, "startDate" }, // 20
- { 0, GIE::TestEnd, 0, 22, 0, 0 }, // 21
- { 0, GIE::TestListEnd, 0, 23, 0, 0 }, // 22
-
- { 0, GIE::TestEnd, 0, 24, 0, 0 }, // 23
- { 0, GIE::TestEnd, 0, 25, 0, 0 }, // 24
+ { 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, 8, 0 }, // 5
+ { 0, GIE::StringArgument, "date", 7, 0, 0 }, // 6
+ { 0, GIE::StringArgument, 0, 11, 0, "startDate" }, // 7
+ { 0, GIE::StringArgument, "le", 9, 0, 0 }, // 8
+ { 0, GIE::StringArgument, "date", 10, 0, 0 }, // 9
+ { 0, GIE::StringArgument, 0, 11, 0, "endDate" }, // 10
+ { 0, GIE::TestEnd, 0, 12, 0, 0 }, // 11
+
+ { 0, GIE::TestStart, "currentdate", 13, 12, 0 }, // 12
+ { 0, GIE::TaggedArgument, "value", 14, 13, 0 }, // 13
+ { 0, GIE::StringArgument, "le", 15, 17, 0 }, // 14
+ { 0, GIE::StringArgument, "date", 16, 0, 0 }, // 15
+ { 0, GIE::StringArgument, 0, 20, 0, "endDate" }, // 16
+ { 0, GIE::StringArgument, "ge", 18, 0, 0 }, // 17
+ { 0, GIE::StringArgument, "date", 19, 0, 0 }, // 18
+ { 0, GIE::StringArgument, 0, 20, 0, "startDate" }, // 19
+ { 0, GIE::TestEnd, 0, 24, 0, 0 }, // 20
+ { 0, GIE::TestStart, 0, 23, 22, 0 }, // 21
+ { -1, GIE::Any, 0, 24, 0, 0 }, // 22
+ { 0, GIE::TestEnd, 0, 24, 22, 0 }, // 23
+ { 0, GIE::TestListEnd, 0, 25, 21, 0 }, // 24
+
+ { 0, GIE::TestEnd, 0, 26, 0, 0 }, // 25
// block of commands, find "stop", take nested if's into account:
- { 0, GIE::BlockStart, 0, 26, 0, 0 }, // 25
- { 1, GIE::CommandStart, "stop", 29, 28, "stop" }, // 26
- { -1, GIE::Any, 0, 26, 0, 0 }, // 27
- { 0, GIE::BlockEnd, 0, 0, 27, 0 }, // 28
+ { 0, GIE::BlockStart, 0, 28, 25, 0 }, // 26
+ { -1, GIE::Any, 0, 28, 0, 0 }, // 27
+ { 1, GIE::CommandStart, "vacation", 30, 27, "vacation" }, // 28
+ { -1, GIE::Any, 0, 30, 0, 0 }, // 29
+ { 0, GIE::BlockEnd, 0, 31, 29, 0 }, // 30
- { -1, GIE::Any, 0, 27, 27, 0 } // 29 end state
+ { -1, GIE::Any, 0, 31, 31, 0 } // 31 end state
};
static const unsigned int numDatesNodes = sizeof datesNodes / sizeof *datesNodes;
@@ -387,34 +397,42 @@
// command itself:
VacationCommand,
// tagged args:
- Days, Addresses, Subject
+ Days, Addresses, Subject,
+ VacationEnd,
+ IfBlock
};
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; }
const QString &subject() const
{
return mSubject;
}
+ int lineStart() const {return mLineStart;}
+ int lineEnd() const {return mLineEnd;}
+
private:
- void commandStart( const QString & identifier );
+ void commandStart( const QString & identifier, int lineNumber );
- void commandEnd();
+ void commandEnd(int lineNumber);
- void testStart( const QString & ) {}
+ void testStart( const QString &);
void testEnd() {}
void testListStart() {}
void testListEnd() {}
- void blockStart() {}
- void blockEnd() {}
- void hashComment( const QString & ) {}
- void bracketComment( const QString & ) {}
+ 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();
@@ -435,10 +453,65 @@
QString mMessageText;
QString mSubject;
QStringList mAliases;
+ bool mActive;
+ bool mInIfBlock;
+ int mBlockLevel;
+ QString mIfComment;
+ int mLineStart;
+ int mLineEnd;
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;
+};
}
Index: libksieve/ksieveui/vacation/vacationscriptextractor.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationscriptextractor.cpp
+++ libksieve/ksieveui/vacation/vacationscriptextractor.cpp
@@ -22,6 +22,11 @@
: KSieve::ScriptBuilder(),
mContext( None ),
mNotificationInterval( 0 )
+ , mActive(true)
+ , mInIfBlock(false)
+ , mBlockLevel(0)
+ , mLineStart(0)
+ , mLineEnd(0)
{
kDebug();
}
@@ -31,17 +36,29 @@
}
-void VacationDataExtractor::commandStart( const QString & identifier ) {
+void VacationDataExtractor::commandStart( const QString & identifier, int lineNumber ) {
kDebug() << "( \"" << identifier <<"\" )";
+ if (identifier == QLatin1String("if") && mContext == None) {
+ mContext = IfBlock;
+ mLineStart = lineNumber;
+ mInIfBlock = true;
+ }
if ( identifier != QLatin1String("vacation") )
return;
+
+ if (mContext != IfBlock) {
+ mLineStart = lineNumber;
+ }
+
reset();
mContext = VacationCommand;
}
-void VacationDataExtractor::commandEnd() {
- kDebug();
- mContext = None;
+void VacationDataExtractor::commandEnd(int lineNumber) {
+ if ( mContext != None && mContext != IfBlock && mContext != VacationEnd) {
+ mContext = VacationEnd;
+ mLineEnd = lineNumber;
+ }
}
void VacationDataExtractor::error( const KSieve::Error & e )
@@ -54,6 +71,42 @@
}
+void VacationDataExtractor::testStart(const QString &test)
+{
+ if (mContext == IfBlock) {
+ if (test == QLatin1String("true") || test == QLatin1String("false")) {
+ mActive = (test == QLatin1String("true"));
+ mIfComment = QString();
+ kDebug() << "set active level to" << mActive;
+ }
+ }
+}
+
+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 )
{
kDebug() << "( \"" << tag <<"\" )";
@@ -123,3 +176,53 @@
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
Index: libksieve/ksieveui/vacation/vacationutils.h
===================================================================
--- libksieve/ksieveui/vacation/vacationutils.h
+++ libksieve/ksieveui/vacation/vacationutils.h
@@ -40,17 +40,27 @@
QDate defaultStartDate();
QDate defaultEndDate();
-QString composeScript( const QString & messageText, const QString &subject,
+QString composeScript( const QString & messageText, bool active, const QString &subject,
int notificationInterval,
const KMime::Types::AddrSpecList & aliases,
bool sendForSpam, const QString & excludeDomain,
const QDate & startDate, const QDate & endDate );
-bool parseScript( const QString & script, QString & messageText,
+bool parseScript( const QString & script, bool &active, QString & messageText,
QString &subject,
int & notificationInterval, QStringList & aliases,
bool & sendForSpam, QString & domainName,
QDate & startDate, QDate & endDate );
+//returns if a vacation script is found in the sieve script
+bool foundVacationScript(const QString &script);
+
+// returns if the vacation script is active
+bool vacationScriptActive(const QString &script);
+
+QString mergeRequireLine(const QString &script1, const QString script2);
+
+QString updateVacationBlock(const QString &oldScript, const QString &newScript);
+
}
}
Index: libksieve/ksieveui/vacation/vacationutils.cpp
===================================================================
--- libksieve/ksieveui/vacation/vacationutils.cpp
+++ libksieve/ksieveui/vacation/vacationutils.cpp
@@ -98,13 +98,14 @@
}
-bool KSieveUi::VacationUtils::parseScript( const QString &script, QString &messageText,
+bool KSieveUi::VacationUtils::parseScript( const QString &script, bool &active, QString &messageText,
QString &subject,
int & notificationInterval, QStringList &aliases,
bool & sendForSpam, QString &domainName,
QDate & startDate, QDate & endDate )
{
if ( script.trimmed().isEmpty() ) {
+ active = false;
messageText = VacationUtils::defaultMessageText();
subject = VacationUtils::defaultSubject();
notificationInterval = VacationUtils::defaultNotificationInterval();
@@ -125,26 +126,72 @@
SpamDataExtractor sdx;
DomainRestrictionDataExtractor drdx;
DateExtractor dx;
- KSieveExt::MultiScriptBuilder tsb( &vdx, &sdx, &drdx, &dx );
+ KSieveExt::MultiScriptBuilder tsb( &vdx , &sdx, &drdx, &dx );
parser.setScriptBuilder( &tsb );
- if ( !parser.parse() )
+ parser.parse();
+ if ( !parser.parse() || !vdx.commandFound() ) {
+ active = false;
return false;
+ }
+ active = vdx.active();
messageText = vdx.messageText().trimmed();
if (!vdx.subject().isEmpty()) {
subject = vdx.subject().trimmed();
}
notificationInterval = vdx.notificationInterval();
aliases = vdx.aliases();
- if ( !VacationSettings::allowOutOfOfficeUploadButNoSettings() ) {
- sendForSpam = !sdx.found();
- domainName = drdx.domainName();
+
+ if (!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() ) {
+ return false;
+ }
}
+
+ sendForSpam = !sdx.found();
+ domainName = drdx.domainName();
startDate = dx.startDate();
endDate = dx.endDate();
return true;
}
-QString KSieveUi::VacationUtils::composeScript( const QString & messageText,
+bool KSieveUi::VacationUtils::foundVacationScript(const QString &script)
+{
+ const QByteArray scriptUTF8 = script.trimmed().toUtf8();
+ kDebug() << "scriptUtf8 = \"" + scriptUTF8 +"\"";
+
+ if (scriptUTF8.isEmpty()) {
+ return false;
+ }
+
+ KSieve::Parser parser( scriptUTF8.begin(),
+ scriptUTF8.begin() + scriptUTF8.length() );
+ VacationDataExtractor vdx;
+ parser.setScriptBuilder(&vdx);
+ return parser.parse() && vdx.commandFound();
+}
+
+bool KSieveUi::VacationUtils::vacationScriptActive(const QString &script)
+{
+ const QByteArray scriptUTF8 = script.trimmed().toUtf8();
+ kDebug() << "scriptUtf8 = \"" + scriptUTF8 +"\"";
+
+ if (scriptUTF8.isEmpty()) {
+ return false;
+ }
+
+ KSieve::Parser parser( scriptUTF8.begin(),
+ scriptUTF8.begin() + scriptUTF8.length() );
+ VacationDataExtractor vdx;
+ parser.setScriptBuilder(&vdx);
+ return parser.parse() && vdx.commandFound() && vdx.active();
+}
+
+QString composeOldScript( const QString & messageText,
const QString &subject,
int notificationInterval,
const AddrSpecList & addrSpecs,
@@ -194,8 +241,198 @@
}
script += QString::fromLatin1("text:\n");
- script += dotstuff( messageText.isEmpty() ? VacationUtils::defaultMessageText() : messageText );
+ script += dotstuff( messageText.isEmpty() ? KSieveUi::VacationUtils::defaultMessageText() : messageText );
script += QString::fromLatin1( "\n.\n;\n" );
return script;
}
+QString KSieveUi::VacationUtils::composeScript( const QString & messageText, bool active,
+ const QString &subject,
+ int notificationInterval,
+ const AddrSpecList & addrSpecs,
+ bool sendForSpam, const QString & domain,
+ const QDate & startDate, const QDate & endDate )
+{
+ QStringList condition;
+
+ if (startDate.isValid()) {
+ condition.append(QString::fromLatin1("currentdate :value \"ge\" \"date\" \"%1\"")
+ .arg(startDate.toString(Qt::ISODate)));
+ }
+
+ if (endDate.isValid()) {
+ condition.append(QString::fromLatin1("currentdate :value \"le\" \"date\" \"%1\"")
+ .arg(endDate.toString(Qt::ISODate)));
+ }
+
+ if (!sendForSpam) {
+ condition.append(QString::fromLatin1("not header :contains \"X-Spam-Flag\" \"YES\""));
+ }
+
+ if (!domain.isEmpty()) {
+ condition.append(QString::fromLatin1("address :domain :contains \"from\" \"%1\"").arg( domain ));
+ }
+
+ 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 vacation(QLatin1String("vacation "));
+ vacation += addressesArgument;
+ if ( notificationInterval > 0 )
+ vacation += QString::fromLatin1(":days %1 ").arg(notificationInterval);
+
+ if (!subject.trimmed().isEmpty()) {
+ vacation += QString::fromLatin1(":subject \"%1\" ").arg(stringReplace(subject).trimmed());
+ }
+
+ vacation += QString::fromLatin1("text:\n");
+ vacation += dotstuff( messageText.isEmpty() ? VacationUtils::defaultMessageText() : messageText );
+ vacation += QString::fromLatin1( "\n.\n;" );
+
+ 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 (condition.count() == 0) {
+ if (active) {
+ script += vacation;
+ } else {
+ script += QString::fromLatin1("if false\n{\n\t");
+ script += vacation;
+ script += QLatin1String("\n}");
+ }
+ } else {
+ if (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 += vacation;
+ 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<QString> 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);
+
+ int startNew(vdxNew.lineStart());
+ int endNew(vdxNew.lineEnd());
+
+ 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"));
+}
Index: libksieve/ksieveui/widgets/managesievewidget.h
===================================================================
--- libksieve/ksieveui/widgets/managesievewidget.h
+++ libksieve/ksieveui/widgets/managesievewidget.h
@@ -35,6 +35,7 @@
namespace KSieveUi {
class ManageSieveTreeView;
+class ParseUserScriptJob;
class KSIEVEUI_EXPORT ManageSieveWidget : public QWidget
{
Q_OBJECT
@@ -65,6 +66,7 @@
void slotDoubleClicked(QTreeWidgetItem *item);
void slotSystemNetworkStatusChanged(Solid::Networking::Status status);
void slotCheckNetworkStatus();
+ void setActiveScripts(ParseUserScriptJob *job);
public Q_SLOTS:
void slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &listScript, const QString &activeScript);
@@ -91,8 +93,6 @@
bool isFileNameItem(QTreeWidgetItem *item) const;
bool itemIsActived(QTreeWidgetItem *item) const;
void changeActiveScript(QTreeWidgetItem *item, bool activate);
- bool isProtectedName(const QString &name);
-
// Maps top-level items to their child which has the radio button selection
QMap<QTreeWidgetItem*,QTreeWidgetItem*> mSelectedItems;
Index: libksieve/ksieveui/widgets/managesievewidget.cpp
===================================================================
--- libksieve/ksieveui/widgets/managesievewidget.cpp
+++ libksieve/ksieveui/widgets/managesievewidget.cpp
@@ -21,6 +21,9 @@
#include <kmanagesieve/sievejob.h>
+#include <managescriptsjob/parseuserscriptjob.h>
+#include <managescriptsjob/generateglobalscriptjob.h>
+#include <util/util.h>
#include <KInputDialog>
#include <KStandardGuiItem>
@@ -31,8 +34,11 @@
#include <QMenu>
#include <QTimer>
#include <QDebug>
+#include <qmetatype.h>
using namespace KSieveUi;
+Q_DECLARE_METATYPE(QTreeWidgetItem*)
+
ManageSieveWidget::ManageSieveWidget(QWidget *parent)
: QWidget(parent),
mClearAll( false ),
@@ -174,7 +180,7 @@
if ( !ok || name.isEmpty() )
return;
- if (isProtectedName(name.toLower())) {
+ if (Util::isKep14ProtectedName(name)) {
KMessageBox::error(this, i18n("You cannot use protected name."), i18n("New Script"));
return;
}
@@ -245,11 +251,27 @@
KUrl u = mUrls[item];
if ( u.isEmpty() )
return;
+
+ if (item->data(0, SIEVE_SERVER_MODE).toInt() == Kep14EditorMode) {
+ QStringList activeScripts;
+ for(int i=0; i < item->childCount(); i++) {
+ QTreeWidgetItem *j = item->child(i);
+ if (itemIsActived(j)) {
+ activeScripts << j->text(0);
+ }
+ }
+ GenerateGlobalScriptJob *job = new GenerateGlobalScriptJob(u);
+ job->addUserActiveScripts(activeScripts);
+ connect( job, SIGNAL(success()), SLOT(slotRefresh()));
+ connect( job, SIGNAL(error(QString)), SLOT(slotRefresh()));
+ job->start();
+ return;
+ }
+
QTreeWidgetItem* selected = mSelectedItems[item];
if ( !selected )
return;
u.setFileName( selected->text(0) );
-
KManageSieve::SieveJob * job;
if ( activate )
job = KManageSieve::SieveJob::activate( u );
@@ -311,16 +333,6 @@
Q_EMIT scriptDeleted(u);
}
-bool ManageSieveWidget::isProtectedName(const QString &name)
-{
- if (name == QLatin1String("master") ||
- name == QLatin1String("user") ||
- name == QLatin1String("management")) {
- return true;
- }
- return false;
-}
-
void ManageSieveWidget::slotRefresh()
{
mBlockSignal = true;
@@ -342,9 +354,7 @@
qDebug()<<"void ManageSieveWidget::slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &listScript, const QString &activeScript) success: "<<success<<" listScript"<<listScript;
if (mClearAll)
return;
- qDebug()<<" After mClear All";
QTreeWidgetItem * parent = mJobs[job];
- qDebug()<<" parent "<<parent;
if ( !parent )
return;
(static_cast<SieveTreeWidgetItem*>(parent))->stopAnimation();
@@ -364,8 +374,7 @@
mBlockSignal = true; // don't trigger slotItemChanged
Q_FOREACH (const QString &script, listScript) {
//Hide protected name.
- const QString lowerScript(script.toLower());
- if (isProtectedName(lowerScript))
+ if (Util::isKep14ProtectedName(script))
continue;
QTreeWidgetItem* item = new QTreeWidgetItem( parent );
item->setFlags(item->flags() & (Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable));
@@ -379,20 +388,60 @@
}
mBlockSignal = false;
- qDebug()<<" LOAD";
- const bool hasIncludeCapability = job->sieveCapabilities().contains(QLatin1String("include"));
- const bool hasUserActiveScript = (activeScript.toLower() == QLatin1String("USER"));
- QStringList mUserActiveScriptList;
- if (hasUserActiveScript && hasIncludeCapability) {
- //TODO parse file.
+ const bool hasKep14EditorMode = Util::hasKep14Support(job->sieveCapabilities(), listScript, activeScript);
+ if (hasKep14EditorMode) {
+ KUrl u = mUrls[parent];
+ u.setFileName(QLatin1String("USER"));
+ ParseUserScriptJob *parseJob = new ParseUserScriptJob(u);
+ parseJob->setProperty(QLatin1String("parentItem").latin1(), QVariant::fromValue<QTreeWidgetItem*>(parent));
+ connect(parseJob, SIGNAL(finished(ParseUserScriptJob*)), SLOT(setActiveScripts(ParseUserScriptJob*)));
+ parseJob->start();
+ (static_cast<SieveTreeWidgetItem*>(parent))->startAnimation();
}
parent->setData( 0, SIEVE_SERVER_CAPABILITIES, job->sieveCapabilities() );
parent->setData( 0, SIEVE_SERVER_ERROR, false );
- parent->setData( 0, SIEVE_SERVER_MODE, hasIncludeCapability ? Kep14EditorMode : NormalEditorMode);
+ parent->setData( 0, SIEVE_SERVER_MODE, hasKep14EditorMode ? Kep14EditorMode : NormalEditorMode);
mTreeView->expandItem( parent );
}
+void ManageSieveWidget::setActiveScripts(ParseUserScriptJob *job)
+{
+ QTreeWidgetItem * parent = job->property(QLatin1String("parentItem").latin1()).value<QTreeWidgetItem*>();
+ if ( !parent ) {
+ return;
+ }
+ (static_cast<SieveTreeWidgetItem*>(parent))->stopAnimation();
+
+ if (!job->error().isEmpty()) {
+ qWarning() << job->error();
+ return;
+ }
+
+ mBlockSignal = true; // don't trigger slotItemChanged
+ const QStringList activeScriptList = job->activeScriptList();
+ QStringList scriptOrder = activeScriptList;
+ QMap<QString, QTreeWidgetItem*> scriptMap;
+
+ const int children = parent->childCount();
+ for(int i=0; i < children; i++) {
+ QTreeWidgetItem *item = parent->takeChild(0);
+ scriptMap.insert(item->text(0), item);
+ const bool isActive = activeScriptList.contains(item->text(0));
+ item->setCheckState(0, isActive ? Qt::Checked : Qt::Unchecked);
+ if (!isActive) {
+ scriptOrder << item->text(0);
+ }
+ }
+
+ foreach(const QString &scriptName, scriptOrder) {
+ parent->addChild(scriptMap[scriptName]);
+ }
+
+ mBlockSignal = false;
+}
+
+
void ManageSieveWidget::slotDoubleClicked( QTreeWidgetItem * item )
{
if ( !isFileNameItem( item ) )
Index: libksieve/parser/lexer.cpp
===================================================================
--- libksieve/parser/lexer.cpp
+++ libksieve/parser/lexer.cpp
@@ -161,7 +161,7 @@
#endif
static QString removeCRLF( const QString & s ) {
const bool CRLF = s.endsWith( QLatin1String("\r\n") );
- const bool LF = !CRLF && s.endsWith( '\n' );
+ const bool LF = !CRLF && s.endsWith( QLatin1Char('\n') );
const int e = CRLF ? 2 : LF ? 1 : 0 ; // what to chop off at the end
@@ -255,7 +255,7 @@
case ')':
case ';':
case ',': // Special
- result = *mState.cursor++;
+ result = QLatin1Char(*mState.cursor++);
return Special;
case '0':
case '1':
@@ -401,7 +401,7 @@
}
if ( reallySave ) {
QString tmp = QString::fromUtf8( commentStart, commentLength );
- result += tmp.remove( '\r' ); // get rid of CR in CRLF pairs
+ result += tmp.remove( QLatin1Char('\r') ); // get rid of CR in CRLF pairs
}
}
@@ -505,7 +505,7 @@
assert( isdigit( *mState.cursor ) );
while ( !atEnd() && isdigit( *mState.cursor ) )
- result += *mState.cursor++;
+ result += QLatin1Char(*mState.cursor++);
if ( atEnd() || isDelim( *mState.cursor ) )
return true;
@@ -517,7 +517,7 @@
case 'm':
case 'K':
case 'k':
- result += *mState.cursor++;
+ result += QLatin1Char(*mState.cursor++);
break;
default:
makeIllegalCharError();
@@ -589,21 +589,21 @@
}
const QString line = removeCRLF( QString::fromUtf8( oldBeginOfLine, lineLength ) );
lines.push_back( removeDotStuff( line ) );
- if ( line == "." )
+ if ( line == QLatin1String(".") )
break;
} else {
lines.push_back( QString() );
}
}
- if ( lines.back() != "." ) {
+ if ( lines.back() != QLatin1String(".") ) {
makeError( Error::PrematureEndOfMultiLine, mlBeginLine, mlBeginCol );
return false;
}
assert( !lines.empty() );
lines.erase( --lines.end() ); // don't include the lone dot.
- result = lines.join("\n");
+ result = lines.join(QLatin1String("\n"));
return true;
}
@@ -630,7 +630,7 @@
case '\n':
if ( !eatCRLF() )
return false;
- result += '\n';
+ result += QLatin1Char('\n');
break;
case '\\':
++mState.cursor;
@@ -639,7 +639,7 @@
// else fall through:
default:
if ( !is8Bit( *mState.cursor ) )
- result += *mState.cursor++;
+ result += QLatin1Char(*mState.cursor++);
else { // probably UTF-8
const char * const eightBitBegin = mState.cursor;
skipTo8BitEnd();
Index: libksieve/parser/parser.cpp
===================================================================
--- libksieve/parser/parser.cpp
+++ libksieve/parser/parser.cpp
@@ -42,6 +42,8 @@
#include <limits.h> // ULONG_MAX
#include <ctype.h> // isdigit
+#include <KDebug>
+
namespace KSieve {
//
@@ -130,7 +132,7 @@
return isStringToken() ||
token() == Lexer::Number ||
token() == Lexer::Tag ||
- ( token() == Lexer::Special && mTokenValue == "[" );
+ ( token() == Lexer::Special && mTokenValue == QLatin1String("[")) ;
}
bool Parser::Impl::obtainToken() {
@@ -218,8 +220,9 @@
if ( !obtainToken() || token() != Lexer::Identifier )
return false;
- if ( scriptBuilder() )
- scriptBuilder()->commandStart( tokenValue() );
+ if ( scriptBuilder() ) {
+ scriptBuilder()->commandStart( tokenValue(), lexer.line() );
+ }
consumeToken();
//
@@ -251,7 +254,7 @@
return false;
}
- if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list
+ if ( token() == Lexer::Special && tokenValue() == QLatin1String ("(")) { // test-list
if ( !parseTestList() ) {
assert( error() );
return false;
@@ -280,9 +283,9 @@
return false;
}
- if ( tokenValue() == ";" )
+ if ( tokenValue() == QLatin1String (";"))
consumeToken();
- else if ( tokenValue() == "{" ) { // block
+ else if ( tokenValue() == QLatin1String ("{")) { // block
if ( !parseBlock() )
return false; // it's an error since we saw '{'
} else {
@@ -290,8 +293,9 @@
return false;
}
- if ( scriptBuilder() )
- scriptBuilder()->commandEnd();
+ if ( scriptBuilder() ) {
+ scriptBuilder()->commandEnd(lexer.line());
+ }
return true;
}
@@ -334,7 +338,7 @@
scriptBuilder()->stringArgument( tokenValue(), token() == Lexer::MultiLineString, QString() );
consumeToken();
return true;
- } else if ( token() == Lexer::Special && tokenValue() == "[" ) {
+ } else if ( token() == Lexer::Special && tokenValue() == QLatin1String("[")) {
if ( !parseStringList() ) {
assert( error() );
return false;
@@ -352,7 +356,7 @@
if ( !obtainToken() || atEnd() )
return false;
- if ( token() != Lexer::Special || tokenValue() != "(" )
+ if ( token() != Lexer::Special || tokenValue() != QLatin1String("("))
return false;
if ( scriptBuilder() )
scriptBuilder()->testListStart();
@@ -462,7 +466,7 @@
if ( atEnd() ) // a test w/o nested tests
goto TestEnd;
- if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list
+ if ( token() == Lexer::Special && tokenValue() == QLatin1String("(")) { // test-list
if ( !parseTestList() ) {
assert( error() );
return false;
@@ -488,10 +492,10 @@
if ( !obtainToken() || atEnd() )
return false;
- if ( token() != Lexer::Special || tokenValue() != "{" )
+ if ( token() != Lexer::Special || tokenValue() != QLatin1String("{"))
return false;
if ( scriptBuilder() )
- scriptBuilder()->blockStart();
+ scriptBuilder()->blockStart(lexer.line());
consumeToken();
if ( !obtainToken() )
@@ -517,12 +521,12 @@
return false;
}
- if ( token() != Lexer::Special || tokenValue() != "}" ) {
+ if ( token() != Lexer::Special || tokenValue() != QLatin1String("}")) {
makeError( Error::NonCommandInCommandList );
return false;
}
if ( scriptBuilder() )
- scriptBuilder()->blockEnd();
+ scriptBuilder()->blockEnd(lexer.line());
consumeToken();
return true;
}
@@ -538,7 +542,7 @@
if ( !obtainToken() || atEnd() )
return false;
- if ( token() != Lexer::Special || tokenValue() != "[" )
+ if ( token() != Lexer::Special || tokenValue() != QLatin1String("[") )
return false;
if ( scriptBuilder() )
@@ -619,7 +623,7 @@
int i = 0;
const QByteArray s = tokenValue().toLatin1();
for ( const int len = s.length() ; i < len && isdigit( s[i] ) ; ++i ) {
- const unsigned long digitValue = s[i] - '0' ;
+ const unsigned long digitValue = s[i] - QLatin1Char('0').toLatin1() ;
if ( willOverflowULong( result, digitValue ) ) {
makeError( Error::NumberOutOfRange );
return false;
Index: libksieve/tests/parsertest.cpp
===================================================================
--- libksieve/tests/parsertest.cpp
+++ libksieve/tests/parsertest.cpp
@@ -400,12 +400,12 @@
const QString txt = "number" + ( quantifier ? QString(" quantifier=\"%1\"").arg( quantifier ) : QString() ) ;
write( txt.toLatin1(), QString::number( number ) );
}
- void commandStart( const QString & identifier ) {
+ void commandStart( const QString & identifier, int lineNumber) {
write( "<command>" );
++indent;
write( "identifier", identifier );
}
- void commandEnd() {
+ void commandEnd(int lineNumber) {
--indent;
write( "</command>" );
}
@@ -426,11 +426,11 @@
--indent;
write( "</testlist>" );
}
- void blockStart() {
+ void blockStart(int lineNumber) {
write( "<block>" );
++indent;
}
- void blockEnd() {
+ void blockEnd(int lineNumber) {
--indent;
write( "</block>" );
}
@@ -515,12 +515,12 @@
checkEquals( QString::number( number ) + ( quantifier ? quantifier : ' ' ) );
++mNextResponse;
}
- void commandStart( const QString & identifier ) {
+ void commandStart( const QString & identifier, int lineNumber ) {
checkIs( CommandStart );
checkEquals( identifier );
++mNextResponse;
}
- void commandEnd() {
+ void commandEnd(int lineNumber) {
checkIs( CommandEnd );
++mNextResponse;
}
@@ -541,11 +541,11 @@
checkIs( TestListEnd );
++mNextResponse;
}
- void blockStart() {
+ void blockStart(int lineNumber) {
checkIs( BlockStart );
++mNextResponse;
}
- void blockEnd() {
+ void blockEnd(int lineNumber) {
checkIs( BlockEnd );
++mNextResponse;
}

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 5, 5:14 PM (5 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10179219
Default Alt Text
D31.id61.diff (132 KB)

Event Timeline