You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

311 lines
7.8 KiB

// kmfilter.cpp
// Author: Stefan Taferner <taferner@kde.org>
#include "kmfilter.h"
#include "kmglobal.h"
#include "kmmessage.h"
#include <kconfig.h>
#include <qregexp.h>
#include <assert.h>
#include <string.h>
#include <kapp.h>
static const char* opConfigNames[] =
{ "ignore", "and", "unless", "or", NULL };
static const char* funcConfigNames[] =
{ "equals", "not-equal", "contains", "contains-not", "regexp",
"not-regexp", NULL };
KMFilterActionDict* KMFilter::sActionDict = NULL;
//-----------------------------------------------------------------------------
// Case-insensitive. Searches for string in string list and returns index
// or -1 if not found.
static int findInStrList(const char* strList[], const char* str)
{
int i;
assert(strList != NULL);
if (!str) return -1;
for (i=0; strList[i]; i++)
if (strcasecmp(strList[i], str)==0)
{
debug("findInStrList: %s is at %d", str, i);
return i;
}
debug("findInStrList: %s not found", str);
return -1;
}
//-----------------------------------------------------------------------------
KMFilter::KMFilter(KConfig* config)
{
if (!sActionDict) sActionDict = new KMFilterActionDict;
if (config) readConfig(config);
}
//-----------------------------------------------------------------------------
KMFilter::~KMFilter()
{
}
//-----------------------------------------------------------------------------
bool KMFilter::matches(const KMMessage* msg)
{
bool matchesA, matchesB;
matchesA = mRuleA.matches(msg);
if (mOperator==OpIgnore) return matchesA;
if (matchesA && mOperator==OpOr) return TRUE;
if (!matchesA && (mOperator==OpAnd || mOperator==OpAndNot)) return FALSE;
matchesB = mRuleB.matches(msg);
switch (mOperator)
{
case OpAnd:
return (matchesA && matchesB);
case OpAndNot:
return (matchesA && !matchesB);
case OpOr:
return (matchesA || matchesB);
default:
return FALSE;
}
}
//-----------------------------------------------------------------------------
bool KMFilter::execActions(KMMessage* msg, bool& stopIt)
{
int i;
bool stillOwner = TRUE;
stopIt = FALSE;
for (i=0; !stopIt && mAction[i]; i++)
if (!mAction[i]->process(msg,stopIt)) stillOwner = FALSE;
return stillOwner;
}
//-----------------------------------------------------------------------------
void KMFilter::setName(const QString aName)
{
mName = aName.copy();
}
//-----------------------------------------------------------------------------
void KMFilter::setOper(KMFilter::Operator aOperator)
{
mOperator = aOperator;
}
//-----------------------------------------------------------------------------
KMFilterAction* KMFilter::action(int idx) const
{
if (idx<0 || idx >= FILTER_MAX_ACTIONS) return NULL;
return mAction[idx];
}
//-----------------------------------------------------------------------------
void KMFilter::setAction(int idx, KMFilterAction* aAction)
{
if (idx>=0 && idx < FILTER_MAX_ACTIONS)
mAction[idx] = aAction;
}
//-----------------------------------------------------------------------------
void KMFilter::readConfig(KConfig* config)
{
KMFilterRule::Function funcA, funcB;
QString fieldA, fieldB;
QString contA, contB;
int idx, i, j, num;
QString actName(64), argsName(64);
mName = config->readEntry("name").copy();
idx = findInStrList(funcConfigNames, config->readEntry("funcA"));
funcA = (KMFilterRule::Function)(idx >= 0 ? idx : 0);
idx = findInStrList(funcConfigNames, config->readEntry("funcB"));
funcB = (KMFilterRule::Function)(idx >= 0 ? idx : 0);
fieldA = config->readEntry("fieldA");
fieldB = config->readEntry("fieldB");
contA = config->readEntry("contentsA");
contB = config->readEntry("contentsB");
idx = findInStrList(opConfigNames, config->readEntry("operator"));
mOperator = (KMFilter::Operator)(idx >= 0 ? idx : 0);
mRuleA.init(fieldA, funcA, contA);
mRuleB.init(fieldB, funcB, contB);
num = config->readNumEntry("actions",0);
if (num > FILTER_MAX_ACTIONS)
{
num = FILTER_MAX_ACTIONS;
warning("Too many filter actions in filter rule `%s'", (const char*)mName);
}
for (i=0, j=0; i<num; i++, j++)
{
actName.sprintf("action-name-%d", i);
argsName.sprintf("action-args-%d", i);
actName = config->readEntry(actName);
mAction[j] = sActionDict->create(actName);
if (!mAction[j])
{
warning(i18n("Unknown filter action `%s'\n"
"in filter rule `%s'.\n"
"Ignoring it."),
(const char*)actName, (const char*)mName);
j--;
continue;
}
mAction[i]->argsFromString(config->readEntry(argsName));
}
while (i<=FILTER_MAX_ACTIONS)
mAction[i++] = NULL;
}
//-----------------------------------------------------------------------------
void KMFilter::writeConfig(KConfig* config)
{
QString key(64);
int i;
config->writeEntry("name", mName);
config->writeEntry("funcA", funcConfigNames[(int)mRuleA.function()]);
config->writeEntry("funcB", funcConfigNames[(int)mRuleB.function()]);
config->writeEntry("fieldA", mRuleA.field());
config->writeEntry("fieldB", mRuleB.field());
config->writeEntry("contentsA", mRuleA.contents());
config->writeEntry("contentsB", mRuleB.contents());
config->writeEntry("operator", opConfigNames[(int)mOperator]);
for (i=0; i<FILTER_MAX_ACTIONS && mAction[i]; i++)
{
key.sprintf("action-name-%d", i);
config->writeEntry(key, mAction[i]->name());
key.sprintf("action-args-%d", i);
config->writeEntry(key, mAction[i]->argsAsString());
}
config->writeEntry("actions", i);
}
//-----------------------------------------------------------------------------
const QString KMFilter::asString(void) const
{
QString result;
int i;
result = "Filter \"" + mName + "\":\n{\n ";
result += mRuleA.asString();
result += "\n ";
result += opConfigNames[(int)mOperator];
result += "\n ";
result += mRuleB.asString();
result += "\n";
for (i=0; i<=FILTER_MAX_ACTIONS && mAction[i]; i++)
{
result += " action: ";
result += mAction[i]->label();
result += " ";
result += mAction[i]->argsAsString();
result += "\n";
}
result += "}";
return result;
}
//=============================================================================
//
// Class KMFilterRule
//
//=============================================================================
KMFilterRule::KMFilterRule()
{
mField = NULL;
mFunction = FuncContains;
mContents = "";
}
//-----------------------------------------------------------------------------
void KMFilterRule::init(const QString aField, Function aFunction,
const QString aContents)
{
mField = aField.copy();
mFunction = aFunction;
mContents = aContents.copy();
}
//-----------------------------------------------------------------------------
bool KMFilterRule::matches(const KMMessage* msg)
{
QString msgContents;
assert(msg != NULL);
msgContents = msg->headerField(mField);
switch (mFunction)
{
case KMFilterRule::FuncEquals:
return (stricmp(mContents, msgContents) == 0);
case KMFilterRule::FuncNotEqual:
return (stricmp(mContents, msgContents) != 0);
case KMFilterRule::FuncContains:
return (msgContents.find(mContents, 0, FALSE) >= 0);
case KMFilterRule::FuncContainsNot:
return (msgContents.find(mContents, 0, FALSE) < 0);
case KMFilterRule::FuncRegExp:
return (msgContents.find(QRegExp(mContents, FALSE)) >= 0);
case KMFilterRule::FuncNotRegExp:
return (msgContents.find(QRegExp(mContents, FALSE)) < 0);
}
return FALSE;
}
//-----------------------------------------------------------------------------
const QString KMFilterRule::asString(void) const
{
QString result;
result = "\"" + mField + "\" ";
result += funcConfigNames[(int)mFunction];
result += " \"" + mContents + "\"";
debug("%s=%d",funcConfigNames[(int)mFunction], (int)mFunction);
return result;
}