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