00001
00002
00003
00004
00005 #ifdef HAVE_CONFIG_H
00006 #include <config.h>
00007 #endif
00008
00009 #include "kmfiltermgr.h"
00010
00011
00012 #include "filterlog.h"
00013 using KMail::FilterLog;
00014 #include "kmfilterdlg.h"
00015 #include "kmfolderindex.h"
00016 #include "kmfoldermgr.h"
00017 #include "kmmsgdict.h"
00018 #include "messageproperty.h"
00019 using KMail::MessageProperty;
00020
00021
00022 #include <kdebug.h>
00023 #include <klocale.h>
00024 #include <kconfig.h>
00025
00026
00027 #include <qregexp.h>
00028 #include <qvaluevector.h>
00029
00030
00031 #include <assert.h>
00032
00033
00034
00035 KMFilterMgr::KMFilterMgr( bool popFilter )
00036 : mEditDialog( 0 ),
00037 bPopFilter( popFilter ),
00038 mShowLater( false ),
00039 mDirtyBufferedFolderTarget( true ),
00040 mBufferedFolderTarget( true ),
00041 mRefCount( 0 )
00042 {
00043 if (bPopFilter)
00044 kdDebug(5006) << "pPopFilter set" << endl;
00045 connect( kmkernel, SIGNAL( folderRemoved( KMFolder* ) ),
00046 this, SLOT( slotFolderRemoved( KMFolder* ) ) );
00047 }
00048
00049
00050
00051 KMFilterMgr::~KMFilterMgr()
00052 {
00053 deref( true );
00054 writeConfig( false );
00055 clear();
00056 }
00057
00058 void KMFilterMgr::clear()
00059 {
00060 mDirtyBufferedFolderTarget = true;
00061 for ( QValueListIterator<KMFilter*> it = mFilters.begin() ;
00062 it != mFilters.end() ; ++it ) {
00063 delete *it;
00064 }
00065 }
00066
00067
00068 void KMFilterMgr::readConfig(void)
00069 {
00070 KConfig* config = KMKernel::config();
00071 int numFilters;
00072 QString grpName;
00073
00074 clear();
00075
00076 KConfigGroupSaver saver(config, "General");
00077
00078 if (bPopFilter) {
00079 numFilters = config->readNumEntry("popfilters",0);
00080 mShowLater = config->readNumEntry("popshowDLmsgs",0);
00081 } else {
00082 numFilters = config->readNumEntry("filters",0);
00083 }
00084
00085 for ( int i=0 ; i < numFilters ; ++i ) {
00086 grpName.sprintf("%s #%d", (bPopFilter ? "PopFilter" : "Filter") , i);
00087 KConfigGroupSaver saver(config, grpName);
00088 KMFilter * filter = new KMFilter(config, bPopFilter);
00089 filter->purify();
00090 if ( filter->isEmpty() ) {
00091 #ifndef NDEBUG
00092 kdDebug(5006) << "KMFilter::readConfig: filter\n" << filter->asString()
00093 << "is empty!" << endl;
00094 #endif
00095 delete filter;
00096 } else
00097 mFilters.append(filter);
00098 }
00099 }
00100
00101
00102
00103 void KMFilterMgr::writeConfig(bool withSync)
00104 {
00105 KConfig* config = KMKernel::config();
00106
00107
00108 QStringList filterGroups =
00109 config->groupList().grep( QRegExp( bPopFilter ? "PopFilter #\\d+" : "Filter #\\d+" ) );
00110 for ( QStringList::Iterator it = filterGroups.begin() ;
00111 it != filterGroups.end() ; ++it )
00112 config->deleteGroup( *it );
00113
00114
00115 int i = 0;
00116 QString grpName;
00117 for ( QValueListConstIterator<KMFilter*> it = mFilters.constBegin() ;
00118 it != mFilters.constEnd() ; ++it ) {
00119 if ( !(*it)->isEmpty() ) {
00120 if ( bPopFilter )
00121 grpName.sprintf("PopFilter #%d", i);
00122 else
00123 grpName.sprintf("Filter #%d", i);
00124 KConfigGroupSaver saver(config, grpName);
00125 (*it)->writeConfig(config);
00126 ++i;
00127 }
00128 }
00129
00130 KConfigGroupSaver saver(config, "General");
00131 if (bPopFilter) {
00132 config->writeEntry("popfilters", i);
00133 config->writeEntry("popshowDLmsgs", mShowLater);
00134 } else
00135 config->writeEntry("filters", i);
00136
00137 if (withSync) config->sync();
00138 }
00139
00140
00141 int KMFilterMgr::processPop( KMMessage * msg ) const {
00142 for ( QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00143 it != mFilters.constEnd() ; ++it )
00144 if ( (*it)->pattern()->matches( msg ) )
00145 return (*it)->action();
00146 return NoAction;
00147 }
00148
00149 bool KMFilterMgr::beginFiltering(KMMsgBase *msgBase) const
00150 {
00151 if (MessageProperty::filtering( msgBase ))
00152 return false;
00153 MessageProperty::setFiltering( msgBase, true );
00154 MessageProperty::setFilterFolder( msgBase, 0 );
00155 if ( FilterLog::instance()->isLogging() ) {
00156 FilterLog::instance()->addSeparator();
00157 }
00158 return true;
00159 }
00160
00161 int KMFilterMgr::moveMessage(KMMessage *msg) const
00162 {
00163 if (MessageProperty::filterFolder(msg)->moveMsg( msg ) == 0) {
00164 if ( kmkernel->folderIsTrash( MessageProperty::filterFolder( msg )))
00165 KMFilterAction::sendMDN( msg, KMime::MDN::Deleted );
00166 } else {
00167 kdDebug(5006) << "KMfilterAction - couldn't move msg" << endl;
00168 return 2;
00169 }
00170 return 0;
00171 }
00172
00173 void KMFilterMgr::endFiltering(KMMsgBase *msgBase) const
00174 {
00175 KMFolder *parent = msgBase->parent();
00176 if ( parent ) {
00177 if ( parent == MessageProperty::filterFolder( msgBase ) ) {
00178 parent->take( parent->find( msgBase ) );
00179 }
00180 else if ( ! MessageProperty::filterFolder( msgBase ) ) {
00181 int index = parent->find( msgBase );
00182 KMMessage *msg = parent->getMsg( index );
00183 parent->take( index );
00184 parent->addMsgKeepUID( msg );
00185 }
00186 }
00187 MessageProperty::setFiltering( msgBase, false );
00188 }
00189
00190 int KMFilterMgr::process( KMMessage * msg, const KMFilter * filter ) {
00191 if ( !msg || !filter || !beginFiltering( msg ))
00192 return 1;
00193 bool stopIt = false;
00194 int result = 1;
00195
00196 if ( FilterLog::instance()->isLogging() ) {
00197 QString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
00198 logText.append( filter->pattern()->asString() );
00199 FilterLog::instance()->add( logText, FilterLog::patternDesc );
00200 }
00201
00202 if (filter->pattern()->matches( msg )) {
00203 if ( FilterLog::instance()->isLogging() ) {
00204 FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
00205 FilterLog::patternResult );
00206 }
00207 if (filter->execActions( msg, stopIt ) == KMFilter::CriticalError)
00208 return 2;
00209
00210 KMFolder *folder = MessageProperty::filterFolder( msg );
00211
00212 endFiltering( msg );
00213 if (folder) {
00214 tempOpenFolder( folder );
00215 result = folder->moveMsg( msg );
00216 }
00217 } else {
00218 endFiltering( msg );
00219 result = 1;
00220 }
00221 return result;
00222 }
00223
00224 int KMFilterMgr::process( Q_UINT32 serNum, const KMFilter *filter )
00225 {
00226 bool stopIt = false;
00227 int result = 1;
00228
00229 if ( !filter )
00230 return 1;
00231
00232 if ( isMatching( serNum, filter ) ) {
00233 KMFolder *folder = 0;
00234 int idx = -1;
00235
00236 KMMsgDict::instance()->getLocation( serNum, &folder, &idx );
00237 if ( !folder || ( idx == -1 ) || ( idx >= folder->count() ) ) {
00238 return 1;
00239 }
00240 KMFolderOpener openFolder(folder, "filtermgr");
00241 KMMsgBase *msgBase = folder->getMsgBase( idx );
00242 bool unGet = !msgBase->isMessage();
00243 KMMessage *msg = folder->getMsg( idx );
00244
00245 if ( !msg || !beginFiltering( msg ) ) {
00246 if ( unGet )
00247 folder->unGetMsg( idx );
00248 return 1;
00249 }
00250 if ( filter->execActions( msg, stopIt ) == KMFilter::CriticalError ) {
00251 if ( unGet )
00252 folder->unGetMsg( idx );
00253 return 2;
00254 }
00255
00256 KMFolder *targetFolder = MessageProperty::filterFolder( msg );
00257
00258 endFiltering( msg );
00259 if ( targetFolder ) {
00260 tempOpenFolder( targetFolder );
00261 msg->setTransferInProgress( false );
00262 result = targetFolder->moveMsg( msg );
00263 msg->setTransferInProgress( true );
00264 }
00265 if ( unGet )
00266 folder->unGetMsg( idx );
00267 } else {
00268 result = 1;
00269 }
00270 return result;
00271 }
00272
00273 int KMFilterMgr::process( KMMessage * msg, FilterSet set,
00274 bool account, uint accountId ) {
00275 if ( bPopFilter )
00276 return processPop( msg );
00277
00278 if ( set == NoSet ) {
00279 kdDebug(5006) << "KMFilterMgr: process() called with not filter set selected"
00280 << endl;
00281 return 1;
00282 }
00283
00284 bool stopIt = false;
00285 bool atLeastOneRuleMatched = false;
00286
00287 if (!beginFiltering( msg ))
00288 return 1;
00289 for ( QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00290 !stopIt && it != mFilters.constEnd() ; ++it ) {
00291
00292 if ( ( ( (set&Inbound) && (*it)->applyOnInbound() ) &&
00293 ( !account ||
00294 ( account && (*it)->applyOnAccount( accountId ) ) ) ) ||
00295 ( (set&Outbound) && (*it)->applyOnOutbound() ) ||
00296 ( (set&Explicit) && (*it)->applyOnExplicit() ) ) {
00297
00298
00299 if ( FilterLog::instance()->isLogging() ) {
00300 QString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
00301 logText.append( (*it)->pattern()->asString() );
00302 FilterLog::instance()->add( logText, FilterLog::patternDesc );
00303 }
00304 if ( (*it)->pattern()->matches( msg ) ) {
00305
00306 if ( FilterLog::instance()->isLogging() ) {
00307 FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
00308 FilterLog::patternResult );
00309 }
00310 atLeastOneRuleMatched = true;
00311
00312 if ( (*it)->execActions(msg, stopIt) == KMFilter::CriticalError )
00313 return 2;
00314 }
00315 }
00316 }
00317
00318 KMFolder *folder = MessageProperty::filterFolder( msg );
00319
00320
00321
00322 if ( atLeastOneRuleMatched )
00323 endFiltering( msg );
00324 else
00325 MessageProperty::setFiltering( msg, false );
00326 if (folder) {
00327 tempOpenFolder( folder );
00328 folder->moveMsg(msg);
00329 return 0;
00330 }
00331 return 1;
00332 }
00333
00334 bool KMFilterMgr::isMatching( Q_UINT32 serNum, const KMFilter *filter )
00335 {
00336 bool result = false;
00337 if ( FilterLog::instance()->isLogging() ) {
00338 QString logText( i18n( "<b>Evaluating filter rules:</b> " ) );
00339 logText.append( filter->pattern()->asString() );
00340 FilterLog::instance()->add( logText, FilterLog::patternDesc );
00341 }
00342 if ( filter->pattern()->matches( serNum ) ) {
00343 if ( FilterLog::instance()->isLogging() ) {
00344 FilterLog::instance()->add( i18n( "<b>Filter rules have matched.</b>" ),
00345 FilterLog::patternResult );
00346 }
00347 result = true;
00348 }
00349 return result;
00350 }
00351
00352 bool KMFilterMgr::atLeastOneFilterAppliesTo( unsigned int accountID ) const
00353 {
00354 QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00355 for ( ; it != mFilters.constEnd() ; ++it ) {
00356 if ( (*it)->applyOnAccount( accountID ) ) {
00357 return true;
00358 }
00359 }
00360 return false;
00361 }
00362
00363 bool KMFilterMgr::atLeastOneIncomingFilterAppliesTo( unsigned int accountID ) const
00364 {
00365 QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00366 for ( ; it != mFilters.constEnd() ; ++it ) {
00367 if ( (*it)->applyOnInbound() && (*it)->applyOnAccount( accountID ) ) {
00368 return true;
00369 }
00370 }
00371 return false;
00372 }
00373
00374 bool KMFilterMgr::atLeastOneOnlineImapFolderTarget()
00375 {
00376 if (!mDirtyBufferedFolderTarget)
00377 return mBufferedFolderTarget;
00378
00379 mDirtyBufferedFolderTarget = false;
00380
00381 QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00382 for ( ; it != mFilters.constEnd() ; ++it ) {
00383 KMFilter *filter = *it;
00384 QPtrListIterator<KMFilterAction> jt( *filter->actions() );
00385 for ( jt.toFirst() ; jt.current() ; ++jt ) {
00386 KMFilterActionWithFolder *f = dynamic_cast<KMFilterActionWithFolder*>(*jt);
00387 if (!f)
00388 continue;
00389 QString name = f->argsAsString();
00390 KMFolder *folder = kmkernel->imapFolderMgr()->findIdString( name );
00391 if (folder) {
00392 mBufferedFolderTarget = true;
00393 return true;
00394 }
00395 }
00396 }
00397 mBufferedFolderTarget = false;
00398 return false;
00399 }
00400
00401
00402 void KMFilterMgr::ref(void)
00403 {
00404 mRefCount++;
00405 }
00406
00407
00408 void KMFilterMgr::deref(bool force)
00409 {
00410 if (!force)
00411 mRefCount--;
00412 if (mRefCount < 0)
00413 mRefCount = 0;
00414 if (mRefCount && !force)
00415 return;
00416 QValueVector< KMFolder *>::const_iterator it;
00417 for ( it = mOpenFolders.constBegin(); it != mOpenFolders.constEnd(); ++it )
00418 (*it)->close("filtermgr");
00419 mOpenFolders.clear();
00420 }
00421
00422
00423
00424 int KMFilterMgr::tempOpenFolder(KMFolder* aFolder)
00425 {
00426 assert( aFolder );
00427
00428 int rc = aFolder->open("filermgr");
00429 if (rc) return rc;
00430
00431 mOpenFolders.append( aFolder );
00432 return 0;
00433 }
00434
00435
00436
00437 void KMFilterMgr::openDialog( QWidget *, bool checkForEmptyFilterList )
00438 {
00439 if( !mEditDialog )
00440 {
00441
00442
00443
00444
00445 mEditDialog = new KMFilterDlg( 0, "filterdialog", bPopFilter,
00446 checkForEmptyFilterList );
00447 }
00448 mEditDialog->show();
00449 }
00450
00451
00452
00453 void KMFilterMgr::createFilter( const QCString & field, const QString & value )
00454 {
00455 openDialog( 0, false );
00456 mEditDialog->createFilter( field, value );
00457 }
00458
00459
00460
00461 const QString KMFilterMgr::createUniqueName( const QString & name )
00462 {
00463 QString uniqueName = name;
00464 int counter = 0;
00465 bool found = true;
00466
00467 while ( found ) {
00468 found = false;
00469 for ( QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00470 it != mFilters.constEnd(); ++it ) {
00471 if ( !( (*it)->name().compare( uniqueName ) ) ) {
00472 found = true;
00473 ++counter;
00474 uniqueName = name;
00475 uniqueName += QString( " (" ) + QString::number( counter )
00476 + QString( ")" );
00477 break;
00478 }
00479 }
00480 }
00481 return uniqueName;
00482 }
00483
00484
00485
00486 void KMFilterMgr::appendFilters( const QValueList<KMFilter*> &filters,
00487 bool replaceIfNameExists )
00488 {
00489 mDirtyBufferedFolderTarget = true;
00490 beginUpdate();
00491 if ( replaceIfNameExists ) {
00492 QValueListConstIterator<KMFilter*> it1 = filters.constBegin();
00493 for ( ; it1 != filters.constEnd() ; ++it1 ) {
00494 QValueListConstIterator<KMFilter*> it2 = mFilters.constBegin();
00495 for ( ; it2 != mFilters.constEnd() ; ++it2 ) {
00496 if ( (*it1)->name() == (*it2)->name() ) {
00497 mFilters.remove( (*it2) );
00498 it2 = mFilters.constBegin();
00499 }
00500 }
00501 }
00502 }
00503 mFilters += filters;
00504 writeConfig( true );
00505 endUpdate();
00506 }
00507
00508 void KMFilterMgr::setFilters( const QValueList<KMFilter*> &filters )
00509 {
00510 clear();
00511 mFilters = filters;
00512 }
00513
00514 void KMFilterMgr::slotFolderRemoved( KMFolder * aFolder )
00515 {
00516 folderRemoved( aFolder, 0 );
00517 }
00518
00519
00520 bool KMFilterMgr::folderRemoved(KMFolder* aFolder, KMFolder* aNewFolder)
00521 {
00522 mDirtyBufferedFolderTarget = true;
00523 bool rem = false;
00524 QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00525 for ( ; it != mFilters.constEnd() ; ++it )
00526 if ( (*it)->folderRemoved(aFolder, aNewFolder) )
00527 rem = true;
00528
00529 return rem;
00530 }
00531
00532
00533
00534 #ifndef NDEBUG
00535 void KMFilterMgr::dump(void) const
00536 {
00537
00538 QValueListConstIterator<KMFilter*> it = mFilters.constBegin();
00539 for ( ; it != mFilters.constEnd() ; ++it ) {
00540 kdDebug(5006) << (*it)->asString() << endl;
00541 }
00542 }
00543 #endif
00544
00545
00546 void KMFilterMgr::endUpdate(void)
00547 {
00548 emit filterListUpdated();
00549 }
00550
00551 #include "kmfiltermgr.moc"