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