|
|
|
// -*- mode: C++; c-file-style: "gnu" -*-
|
|
|
|
// kmfiltermgr.cpp
|
|
|
|
|
|
|
|
// my header
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "kmfiltermgr.h"
|
|
|
|
|
|
|
|
// other kmail headers
|
|
|
|
#include "filterlog.h"
|
|
|
|
using KMail::FilterLog;
|
|
|
|
#include "kmfilterdlg.h"
|
|
|
|
#include "kmfolderindex.h"
|
|
|
|
#include "filterimporterexporter.h"
|
|
|
|
using KMail::FilterImporterExporter;
|
|
|
|
#include "kmfoldermgr.h"
|
|
|
|
#include "kmmsgdict.h"
|
|
|
|
#include "messageproperty.h"
|
|
|
|
using KMail::MessageProperty;
|
|
|
|
|
|
|
|
// other KDE headers
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
|
|
|
|
// other TQt headers
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqvaluevector.h>
|
|
|
|
|
|
|
|
// other headers
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
KMFilterMgr::KMFilterMgr( bool popFilter )
|
|
|
|
: mEditDialog( 0 ),
|
|
|
|
bPopFilter( popFilter ),
|
|
|
|
mShowLater( false ),
|
|
|
|
mDirtyBufferedFolderTarget( true ),
|
|
|
|
mBufferedFolderTarget( true ),
|
|
|
|
mRefCount( 0 )
|
|
|
|
{
|
|
|
|
connect( kmkernel, TQT_SIGNAL( folderRemoved( KMFolder* ) ),
|
|
|
|
this, TQT_SLOT( slotFolderRemoved( KMFolder* ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
KMFilterMgr::~KMFilterMgr()
|
|
|
|
{
|
|
|
|
deref( true );
|
|
|
|
writeConfig( false );
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMFilterMgr::clear()
|
|
|
|
{
|
|
|
|
mDirtyBufferedFolderTarget = true;
|
|
|
|
for ( TQValueListIterator<KMFilter*> it = mFilters.begin() ;
|
|
|
|
it != mFilters.end() ; ++it ) {
|
|
|
|
delete *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::readConfig(void)
|
|
|
|
{
|
|
|
|
KConfig* config = KMKernel::config();
|
|
|
|
clear();
|
|
|
|
|
|
|
|
if (bPopFilter) {
|
|
|
|
KConfigGroupSaver saver(config, "General");
|
|
|
|
mShowLater = config->readNumEntry("popshowDLmsgs",0);
|
|
|
|
}
|
|
|
|
mFilters = FilterImporterExporter::readFiltersFromConfig( config, bPopFilter );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::writeConfig(bool withSync)
|
|
|
|
{
|
|
|
|
KConfig* config = KMKernel::config();
|
|
|
|
|
|
|
|
// Now, write out the new stuff:
|
|
|
|
FilterImporterExporter::writeFiltersToConfig( mFilters, config, bPopFilter );
|
|
|
|
KConfigGroupSaver saver(config, "General");
|
|
|
|
if (bPopFilter)
|
|
|
|
config->writeEntry("popshowDLmsgs", mShowLater);
|
|
|
|
|
|
|
|
if (withSync) config->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
int KMFilterMgr::processPop( KMMessage * msg ) const {
|
|
|
|
for ( TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
it != mFilters.constEnd() ; ++it )
|
|
|
|
if ( (*it)->pattern()->matches( msg ) )
|
|
|
|
return (*it)->action();
|
|
|
|
return NoAction;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KMFilterMgr::beginFiltering(KMMsgBase *msgBase) const
|
|
|
|
{
|
|
|
|
if (MessageProperty::filtering( msgBase ))
|
|
|
|
return false;
|
|
|
|
MessageProperty::setFiltering( msgBase, true );
|
|
|
|
MessageProperty::setFilterFolder( msgBase, 0 );
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
FilterLog::instance()->addSeparator();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KMFilterMgr::moveMessage(KMMessage *msg) const
|
|
|
|
{
|
|
|
|
if (MessageProperty::filterFolder(msg)->moveMsg( msg ) == 0) {
|
|
|
|
if ( kmkernel->folderIsTrash( MessageProperty::filterFolder( msg )))
|
|
|
|
KMFilterAction::sendMDN( msg, KMime::MDN::Deleted );
|
|
|
|
} else {
|
|
|
|
kdDebug(5006) << "KMfilterAction - couldn't move msg" << endl;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMFilterMgr::endFiltering(KMMsgBase *msgBase) const
|
|
|
|
{
|
|
|
|
KMFolder *tqparent = msgBase->tqparent();
|
|
|
|
if ( tqparent ) {
|
|
|
|
if ( tqparent == MessageProperty::filterFolder( msgBase ) ) {
|
|
|
|
tqparent->take( tqparent->tqfind( msgBase ) );
|
|
|
|
}
|
|
|
|
else if ( ! MessageProperty::filterFolder( msgBase ) ) {
|
|
|
|
int index = tqparent->tqfind( msgBase );
|
|
|
|
KMMessage *msg = tqparent->getMsg( index );
|
|
|
|
tqparent->take( index );
|
|
|
|
tqparent->addMsgKeepUID( msg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MessageProperty::setFiltering( msgBase, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
int KMFilterMgr::process( KMMessage * msg, const KMFilter * filter ) {
|
|
|
|
if ( !msg || !filter || !beginFiltering( msg ))
|
|
|
|
return 1;
|
|
|
|
bool stopIt = false;
|
|
|
|
int result = 1;
|
|
|
|
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
TQString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
|
|
|
|
logText.append( filter->pattern()->asString() );
|
|
|
|
FilterLog::instance()->add( logText, FilterLog::patternDesc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filter->pattern()->matches( msg )) {
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
|
|
|
|
FilterLog::patternResult );
|
|
|
|
}
|
|
|
|
if (filter->execActions( msg, stopIt ) == KMFilter::CriticalError)
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
KMFolder *folder = MessageProperty::filterFolder( msg );
|
|
|
|
|
|
|
|
endFiltering( msg );
|
|
|
|
if (folder) {
|
|
|
|
tempOpenFolder( folder );
|
|
|
|
result = folder->moveMsg( msg );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
endFiltering( msg );
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KMFilterMgr::process( TQ_UINT32 serNum, const KMFilter *filter )
|
|
|
|
{
|
|
|
|
bool stopIt = false;
|
|
|
|
int result = 1;
|
|
|
|
|
|
|
|
if ( !filter )
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if ( isMatching( serNum, filter ) ) {
|
|
|
|
KMFolder *folder = 0;
|
|
|
|
int idx = -1;
|
|
|
|
// get the message with the serNum
|
|
|
|
KMMsgDict::instance()->getLocation( serNum, &folder, &idx );
|
|
|
|
if ( !folder || ( idx == -1 ) || ( idx >= folder->count() ) ) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
KMFolderOpener openFolder(folder, "filtermgr");
|
|
|
|
KMMsgBase *msgBase = folder->getMsgBase( idx );
|
|
|
|
bool unGet = !msgBase->isMessage();
|
|
|
|
KMMessage *msg = folder->getMsg( idx );
|
|
|
|
// do the actual filtering stuff
|
|
|
|
if ( !msg || !beginFiltering( msg ) ) {
|
|
|
|
if ( unGet )
|
|
|
|
folder->unGetMsg( idx );
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if ( filter->execActions( msg, stopIt ) == KMFilter::CriticalError ) {
|
|
|
|
if ( unGet )
|
|
|
|
folder->unGetMsg( idx );
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
KMFolder *targetFolder = MessageProperty::filterFolder( msg );
|
|
|
|
|
|
|
|
endFiltering( msg );
|
|
|
|
if ( targetFolder ) {
|
|
|
|
tempOpenFolder( targetFolder );
|
|
|
|
msg->setTransferInProgress( false );
|
|
|
|
result = targetFolder->moveMsg( msg );
|
|
|
|
msg->setTransferInProgress( true );
|
|
|
|
}
|
|
|
|
if ( unGet )
|
|
|
|
folder->unGetMsg( idx );
|
|
|
|
} else {
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KMFilterMgr::process( KMMessage * msg, FilterSet set,
|
|
|
|
bool account, uint accountId ) {
|
|
|
|
if ( bPopFilter )
|
|
|
|
return processPop( msg );
|
|
|
|
|
|
|
|
if ( set == NoSet ) {
|
|
|
|
kdDebug(5006) << "KMFilterMgr: process() called with not filter set selected"
|
|
|
|
<< endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool stopIt = false;
|
|
|
|
bool atLeastOneRuleMatched = false;
|
|
|
|
|
|
|
|
if (!beginFiltering( msg ))
|
|
|
|
return 1;
|
|
|
|
for ( TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
!stopIt && it != mFilters.constEnd() ; ++it ) {
|
|
|
|
|
|
|
|
if ( ( ( (set&Inbound) && (*it)->applyOnInbound() ) &&
|
|
|
|
( !account ||
|
|
|
|
( account && (*it)->applyOnAccount( accountId ) ) ) ) ||
|
|
|
|
( (set&Outbound) && (*it)->applyOnOutbound() ) ||
|
|
|
|
( (set&Explicit) && (*it)->applyOnExplicit() ) ) {
|
|
|
|
// filter is applicable
|
|
|
|
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
TQString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
|
|
|
|
logText.append( (*it)->pattern()->asString() );
|
|
|
|
FilterLog::instance()->add( logText, FilterLog::patternDesc );
|
|
|
|
}
|
|
|
|
if ( (*it)->pattern()->matches( msg ) ) {
|
|
|
|
// filter matches
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
|
|
|
|
FilterLog::patternResult );
|
|
|
|
}
|
|
|
|
atLeastOneRuleMatched = true;
|
|
|
|
// execute actions:
|
|
|
|
if ( (*it)->execActions(msg, stopIt) == KMFilter::CriticalError )
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KMFolder *folder = MessageProperty::filterFolder( msg );
|
|
|
|
/* endFilter does a take() and addButKeepUID() to ensure the changed
|
|
|
|
* message is on disk. This is unnessecary if nothing matched, so just
|
|
|
|
* reset state and don't update the listview at all. */
|
|
|
|
if ( atLeastOneRuleMatched )
|
|
|
|
endFiltering( msg );
|
|
|
|
else
|
|
|
|
MessageProperty::setFiltering( msg, false );
|
|
|
|
if (folder) {
|
|
|
|
tempOpenFolder( folder );
|
|
|
|
folder->moveMsg(msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KMFilterMgr::isMatching( TQ_UINT32 serNum, const KMFilter *filter )
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
TQString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
|
|
|
|
logText.append( filter->pattern()->asString() );
|
|
|
|
FilterLog::instance()->add( logText, FilterLog::patternDesc );
|
|
|
|
}
|
|
|
|
if ( filter->pattern()->matches( serNum ) ) {
|
|
|
|
if ( FilterLog::instance()->isLogging() ) {
|
|
|
|
FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
|
|
|
|
FilterLog::patternResult );
|
|
|
|
}
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KMFilterMgr::atLeastOneFilterAppliesTo( unsigned int accountID ) const
|
|
|
|
{
|
|
|
|
TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
for ( ; it != mFilters.constEnd() ; ++it ) {
|
|
|
|
if ( (*it)->applyOnAccount( accountID ) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KMFilterMgr::atLeastOneIncomingFilterAppliesTo( unsigned int accountID ) const
|
|
|
|
{
|
|
|
|
TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
for ( ; it != mFilters.constEnd() ; ++it ) {
|
|
|
|
if ( (*it)->applyOnInbound() && (*it)->applyOnAccount( accountID ) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KMFilterMgr::atLeastOneOnlineImapFolderTarget()
|
|
|
|
{
|
|
|
|
if (!mDirtyBufferedFolderTarget)
|
|
|
|
return mBufferedFolderTarget;
|
|
|
|
|
|
|
|
mDirtyBufferedFolderTarget = false;
|
|
|
|
|
|
|
|
TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
for ( ; it != mFilters.constEnd() ; ++it ) {
|
|
|
|
KMFilter *filter = *it;
|
|
|
|
TQPtrListIterator<KMFilterAction> jt( *filter->actions() );
|
|
|
|
for ( jt.toFirst() ; jt.current() ; ++jt ) {
|
|
|
|
KMFilterActionWithFolder *f = dynamic_cast<KMFilterActionWithFolder*>(*jt);
|
|
|
|
if (!f)
|
|
|
|
continue;
|
|
|
|
TQString name = f->argsAsString();
|
|
|
|
KMFolder *folder = kmkernel->imapFolderMgr()->findIdString( name );
|
|
|
|
if (folder) {
|
|
|
|
mBufferedFolderTarget = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mBufferedFolderTarget = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::ref(void)
|
|
|
|
{
|
|
|
|
mRefCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::deref(bool force)
|
|
|
|
{
|
|
|
|
if (!force)
|
|
|
|
mRefCount--;
|
|
|
|
if (mRefCount < 0)
|
|
|
|
mRefCount = 0;
|
|
|
|
if (mRefCount && !force)
|
|
|
|
return;
|
|
|
|
TQValueVector< KMFolder *>::const_iterator it;
|
|
|
|
for ( it = mOpenFolders.constBegin(); it != mOpenFolders.constEnd(); ++it )
|
|
|
|
(*it)->close("filtermgr");
|
|
|
|
mOpenFolders.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int KMFilterMgr::tempOpenFolder(KMFolder* aFolder)
|
|
|
|
{
|
|
|
|
assert( aFolder );
|
|
|
|
|
|
|
|
int rc = aFolder->open("filermgr");
|
|
|
|
if (rc) return rc;
|
|
|
|
|
|
|
|
mOpenFolders.append( aFolder );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::openDialog( TQWidget *, bool checkForEmptyFilterList )
|
|
|
|
{
|
|
|
|
if( !mEditDialog )
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We can't use the tqparent as long as the dialog is modeless
|
|
|
|
// and there is one shared dialog for all top level windows.
|
|
|
|
//
|
|
|
|
mEditDialog = new KMFilterDlg( 0, "filterdialog", bPopFilter,
|
|
|
|
checkForEmptyFilterList );
|
|
|
|
}
|
|
|
|
mEditDialog->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::createFilter( const TQCString & field, const TQString & value )
|
|
|
|
{
|
|
|
|
openDialog( 0, false );
|
|
|
|
mEditDialog->createFilter( field, value );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const TQString KMFilterMgr::createUniqueName( const TQString & name )
|
|
|
|
{
|
|
|
|
TQString uniqueName = name;
|
|
|
|
int counter = 0;
|
|
|
|
bool found = true;
|
|
|
|
|
|
|
|
while ( found ) {
|
|
|
|
found = false;
|
|
|
|
for ( TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
it != mFilters.constEnd(); ++it ) {
|
|
|
|
if ( !( (*it)->name().compare( uniqueName ) ) ) {
|
|
|
|
found = true;
|
|
|
|
++counter;
|
|
|
|
uniqueName = name;
|
|
|
|
uniqueName += TQString( " (" ) + TQString::number( counter )
|
|
|
|
+ TQString( ")" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return uniqueName;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::appendFilters( const TQValueList<KMFilter*> &filters,
|
|
|
|
bool replaceIfNameExists )
|
|
|
|
{
|
|
|
|
mDirtyBufferedFolderTarget = true;
|
|
|
|
beginUpdate();
|
|
|
|
if ( replaceIfNameExists ) {
|
|
|
|
TQValueListConstIterator<KMFilter*> it1 = filters.constBegin();
|
|
|
|
for ( ; it1 != filters.constEnd() ; ++it1 ) {
|
|
|
|
TQValueListConstIterator<KMFilter*> it2 = mFilters.constBegin();
|
|
|
|
for ( ; it2 != mFilters.constEnd() ; ++it2 ) {
|
|
|
|
if ( (*it1)->name() == (*it2)->name() ) {
|
|
|
|
mFilters.remove( (*it2) );
|
|
|
|
it2 = mFilters.constBegin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mFilters += filters;
|
|
|
|
writeConfig( true );
|
|
|
|
endUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMFilterMgr::setFilters( const TQValueList<KMFilter*> &filters )
|
|
|
|
{
|
|
|
|
beginUpdate();
|
|
|
|
clear();
|
|
|
|
mFilters = filters;
|
|
|
|
writeConfig( true );
|
|
|
|
endUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMFilterMgr::slotFolderRemoved( KMFolder * aFolder )
|
|
|
|
{
|
|
|
|
folderRemoved( aFolder, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool KMFilterMgr::folderRemoved(KMFolder* aFolder, KMFolder* aNewFolder)
|
|
|
|
{
|
|
|
|
mDirtyBufferedFolderTarget = true;
|
|
|
|
bool rem = false;
|
|
|
|
TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
for ( ; it != mFilters.constEnd() ; ++it )
|
|
|
|
if ( (*it)->folderRemoved(aFolder, aNewFolder) )
|
|
|
|
rem = true;
|
|
|
|
|
|
|
|
return rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void KMFilterMgr::dump(void) const
|
|
|
|
{
|
|
|
|
|
|
|
|
TQValueListConstIterator<KMFilter*> it = mFilters.constBegin();
|
|
|
|
for ( ; it != mFilters.constEnd() ; ++it ) {
|
|
|
|
kdDebug(5006) << (*it)->asString() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMFilterMgr::endUpdate(void)
|
|
|
|
{
|
|
|
|
emit filterListUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kmfiltermgr.moc"
|