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