00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024 #include "kmfilter.h"
00025 #include "kmkernel.h"
00026 #include "accountmanager.h"
00027 using KMail::AccountManager;
00028 #include "kmacctimap.h"
00029 #include "kmfilteraction.h"
00030 #include "kmglobal.h"
00031 #include "filterlog.h"
00032 using KMail::FilterLog;
00033
00034 #include <klocale.h>
00035 #include <kmessagebox.h>
00036 #include <kdebug.h>
00037 #include <kconfig.h>
00038
00039 #include <assert.h>
00040
00041
00042 KMFilter::KMFilter( KConfig* aConfig, bool popFilter )
00043 : bPopFilter(popFilter)
00044 {
00045 if (!bPopFilter)
00046 mActions.setAutoDelete( true );
00047
00048 if ( aConfig )
00049 readConfig( aConfig );
00050 else if ( bPopFilter )
00051 mAction = Down;
00052 else {
00053 bApplyOnInbound = true;
00054 bApplyOnOutbound = false;
00055 bApplyOnExplicit = true;
00056 bStopProcessingHere = true;
00057 bConfigureShortcut = false;
00058 bConfigureToolbar = false;
00059 bAutoNaming = true;
00060 mApplicability = All;
00061 }
00062 }
00063
00064
00065 KMFilter::KMFilter( const KMFilter & aFilter )
00066 {
00067 bPopFilter = aFilter.isPopFilter();
00068
00069 if ( !bPopFilter )
00070 mActions.setAutoDelete( true );
00071
00072 mPattern = aFilter.mPattern;
00073
00074 if ( bPopFilter ){
00075 mAction = aFilter.mAction;
00076 } else {
00077 bApplyOnInbound = aFilter.applyOnInbound();
00078 bApplyOnOutbound = aFilter.applyOnOutbound();
00079 bApplyOnExplicit = aFilter.applyOnExplicit();
00080 bStopProcessingHere = aFilter.stopProcessingHere();
00081 bConfigureShortcut = aFilter.configureShortcut();
00082 bConfigureToolbar = aFilter.configureToolbar();
00083 mApplicability = aFilter.applicability();
00084 mIcon = aFilter.icon();
00085 mShortcut = aFilter.shortcut();
00086
00087 QPtrListIterator<KMFilterAction> it( aFilter.mActions );
00088 for ( it.toFirst() ; it.current() ; ++it ) {
00089 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ (*it)->name() ];
00090 if ( desc ) {
00091 KMFilterAction *f = desc->create();
00092 if ( f ) {
00093 f->argsFromString( (*it)->argsAsString() );
00094 mActions.append( f );
00095 }
00096 }
00097 }
00098
00099 mAccounts.clear();
00100 QValueListConstIterator<int> it2;
00101 for ( it2 = aFilter.mAccounts.begin() ; it2 != aFilter.mAccounts.end() ; ++it2 )
00102 mAccounts.append( *it2 );
00103 }
00104 }
00105
00106
00107 KMFilter::ReturnCode KMFilter::execActions( KMMessage* msg, bool& stopIt ) const
00108 {
00109 ReturnCode status = NoResult;
00110
00111 QPtrListIterator<KMFilterAction> it( mActions );
00112 for ( it.toFirst() ; it.current() ; ++it ) {
00113
00114 if ( FilterLog::instance()->isLogging() ) {
00115 QString logText( i18n( "<b>Applying filter action:</b> %1" )
00116 .arg( (*it)->displayString() ) );
00117 FilterLog::instance()->add( logText, FilterLog::appliedAction );
00118 }
00119
00120 KMFilterAction::ReturnCode result = (*it)->process( msg );
00121
00122 switch ( result ) {
00123 case KMFilterAction::CriticalError:
00124 if ( FilterLog::instance()->isLogging() ) {
00125 QString logText = QString( "<font color=#FF0000>%1</font>" )
00126 .arg( i18n( "A critical error occurred. Processing stops here." ) );
00127 FilterLog::instance()->add( logText, FilterLog::appliedAction );
00128 }
00129
00130 return CriticalError;
00131 case KMFilterAction::ErrorButGoOn:
00132 if ( FilterLog::instance()->isLogging() ) {
00133 QString logText = QString( "<font color=#FF0000>%1</font>" )
00134 .arg( i18n( "A problem was found while applying this action." ) );
00135 FilterLog::instance()->add( logText, FilterLog::appliedAction );
00136 }
00137 default:
00138 break;
00139 }
00140 }
00141
00142 if ( status == NoResult )
00143 status = GoOn;
00144
00145 stopIt = stopProcessingHere();
00146
00147 return status;
00148 }
00149
00150 bool KMFilter::requiresBody( KMMsgBase* msg )
00151 {
00152 if (pattern() && pattern()->requiresBody())
00153 return true;
00154 QPtrListIterator<KMFilterAction> it( *actions() );
00155 for ( it.toFirst() ; it.current() ; ++it )
00156 if ((*it)->requiresBody( msg ))
00157 return true;
00158 return false;
00159 }
00160
00162
00163 void KMFilter::setAction(const KMPopFilterAction aAction)
00164 {
00165 mAction = aAction;
00166 }
00167
00168
00169 KMPopFilterAction KMFilter::action()
00170 {
00171 return mAction;
00172 }
00173
00174
00175 bool KMFilter::folderRemoved( KMFolder* aFolder, KMFolder* aNewFolder )
00176 {
00177 bool rem = false;
00178
00179 QPtrListIterator<KMFilterAction> it( mActions );
00180 for ( it.toFirst() ; it.current() ; ++it )
00181 if ( (*it)->folderRemoved( aFolder, aNewFolder ) )
00182 rem = true;
00183
00184 return rem;
00185 }
00186
00187 void KMFilter::setApplyOnAccount( uint id, bool aApply )
00188 {
00189 if (aApply && !mAccounts.contains( id )) {
00190 mAccounts.append( id );
00191 } else if (!aApply && mAccounts.contains( id )) {
00192 mAccounts.remove( id );
00193 }
00194 }
00195
00196 bool KMFilter::applyOnAccount( uint id ) const
00197 {
00198 if ( applicability() == All )
00199 return true;
00200 if ( applicability() == ButImap ) {
00201 KMAccount *account = kmkernel->acctMgr()->find( id );
00202 bool result = account && !dynamic_cast<KMAcctImap*>(account);
00203 return result;
00204 }
00205 if ( applicability() == Checked )
00206 return mAccounts.contains( id );
00207
00208 return false;
00209 }
00210
00211
00212
00213 void KMFilter::readConfig(KConfig* config)
00214 {
00215
00216
00217 mPattern.readConfig(config);
00218
00219 if (bPopFilter) {
00220
00221 QString action = config->readEntry( "action" );
00222 if ( action == "down" )
00223 mAction = Down;
00224 else if ( action == "later" )
00225 mAction = Later;
00226 else if ( action == "delete" )
00227 mAction = Delete;
00228 else
00229 mAction = NoAction;
00230 }
00231 else {
00232 QStringList sets = config->readListEntry("apply-on");
00233 if ( sets.isEmpty() && !config->hasKey("apply-on") ) {
00234 bApplyOnOutbound = false;
00235 bApplyOnInbound = true;
00236 bApplyOnExplicit = true;
00237 mApplicability = ButImap;
00238 } else {
00239 bApplyOnInbound = bool(sets.contains("check-mail"));
00240 bApplyOnOutbound = bool(sets.contains("send-mail"));
00241 bApplyOnExplicit = bool(sets.contains("manual-filtering"));
00242 mApplicability = (AccountType)config->readNumEntry( "Applicability", ButImap );
00243 }
00244
00245 bStopProcessingHere = config->readBoolEntry("StopProcessingHere", true);
00246 bConfigureShortcut = config->readBoolEntry("ConfigureShortcut", false);
00247 QString shortcut( config->readEntry( "Shortcut" ) );
00248 if ( !shortcut.isEmpty() ) {
00249 KShortcut sc( shortcut );
00250 setShortcut( sc );
00251 }
00252 bConfigureToolbar = config->readBoolEntry("ConfigureToolbar", false);
00253 bConfigureToolbar = bConfigureToolbar && bConfigureShortcut;
00254 mIcon = config->readEntry( "Icon", "gear" );
00255 bAutoNaming = config->readBoolEntry("AutomaticName", false);
00256
00257 int i, numActions;
00258 QString actName, argsName;
00259
00260 mActions.clear();
00261
00262 numActions = config->readNumEntry("actions",0);
00263 if (numActions > FILTER_MAX_ACTIONS) {
00264 numActions = FILTER_MAX_ACTIONS ;
00265 KMessageBox::information( 0, i18n("<qt>Too many filter actions in filter rule <b>%1</b>.</qt>").arg( mPattern.name() ) );
00266 }
00267
00268 for ( i=0 ; i < numActions ; i++ ) {
00269 actName.sprintf("action-name-%d", i);
00270 argsName.sprintf("action-args-%d", i);
00271
00272 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ config->readEntry( actName ) ];
00273 if ( desc ) {
00274
00275 KMFilterAction *fa = desc->create();
00276 if ( fa ) {
00277
00278 fa->argsFromString( config->readEntry( argsName ) );
00279
00280 if ( !fa->isEmpty() )
00281
00282 mActions.append( fa );
00283 else
00284
00285 delete fa;
00286 }
00287 } else
00288 KMessageBox::information( 0 ,
00289 i18n("<qt>Unknown filter action <b>%1</b><br>in filter rule <b>%2</b>.<br>Ignoring it.</qt>")
00290 .arg( config->readEntry( actName ) ).arg( mPattern.name() ) );
00291 }
00292
00293 mAccounts = config->readIntListEntry( "accounts-set" );
00294 }
00295 }
00296
00297
00298 void KMFilter::writeConfig(KConfig* config) const
00299 {
00300 mPattern.writeConfig(config);
00301
00302 if (bPopFilter) {
00303 switch ( mAction ) {
00304 case Down:
00305 config->writeEntry( "action", "down" );
00306 break;
00307 case Later:
00308 config->writeEntry( "action", "later" );
00309 break;
00310 case Delete:
00311 config->writeEntry( "action", "delete" );
00312 break;
00313 default:
00314 config->writeEntry( "action", "" );
00315 }
00316 } else {
00317 QStringList sets;
00318 if ( bApplyOnInbound )
00319 sets.append( "check-mail" );
00320 if ( bApplyOnOutbound )
00321 sets.append( "send-mail" );
00322 if ( bApplyOnExplicit )
00323 sets.append( "manual-filtering" );
00324 config->writeEntry( "apply-on", sets );
00325
00326 config->writeEntry( "StopProcessingHere", bStopProcessingHere );
00327 config->writeEntry( "ConfigureShortcut", bConfigureShortcut );
00328 if ( !mShortcut.isNull() )
00329 config->writeEntry( "Shortcut", mShortcut.toString() );
00330 config->writeEntry( "ConfigureToolbar", bConfigureToolbar );
00331 config->writeEntry( "Icon", mIcon );
00332 config->writeEntry( "AutomaticName", bAutoNaming );
00333 config->writeEntry( "Applicability", mApplicability );
00334
00335 QString key;
00336 int i;
00337
00338 QPtrListIterator<KMFilterAction> it( mActions );
00339 for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
00340 config->writeEntry( key.sprintf("action-name-%d", i),
00341 (*it)->name() );
00342 config->writeEntry( key.sprintf("action-args-%d", i),
00343 (*it)->argsAsString() );
00344 }
00345 config->writeEntry( "actions", i );
00346 config->writeEntry( "accounts-set", mAccounts );
00347 }
00348 }
00349
00350 void KMFilter::purify()
00351 {
00352 mPattern.purify();
00353
00354 if (!bPopFilter) {
00355 QPtrListIterator<KMFilterAction> it( mActions );
00356 it.toLast();
00357 while ( it.current() )
00358 if ( (*it)->isEmpty() )
00359 mActions.remove ( (*it) );
00360 else
00361 --it;
00362
00363
00364 QValueListIterator<int> it2 = mAccounts.begin();
00365 while ( it2 != mAccounts.end() ) {
00366 if ( !kmkernel->acctMgr()->find( *it2 ) )
00367 it2 = mAccounts.remove( it2 );
00368 else
00369 ++it2;
00370 }
00371 }
00372 }
00373
00374 bool KMFilter::isEmpty() const
00375 {
00376 if (bPopFilter)
00377 return mPattern.isEmpty();
00378 else
00379 return mPattern.isEmpty() && mActions.isEmpty() && mAccounts.isEmpty();
00380 }
00381
00382 #ifndef NDEBUG
00383 const QString KMFilter::asString() const
00384 {
00385 QString result;
00386
00387 result += mPattern.asString();
00388
00389 if (bPopFilter){
00390 result += " action: ";
00391 result += mAction;
00392 result += "\n";
00393 }
00394 else {
00395 QPtrListIterator<KMFilterAction> it( mActions );
00396 for ( it.toFirst() ; it.current() ; ++it ) {
00397 result += " action: ";
00398 result += (*it)->label();
00399 result += " ";
00400 result += (*it)->argsAsString();
00401 result += "\n";
00402 }
00403 result += "This filter belongs to the following sets:";
00404 if ( bApplyOnInbound )
00405 result += " Inbound";
00406 if ( bApplyOnOutbound )
00407 result += " Outbound";
00408 if ( bApplyOnExplicit )
00409 result += " Explicit";
00410 result += "\n";
00411 if ( bApplyOnInbound && mApplicability == All ) {
00412 result += "This filter applies to all accounts.\n";
00413 } else if ( bApplyOnInbound && mApplicability == ButImap ) {
00414 result += "This filter applies to all but online IMAP accounts.\n";
00415 } else if ( bApplyOnInbound ) {
00416 QValueListConstIterator<int> it2;
00417 result += "This filter applies to the following accounts:";
00418 if ( mAccounts.isEmpty() )
00419 result += " None";
00420 else for ( it2 = mAccounts.begin() ; it2 != mAccounts.end() ; ++it2 )
00421 if ( kmkernel->acctMgr()->find( *it2 ) )
00422 result += " " + kmkernel->acctMgr()->find( *it2 )->name();
00423 result += "\n";
00424 }
00425 if ( bStopProcessingHere )
00426 result += "If it matches, processing stops at this filter.\n";
00427 }
00428 return result;
00429 }
00430 #endif