kmail Library API Documentation

antispamwizard.cpp

00001 /*
00002     This file is part of KMail.
00003     Copyright (c) 2003 Andreas Gungl <a.gungl@gmx.de>
00004 
00005     KMail is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU General Public License, version 2, as
00007     published by the Free Software Foundation.
00008 
00009     KMail is distributed in the hope that it will be useful, but
00010     WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018     In addition, as a special exception, the copyright holders give
00019     permission to link the code of this program with any edition of
00020     the Qt library by Trolltech AS, Norway (or with modified versions
00021     of Qt that use the same license as Qt), and distribute linked
00022     combinations including the two.  You must obey the GNU General
00023     Public License in all respects for all of the code used other than
00024     Qt.  If you modify this file, you may extend this exception to
00025     your version of the file, but you are not obligated to do so.  If
00026     you do not wish to do so, delete this exception statement from
00027     your version.
00028 */
00029 
00030 #include "antispamwizard.h"
00031 #include "kcursorsaver.h"
00032 #include "kmfilter.h"
00033 #include "kmfilteraction.h"
00034 #include "kmfiltermgr.h"
00035 #include "kmkernel.h"
00036 #include "kmfoldertree.h"
00037 #include "kmmainwin.h"
00038 
00039 #include <kaction.h>
00040 #include <kapplication.h>
00041 #include <kdebug.h>
00042 #include <kdialog.h>
00043 #include <klocale.h>
00044 #include <kmessagebox.h>
00045 #include <kprocess.h>
00046 
00047 #include <qdom.h>
00048 #include <qlabel.h>
00049 #include <qlayout.h>
00050 #include <qtooltip.h>
00051 #include <qwhatsthis.h>
00052 
00053 using namespace KMail;
00054 
00055 AntiSpamWizard::AntiSpamWizard( WizardMode mode,
00056                                 QWidget* parent, KMFolderTree * mainFolderTree,
00057                                 KActionCollection * collection )
00058   : KWizard( parent ),
00059     mSpamRulesPage( 0 ),
00060     mVirusRulesPage( 0 ),
00061     mMode( mode )
00062 {
00063   // read the configuration for the anti-spam tools
00064   ConfigReader reader( mMode, mToolList );
00065   reader.readAndMergeConfig();
00066   mToolList = reader.getToolList();
00067 
00068 #ifndef NDEBUG
00069   if ( mMode == AntiSpam )
00070     kdDebug(5006) << endl << "Considered anti-spam tools: " << endl;
00071   else
00072     kdDebug(5006) << endl << "Considered anti-virus tools: " << endl;
00073 #endif
00074   QStringList descriptionList;
00075   QStringList whatsThisList;
00076   for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00077         it != mToolList.end(); ++it ) {
00078     descriptionList.append( (*it).getVisibleName() );
00079     whatsThisList.append( (*it).getWhatsThisText() );
00080 #ifndef NDEBUG
00081     kdDebug(5006) << "Predefined tool: " << (*it).getId() << endl;
00082     kdDebug(5006) << "Config version: " << (*it).getVersion() << endl;
00083     kdDebug(5006) << "Displayed name: " << (*it).getVisibleName() << endl;
00084     kdDebug(5006) << "Executable: " << (*it).getExecutable() << endl;
00085     kdDebug(5006) << "WhatsThis URL: " << (*it).getWhatsThisText() << endl;
00086     kdDebug(5006) << "Filter name: " << (*it).getFilterName() << endl;
00087     kdDebug(5006) << "Detection command: " << (*it).getDetectCmd() << endl;
00088     kdDebug(5006) << "Learn spam command: " << (*it).getSpamCmd() << endl;
00089     kdDebug(5006) << "Learn ham command: " << (*it).getHamCmd() << endl;
00090     kdDebug(5006) << "Detection header: " << (*it).getDetectionHeader() << endl;
00091     kdDebug(5006) << "Detection pattern: " << (*it).getDetectionPattern() << endl;
00092     kdDebug(5006) << "Use as RegExp: " << (*it).isUseRegExp() << endl;
00093     kdDebug(5006) << "Supports Bayes Filter: " << (*it).useBayesFilter() << endl;
00094     kdDebug(5006) << "Type: " << (*it).getType() << endl << endl;
00095 #endif
00096   }
00097 
00098   mActionCollection = collection;
00099 
00100   setCaption( ( mMode == AntiSpam ) ? i18n( "Anti-Spam Wizard" )
00101                                     : i18n( "Anti-Virus Wizard" ) );
00102   mInfoPage = new ASWizInfoPage( mMode, 0, "" );
00103   addPage( mInfoPage,
00104            ( mMode == AntiSpam )
00105            ? i18n( "Welcome to the KMail Anti-Spam Wizard" )
00106            : i18n( "Welcome to the KMail Anti-Virus Wizard" ) );
00107   mProgramsPage = new ASWizProgramsPage( 0, "", descriptionList, whatsThisList );
00108   addPage( mProgramsPage, i18n( "Please select the tools to be used by KMail" ));
00109   connect( mProgramsPage, SIGNAL( selectionChanged( void ) ),
00110             this, SLOT( checkProgramsSelections( void ) ) );
00111 
00112   if ( mMode == AntiSpam ) {
00113     mSpamRulesPage = new ASWizSpamRulesPage( 0, "", mainFolderTree );
00114     connect( mSpamRulesPage, SIGNAL( selectionChanged( void ) ),
00115              this, SLOT( checkSpamRulesSelections( void ) ) );
00116   }
00117   else {
00118     mVirusRulesPage = new ASWizVirusRulesPage( 0, "", mainFolderTree );
00119     connect( mVirusRulesPage, SIGNAL( selectionChanged( void ) ),
00120              this, SLOT( checkVirusRulesSelections( void ) ) );
00121   }
00122 
00123   connect( this, SIGNAL( helpClicked( void) ),
00124             this, SLOT( slotHelpClicked( void ) ) );
00125 
00126   setNextEnabled( mInfoPage, false );
00127   setNextEnabled( mProgramsPage, false );
00128 
00129   QTimer::singleShot( 0, this, SLOT( checkToolAvailability( void ) ) );
00130 }
00131 
00132 
00133 void AntiSpamWizard::accept()
00134 {
00135   if ( mSpamRulesPage )
00136     kdDebug( 5006 ) << "Folder name for spam is "
00137                     << mSpamRulesPage->selectedFolderName() << endl;
00138   if ( mVirusRulesPage )
00139     kdDebug( 5006 ) << "Folder name for viruses is "
00140                     << mVirusRulesPage->selectedFolderName() << endl;
00141 
00142   KMFilterActionDict dict;
00143   QPtrList<KMFilter> filterList;
00144 
00145   // Let's start with virus detection and handling,
00146   // so we can avoid spam checks for viral messages
00147   if ( mMode == AntiVirus ) {
00148     for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00149           it != mToolList.end(); ++it ) {
00150       if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) &&
00151          ( mVirusRulesPage->pipeRulesSelected() && (*it).isVirusTool() ) )
00152       {
00153         // pipe messages through the anti-virus tools,
00154         // one single filter for each tool
00155         // (could get combined but so it's easier to understand for the user)
00156         KMFilter* pipeFilter = new KMFilter();
00157         QPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions();
00158         KMFilterAction* pipeFilterAction = dict["filter app"]->create();
00159         pipeFilterAction->argsFromString( (*it).getDetectCmd() );
00160         pipeFilterActions->append( pipeFilterAction );
00161         KMSearchPattern* pipeFilterPattern = pipeFilter->pattern();
00162         pipeFilterPattern->setName( (*it).getFilterName() );
00163         pipeFilterPattern->append( KMSearchRule::createInstance( "<size>",
00164                                    KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
00165         pipeFilter->setApplyOnOutbound( FALSE);
00166         pipeFilter->setApplyOnInbound();
00167         pipeFilter->setApplyOnExplicit();
00168         pipeFilter->setStopProcessingHere( FALSE );
00169         pipeFilter->setConfigureShortcut( FALSE );
00170 
00171         filterList.append( pipeFilter );
00172       }
00173     }
00174 
00175     if ( mVirusRulesPage->moveRulesSelected() )
00176     {
00177       // Sort out viruses depending on header fields set by the tools
00178       KMFilter* virusFilter = new KMFilter();
00179       QPtrList<KMFilterAction>* virusFilterActions = virusFilter->actions();
00180       KMFilterAction* virusFilterAction1 = dict["transfer"]->create();
00181       virusFilterAction1->argsFromString( mVirusRulesPage->selectedFolderName() );
00182       virusFilterActions->append( virusFilterAction1 );
00183       if ( mVirusRulesPage->markReadRulesSelected() ) {
00184         KMFilterAction* virusFilterAction2 = dict["set status"]->create();
00185         virusFilterAction2->argsFromString( "R" ); // Read
00186         virusFilterActions->append( virusFilterAction2 );
00187       }
00188       KMSearchPattern* virusFilterPattern = virusFilter->pattern();
00189       virusFilterPattern->setName( i18n( "Virus handling" ) );
00190       virusFilterPattern->setOp( KMSearchPattern::OpOr );
00191       for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00192             it != mToolList.end(); ++it ) {
00193         if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ))
00194         {
00195           if ( (*it).isVirusTool() )
00196           {
00197               const QCString header = (*it).getDetectionHeader().ascii();
00198               const QString & pattern = (*it).getDetectionPattern();
00199               if ( (*it).isUseRegExp() )
00200                 virusFilterPattern->append(
00201                   KMSearchRule::createInstance( header,
00202                   KMSearchRule::FuncRegExp, pattern ) );
00203               else
00204                 virusFilterPattern->append(
00205                   KMSearchRule::createInstance( header,
00206                   KMSearchRule::FuncContains, pattern ) );
00207           }
00208         }
00209       }
00210       virusFilter->setApplyOnOutbound( FALSE);
00211       virusFilter->setApplyOnInbound();
00212       virusFilter->setApplyOnExplicit();
00213       virusFilter->setStopProcessingHere( TRUE );
00214       virusFilter->setConfigureShortcut( FALSE );
00215 
00216       filterList.append( virusFilter );
00217     }
00218   }
00219   else { // AntiSpam mode
00220     for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00221           it != mToolList.end(); ++it ) {
00222       if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) &&
00223          ( mSpamRulesPage->pipeRulesSelected() && (*it).isSpamTool() ) )
00224       {
00225         // pipe messages through the anti-spam tools,
00226         // one single filter for each tool
00227         // (could get combined but so it's easier to understand for the user)
00228         KMFilter* pipeFilter = new KMFilter();
00229         QPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions();
00230         KMFilterAction* pipeFilterAction = dict["filter app"]->create();
00231         pipeFilterAction->argsFromString( (*it).getDetectCmd() );
00232         pipeFilterActions->append( pipeFilterAction );
00233         KMSearchPattern* pipeFilterPattern = pipeFilter->pattern();
00234         pipeFilterPattern->setName( (*it).getFilterName() );
00235         pipeFilterPattern->append( KMSearchRule::createInstance( "<size>",
00236                                    KMSearchRule::FuncIsLessOrEqual, "256000" ) );
00237         pipeFilter->setApplyOnOutbound( FALSE);
00238         pipeFilter->setApplyOnInbound();
00239         pipeFilter->setApplyOnExplicit();
00240         pipeFilter->setStopProcessingHere( FALSE );
00241         pipeFilter->setConfigureShortcut( FALSE );
00242 
00243         filterList.append( pipeFilter );
00244       }
00245     }
00246 
00247     if ( mSpamRulesPage->moveRulesSelected() )
00248     {
00249       // Sort out spam depending on header fields set by the tools
00250       KMFilter* spamFilter = new KMFilter();
00251       QPtrList<KMFilterAction>* spamFilterActions = spamFilter->actions();
00252       KMFilterAction* spamFilterAction1 = dict["transfer"]->create();
00253       spamFilterAction1->argsFromString( mSpamRulesPage->selectedFolderName() );
00254       spamFilterActions->append( spamFilterAction1 );
00255       KMFilterAction* spamFilterAction2 = dict["set status"]->create();
00256       spamFilterAction2->argsFromString( "P" ); // Spam
00257       spamFilterActions->append( spamFilterAction2 );
00258       if ( mSpamRulesPage->markReadRulesSelected() ) {
00259         KMFilterAction* spamFilterAction3 = dict["set status"]->create();
00260         spamFilterAction3->argsFromString( "R" ); // Read
00261         spamFilterActions->append( spamFilterAction3 );
00262       }
00263       KMSearchPattern* spamFilterPattern = spamFilter->pattern();
00264       spamFilterPattern->setName( i18n( "Spam handling" ) );
00265       spamFilterPattern->setOp( KMSearchPattern::OpOr );
00266       for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00267             it != mToolList.end(); ++it ) {
00268         if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) )
00269         {
00270             if ( (*it).isSpamTool() )
00271             {
00272               const QCString header = (*it).getDetectionHeader().ascii();
00273               const QString & pattern = (*it).getDetectionPattern();
00274               if ( (*it).isUseRegExp() )
00275                 spamFilterPattern->append(
00276                   KMSearchRule::createInstance( header,
00277                   KMSearchRule::FuncRegExp, pattern ) );
00278               else
00279                 spamFilterPattern->append(
00280                   KMSearchRule::createInstance( header,
00281                   KMSearchRule::FuncContains, pattern ) );
00282             }
00283         }
00284       }
00285       spamFilter->setApplyOnOutbound( FALSE);
00286       spamFilter->setApplyOnInbound();
00287       spamFilter->setApplyOnExplicit();
00288       spamFilter->setStopProcessingHere( TRUE );
00289       spamFilter->setConfigureShortcut( FALSE );
00290 
00291       filterList.append( spamFilter );
00292     }
00293 
00294     if ( mSpamRulesPage->classifyRulesSelected() )
00295     {
00296       // Classify messages manually as Spam
00297       KMFilter* classSpamFilter = new KMFilter();
00298       classSpamFilter->setIcon( "mark_as_spam" );
00299       QPtrList<KMFilterAction>* classSpamFilterActions = classSpamFilter->actions();
00300       KMFilterAction* classSpamFilterActionFirst = dict["set status"]->create();
00301       classSpamFilterActionFirst->argsFromString( "P" );
00302       classSpamFilterActions->append( classSpamFilterActionFirst );
00303       for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00304             it != mToolList.end(); ++it ) {
00305         if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() )
00306             && (*it).useBayesFilter() )
00307         {
00308           KMFilterAction* classSpamFilterAction = dict["execute"]->create();
00309           classSpamFilterAction->argsFromString( (*it).getSpamCmd() );
00310           classSpamFilterActions->append( classSpamFilterAction );
00311         }
00312       }
00313       KMFilterAction* classSpamFilterActionLast = dict["transfer"]->create();
00314       classSpamFilterActionLast->argsFromString( mSpamRulesPage->selectedFolderName() );
00315       classSpamFilterActions->append( classSpamFilterActionLast );
00316 
00317       KMSearchPattern* classSpamFilterPattern = classSpamFilter->pattern();
00318       classSpamFilterPattern->setName( i18n( "Classify as spam" ) );
00319       classSpamFilterPattern->append( KMSearchRule::createInstance( "<size>",
00320                                       KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
00321       classSpamFilter->setApplyOnOutbound( FALSE);
00322       classSpamFilter->setApplyOnInbound( FALSE );
00323       classSpamFilter->setApplyOnExplicit( FALSE );
00324       classSpamFilter->setStopProcessingHere( TRUE );
00325       classSpamFilter->setConfigureShortcut( TRUE );
00326       classSpamFilter->setConfigureToolbar( TRUE );
00327       filterList.append( classSpamFilter );
00328 
00329       // Classify messages manually as not Spam / as Ham
00330       KMFilter* classHamFilter = new KMFilter();
00331       classHamFilter->setIcon( "mark_as_ham" );
00332       QPtrList<KMFilterAction>* classHamFilterActions = classHamFilter->actions();
00333       KMFilterAction* classHamFilterActionFirst = dict["set status"]->create();
00334       classHamFilterActionFirst->argsFromString( "H" );
00335       classHamFilterActions->append( classHamFilterActionFirst );
00336       for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00337             it != mToolList.end(); ++it ) {
00338         if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() )
00339             && (*it).useBayesFilter() )
00340         {
00341           KMFilterAction* classHamFilterAction = dict["execute"]->create();
00342           classHamFilterAction->argsFromString( (*it).getHamCmd() );
00343           classHamFilterActions->append( classHamFilterAction );
00344         }
00345       }
00346       KMSearchPattern* classHamFilterPattern = classHamFilter->pattern();
00347       classHamFilterPattern->setName( i18n( "Classify as NOT spam" ) );
00348       classHamFilterPattern->append( KMSearchRule::createInstance( "<size>",
00349                                      KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
00350       classHamFilter->setApplyOnOutbound( FALSE);
00351       classHamFilter->setApplyOnInbound( FALSE );
00352       classHamFilter->setApplyOnExplicit( FALSE );
00353       classHamFilter->setStopProcessingHere( TRUE );
00354       classHamFilter->setConfigureShortcut( TRUE );
00355       classHamFilter->setConfigureToolbar( TRUE );
00356       filterList.append( classHamFilter );
00357     }
00358 
00359     /* Now that all the filters have been added to the list, tell
00360      * the filter manager about it. That will emit filterListUpdate
00361      * which will result in the filter list in kmmainwidget being
00362      * initialized. This should happend only once. */
00363     KMKernel::self()->filterMgr()->appendFilters( filterList );
00364   }
00365 
00366   QDialog::accept();
00367 }
00368 
00369 
00370 void AntiSpamWizard::checkProgramsSelections()
00371 {
00372   bool status = false;
00373   bool canClassify = false;
00374   mSpamToolsUsed = false;
00375   mVirusToolsUsed = false;
00376   for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00377         it != mToolList.end(); ++it ) {
00378     if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) )
00379     {
00380       status = true;
00381       if ( (*it).isSpamTool() ) {
00382         mSpamToolsUsed = true;
00383         if ( (*it).useBayesFilter() )
00384           canClassify = true;
00385       }
00386       if ( (*it).isVirusTool() )
00387         mVirusToolsUsed = true;
00388     }
00389   }
00390 
00391   if ( mSpamRulesPage )
00392     mSpamRulesPage->allowClassification( canClassify );
00393 
00394   if ( mSpamRulesPage )
00395     removePage( mSpamRulesPage );
00396   if ( mVirusRulesPage )
00397     removePage( mVirusRulesPage );
00398   if ( ( mMode == AntiSpam ) && mSpamToolsUsed )
00399   {
00400     addPage( mSpamRulesPage, i18n( "Please select the spam filters to be created inside KMail." ));
00401     checkSpamRulesSelections();
00402   }
00403   if ( ( mMode == AntiVirus ) && mVirusToolsUsed )
00404   {
00405     addPage( mVirusRulesPage, i18n( "Please select the virus filters to be created inside KMail." ));
00406     checkVirusRulesSelections();
00407   }
00408 
00409   setNextEnabled( mProgramsPage, status );
00410 }
00411 
00412 
00413 void AntiSpamWizard::checkSpamRulesSelections()
00414 {
00415   setFinishEnabled( mSpamRulesPage, anySpamOptionChecked() );
00416 }
00417 
00418 void AntiSpamWizard::checkVirusRulesSelections()
00419 {
00420   setFinishEnabled( mVirusRulesPage, anyVirusOptionChecked() );
00421 }
00422 
00423 
00424 void AntiSpamWizard::checkToolAvailability()
00425 {
00426   KCursorSaver busy(KBusyPtr::busy()); // this can take some time to find the tools
00427 
00428   // checkboxes for the tools
00429   for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00430         it != mToolList.end(); ++it ) {
00431     QString text( i18n("Scanning for %1...").arg( (*it).getId() ) );
00432     mInfoPage->setScanProgressText( text );
00433     KApplication::kApplication()->processEvents( 200 );
00434     int rc = checkForProgram( (*it).getExecutable() );
00435     mProgramsPage->setProgramAsFound( (*it).getVisibleName(), !rc );
00436   }
00437   mInfoPage->setScanProgressText( ( mMode == AntiSpam )
00438                                   ? i18n("Scanning for anti-spam tools finished.")
00439                                   : i18n("Scanning for anti-virus tools finished.") );
00440   setNextEnabled( mInfoPage, true );
00441 }
00442 
00443 
00444 int AntiSpamWizard::checkForProgram( QString executable )
00445 {
00446   kdDebug(5006) << "Testing for executable:" << executable << endl;
00447   KProcess process;
00448   process << executable;
00449   process.setUseShell( true );
00450   process.start( KProcess::Block );
00451   return process.exitStatus();
00452 }
00453 
00454 
00455 void AntiSpamWizard::slotHelpClicked()
00456 {
00457   if ( mMode == AntiSpam )
00458     kapp->invokeHelp( "the-anti-spam-wizard", "kmail" );
00459   else
00460     kapp->invokeHelp( "the-anti-virus-wizard", "kmail" );
00461 }
00462 
00463 
00464 bool AntiSpamWizard::anySpamOptionChecked()
00465 {
00466   return ( mSpamRulesPage->moveRulesSelected()
00467         || mSpamRulesPage->pipeRulesSelected()
00468         || mSpamRulesPage->classifyRulesSelected() );
00469 }
00470 
00471 bool AntiSpamWizard::anyVirusOptionChecked()
00472 {
00473   return ( mVirusRulesPage->moveRulesSelected()
00474            || mVirusRulesPage->pipeRulesSelected() );
00475 }
00476 
00477 
00478 //---------------------------------------------------------------------------
00479 AntiSpamWizard::SpamToolConfig::SpamToolConfig(QString toolId,
00480       int configVersion,QString name, QString exec,
00481       QString url, QString filter, QString detection, QString spam, QString ham,
00482       QString header, QString pattern, bool regExp, bool bayesFilter, WizardMode type)
00483   : mId( toolId ), mVersion( configVersion ),
00484     mVisibleName( name ), mExecutable( exec ), mWhatsThisText( url ),
00485     mFilterName( filter ), mDetectCmd( detection ), mSpamCmd( spam ),
00486     mHamCmd( ham ), mDetectionHeader( header ), mDetectionPattern( pattern ),
00487     mUseRegExp( regExp ), mSupportsBayesFilter( bayesFilter ), mType( type )
00488 {
00489 }
00490 
00491 
00492 //---------------------------------------------------------------------------
00493 AntiSpamWizard::ConfigReader::ConfigReader( WizardMode mode,
00494                                             QValueList<SpamToolConfig> & configList )
00495   : mToolList( configList ),
00496     mMode( mode )
00497 {
00498   if ( mMode == AntiSpam )
00499     mConfig = new KConfig( "kmail.antispamrc", true );
00500   else
00501     mConfig = new KConfig( "kmail.antivirusrc", true );
00502 }
00503 
00504 AntiSpamWizard::ConfigReader::~ConfigReader( )
00505 {
00506   delete mConfig;
00507 }
00508 
00509 
00510 void AntiSpamWizard::ConfigReader::readAndMergeConfig()
00511 {
00512   QString groupName = ( mMode == AntiSpam )
00513                       ? QString("Spamtool #%1")
00514                       : QString("Virustool #%1");
00515   // read the configuration from the global config file
00516   mConfig->setReadDefaults( true );
00517   KConfigGroup general( mConfig, "General" );
00518   int registeredTools = general.readNumEntry( "tools", 0 );
00519   for (int i = 1; i <= registeredTools; i++)
00520   {
00521     KConfigGroup toolConfig( mConfig, groupName.arg( i ) );
00522     mToolList.append( readToolConfig( toolConfig ) );
00523   }
00524 
00525   // read the configuration from the user config file
00526   // and merge newer config data
00527   mConfig->setReadDefaults( false );
00528   KConfigGroup user_general( mConfig, "General" );
00529   int user_registeredTools = user_general.readNumEntry( "tools", 0 );
00530   for (int i = 1; i <= user_registeredTools; i++)
00531   {
00532     KConfigGroup toolConfig( mConfig, groupName.arg( i ) );
00533     mergeToolConfig( readToolConfig( toolConfig ) );
00534   }
00535   // Make sure to have add least one tool listed even when the
00536   // config file was not found or whatever went wrong
00537   // Currently only works for spam tools
00538   if ( mMode == AntiSpam ) {
00539     if ( registeredTools < 1 && user_registeredTools < 1 )
00540       mToolList.append( createDummyConfig() );
00541   }
00542 }
00543 
00544 
00545 AntiSpamWizard::SpamToolConfig
00546     AntiSpamWizard::ConfigReader::readToolConfig( KConfigGroup & configGroup )
00547 {
00548   QString id = configGroup.readEntry( "Ident" );
00549   int version = configGroup.readNumEntry( "Version" );
00550 #ifndef NDEBUG
00551   kdDebug(5006) << "Found predefined tool: " << id << endl;
00552   kdDebug(5006) << "With config version  : " << version << endl;
00553 #endif
00554   QString name = configGroup.readEntry( "VisibleName" );
00555   QString executable = configGroup.readEntry( "Executable" );
00556   QString url = configGroup.readEntry( "URL" );
00557   QString filterName = configGroup.readEntry( "PipeFilterName" );
00558   QString detectCmd = configGroup.readEntry( "PipeCmdDetect" );
00559   QString spamCmd = configGroup.readEntry( "ExecCmdSpam" );
00560   QString hamCmd = configGroup.readEntry( "ExecCmdHam" );
00561   QString header = configGroup.readEntry( "DetectionHeader" );
00562   QString pattern = configGroup.readEntry( "DetectionPattern" );
00563   bool useRegExp  = configGroup.readBoolEntry( "UseRegExp" );
00564   bool supportsBayes = configGroup.readBoolEntry( "SupportsBayes", false );
00565   return SpamToolConfig( id, version, name, executable, url,
00566                          filterName, detectCmd, spamCmd, hamCmd,
00567                          header, pattern, useRegExp, supportsBayes, mMode );
00568 }
00569 
00570 
00571 AntiSpamWizard::SpamToolConfig AntiSpamWizard::ConfigReader::createDummyConfig()
00572 {
00573   return SpamToolConfig( "spamassassin", 0,
00574                         "&SpamAssassin", "spamassassin -V",
00575                         "http://spamassassin.org", "SpamAssassin Check",
00576                         "spamassassin -L",
00577                         "sa-learn -L --spam --no-rebuild --single",
00578                         "sa-learn -L --ham --no-rebuild --single",
00579                         "X-Spam-Flag", "yes",
00580                         false, true, AntiSpam );
00581 }
00582 
00583 
00584 void AntiSpamWizard::ConfigReader::mergeToolConfig( AntiSpamWizard::SpamToolConfig config )
00585 {
00586   bool found = false;
00587   for ( QValueListIterator<SpamToolConfig> it = mToolList.begin();
00588         it != mToolList.end(); ++it ) {
00589 #ifndef NDEBUG
00590     kdDebug(5006) << "Check against tool: " << (*it).getId() << endl;
00591     kdDebug(5006) << "Against version   : " << (*it).getVersion() << endl;
00592 #endif
00593     if ( (*it).getId() == config.getId() )
00594     {
00595       found = true;
00596       if ( (*it).getVersion() < config.getVersion() )
00597       {
00598 #ifndef NDEBUG
00599         kdDebug(5006) << "Replacing config ..." << endl;
00600 #endif
00601         mToolList.remove( it );
00602         mToolList.append( config );
00603       }
00604       break;
00605     }
00606   }
00607   if ( !found )
00608     mToolList.append( config );
00609 }
00610 
00611 
00612 //---------------------------------------------------------------------------
00613 ASWizInfoPage::ASWizInfoPage( AntiSpamWizard::WizardMode mode,
00614                               QWidget * parent, const char * name )
00615   : QWidget( parent, name )
00616 {
00617   QGridLayout *grid = new QGridLayout( this, 1, 1, KDialog::marginHint(),
00618                                         KDialog::spacingHint() );
00619   grid->setColStretch( 1, 10 );
00620 
00621   mIntroText = new QLabel( this );
00622   mIntroText->setText(
00623     ( mode == AntiSpamWizard::AntiSpam )
00624     ? i18n(
00625       "<p>Here you can get some assistance in setting up KMail's filter "
00626       "rules to use some commonly-known anti-spam tools.</p>"
00627       "<p>The wizard can detect those tools on your computer as "
00628       "well as create filter rules to classify messages using these "
00629       "tools and to separate messages classified as spam. "
00630       "The wizard will not take any existing filter "
00631       "rules into consideration: it will always append the new rules.</p>"
00632       "<p><b>Warning:</b> As KMail is blocked during the scan of the "
00633       "messages for spam, you may encounter problems with "
00634       "the responsiveness of KMail because anti-spam tool "
00635       "operations are usually time consuming; please consider "
00636       "deleting the filter rules created by the wizard to get "
00637       "back to the former behavior."
00638       )
00639     : i18n(
00640       "<p>Here you can get some assistance in setting up KMail's filter "
00641       "rules to use some commonly-known anti-virus tools.</p>"
00642       "<p>The wizard can detect those tools on your computer as "
00643       "well as create filter rules to classify messages using these "
00644       "tools and to separate messages containing viruses. "
00645       "The wizard will not take any existing filter "
00646       "rules into consideration: it will always append the new rules.</p>"
00647       "<p><b>Warning:</b> As KMail is blocked during the scan of the "
00648       "messages for viruses, you may encounter problems with "
00649       "the responsiveness of KMail because anti-virus tool "
00650       "operations are usually time consuming; please consider "
00651       "deleting the filter rules created by the wizard to get "
00652       "back to the former behavior."
00653       ) );
00654   grid->addWidget( mIntroText, 0, 0 );
00655 
00656   mScanProgressText = new QLabel( this );
00657   mScanProgressText->setText( "" ) ;
00658   grid->addWidget( mScanProgressText, 1, 0 );
00659 }
00660 
00661 void ASWizInfoPage::setScanProgressText( const QString &toolName )
00662 {
00663   mScanProgressText->setText( toolName );
00664 }
00665 
00666 //---------------------------------------------------------------------------
00667 ASWizProgramsPage::ASWizProgramsPage( QWidget * parent, const char * name,
00668                                       QStringList &checkBoxTextList,
00669                                       QStringList &checkBoxWhatsThisList )
00670   : QWidget( parent, name )
00671 {
00672   QGridLayout *grid = new QGridLayout( this, 3, 1, KDialog::marginHint(),
00673                                         KDialog::spacingHint() );
00674   // checkboxes for the tools
00675   int row = 0;
00676   QStringList::Iterator it1 = checkBoxTextList.begin();
00677   QStringList::Iterator it2 = checkBoxWhatsThisList.begin();
00678   while ( it1 != checkBoxTextList.end() )
00679   {
00680     QCheckBox *box = new QCheckBox( *it1, this );
00681     if ( it2 != checkBoxWhatsThisList.end() )
00682     {
00683       QWhatsThis::add( box, *it2 );
00684       QToolTip::add( box, *it2 );
00685       ++it2;
00686     }
00687     grid->addWidget( box, row++, 0 );
00688     connect( box, SIGNAL(clicked()),
00689              this, SLOT(processSelectionChange(void)) );
00690     mProgramDict.insert( *it1, box );
00691     ++it1;
00692   }
00693 
00694   // hint text
00695   QLabel *introText = new QLabel( this );
00696   introText->setText( i18n(
00697     "<p>For these tools it is possible to let the "
00698     "wizard create filter rules. KMail tried to find the tools "
00699     "in the PATH of your system; the wizard does not allow you "
00700     "to create rules for tools which were not found: "
00701     "this is to keep your configuration consistent and "
00702     "to minimize the risk of unpredicted behavior.</p>"
00703     ) );
00704   grid->addWidget( introText, row++, 0 );
00705 }
00706 
00707 
00708 bool ASWizProgramsPage::isProgramSelected( const QString &visibleName )
00709 {
00710   if ( mProgramDict[visibleName] )
00711     return mProgramDict[visibleName]->isChecked();
00712   else
00713     return false;
00714 }
00715 
00716 
00717 void ASWizProgramsPage::setProgramAsFound( const QString &visibleName, bool found )
00718 {
00719   QCheckBox * box = mProgramDict[visibleName];
00720   if ( box )
00721   {
00722     QString foundText( i18n("(found on this system)") );
00723     QString notFoundText( i18n("(not found on this system)") );
00724     QString labelText = visibleName;
00725     labelText += " ";
00726     if ( found )
00727       labelText += foundText;
00728     else
00729     {
00730       labelText += notFoundText;
00731       box->setEnabled( false );
00732     }
00733     box->setText( labelText );
00734   }
00735 }
00736 
00737 
00738 void ASWizProgramsPage::processSelectionChange()
00739 {
00740   emit selectionChanged();
00741 }
00742 
00743 //---------------------------------------------------------------------------
00744 ASWizSpamRulesPage::ASWizSpamRulesPage( QWidget * parent, const char * name,
00745                                         KMFolderTree * mainFolderTree )
00746   : QWidget( parent, name )
00747 {
00748   QGridLayout *grid = new QGridLayout( this, 5, 1, KDialog::marginHint(),
00749                                        KDialog::spacingHint() );
00750 
00751   mClassifyRules = new QCheckBox( i18n("Classify messages manually as spam"), this );
00752   QWhatsThis::add( mClassifyRules,
00753       i18n( "Sometimes messages are classified wrongly or even not at all; "
00754             "the latter might be by intention, because you perhaps filter "
00755             "out messages from mailing lists before you let the anti-spam "
00756             "tools classify the rest of the messages. You can correct these "
00757             "wrong or missing classifications manually by using the "
00758             "appropriate toolbar buttons which trigger special filters "
00759             "created by this wizard." ) );
00760   grid->addWidget( mClassifyRules, 0, 0 );
00761 
00762   mPipeRules = new QCheckBox( i18n("Classify messages using the anti-spam tools"), this );
00763   QWhatsThis::add( mPipeRules,
00764       i18n( "Let the anti-spam tools classify your messages. The wizard "
00765             "will create appropriate filters. The messages are usually "
00766             "marked by the tools so that following filters can react "
00767             "on this and, for example, move spam messages to a special folder.") );
00768   grid->addWidget( mPipeRules, 1, 0 );
00769 
00770   mMoveRules = new QCheckBox( i18n("Move detected spam messages to the selected folder"), this );
00771   QWhatsThis::add( mMoveRules,
00772       i18n( "A filter to detect messages classified as spam and to move "
00773             "those messages into a predefined folder is created. The "
00774             "default folder is the trash folder, but you may change that "
00775             "in the folder view.") );
00776   grid->addWidget( mMoveRules, 2, 0 );
00777 
00778   mMarkRules = new QCheckBox( i18n("Additionally, mark detected spam messages as read"), this );
00779   mMarkRules->setEnabled( false );
00780   QWhatsThis::add( mMarkRules,
00781       i18n( "Mark messages which have been classified as "
00782             "spam as read, as well as moving them to the selected "
00783             "folder.") );
00784   grid->addWidget( mMarkRules, 3, 0 );
00785 
00786   QString s = "trash";
00787   mFolderTree = new SimpleFolderTree( this, mainFolderTree, s, true );
00788   grid->addWidget( mFolderTree, 4, 0 );
00789 
00790   connect( mPipeRules, SIGNAL(clicked()),
00791             this, SLOT(processSelectionChange(void)) );
00792   connect( mClassifyRules, SIGNAL(clicked()),
00793             this, SLOT(processSelectionChange(void)) );
00794   connect( mMoveRules, SIGNAL(clicked()),
00795             this, SLOT(processSelectionChange(void)) );
00796   connect( mMarkRules, SIGNAL(clicked()),
00797             this, SLOT(processSelectionChange(void)) );
00798   connect( mMoveRules, SIGNAL( toggled( bool ) ),
00799            mMarkRules, SLOT( setEnabled( bool ) ) );
00800 }
00801 
00802 bool ASWizSpamRulesPage::pipeRulesSelected() const
00803 {
00804   return mPipeRules->isChecked();
00805 }
00806 
00807 
00808 bool ASWizSpamRulesPage::classifyRulesSelected() const
00809 {
00810   return mClassifyRules->isChecked();
00811 }
00812 
00813 
00814 bool ASWizSpamRulesPage::moveRulesSelected() const
00815 {
00816   return mMoveRules->isChecked();
00817 }
00818 
00819 bool ASWizSpamRulesPage::markReadRulesSelected() const
00820 {
00821   return mMarkRules->isChecked();
00822 }
00823 
00824 
00825 QString ASWizSpamRulesPage::selectedFolderName() const
00826 {
00827   QString name = "trash";
00828   if ( mFolderTree->folder() )
00829     name = mFolderTree->folder()->idString();
00830   return name;
00831 }
00832 
00833 void ASWizSpamRulesPage::processSelectionChange()
00834 {
00835   emit selectionChanged();
00836 }
00837 
00838 
00839 void ASWizSpamRulesPage::allowClassification( bool enabled )
00840 {
00841   if ( enabled )
00842     mClassifyRules->setEnabled( true );
00843   else
00844   {
00845     mClassifyRules->setChecked( false );
00846     mClassifyRules->setEnabled( false );
00847   }
00848 }
00849 
00850 //---------------------------------------------------------------------------
00851 ASWizVirusRulesPage::ASWizVirusRulesPage( QWidget * parent, const char * name,
00852                                   KMFolderTree * mainFolderTree )
00853   : QWidget( parent, name )
00854 {
00855   QGridLayout *grid = new QGridLayout( this, 5, 1, KDialog::marginHint(),
00856                                        KDialog::spacingHint() );
00857 
00858   mPipeRules = new QCheckBox( i18n("Check messages using the anti-virus tools"), this );
00859   QWhatsThis::add( mPipeRules,
00860       i18n( "Let the anti-virus tools check your messages. The wizard "
00861             "will create appropriate filters. The messages are usually "
00862             "marked by the tools so that following filters can react "
00863             "on this and, for example, move virus messages to a special folder.") );
00864   grid->addWidget( mPipeRules, 0, 0 );
00865 
00866   mMoveRules = new QCheckBox( i18n("Move detected viral messages to the selected folder"), this );
00867   QWhatsThis::add( mMoveRules,
00868       i18n( "A filter to detect messages classified as virus-infected and to move "
00869             "those messages into a predefined folder is created. The "
00870             "default folder is the trash folder, but you may change that "
00871             "in the folder view.") );
00872   grid->addWidget( mMoveRules, 1, 0 );
00873 
00874   mMarkRules = new QCheckBox( i18n("Additionally, mark detected viral messages as read"), this );
00875   mMarkRules->setEnabled( false );
00876   QWhatsThis::add( mMarkRules,
00877       i18n( "Mark messages which have been classified as "
00878             "virus-infected as read, as well as moving them "
00879             "to the selected folder.") );
00880   grid->addWidget( mMarkRules, 2, 0 );
00881 
00882   QString s = "trash";
00883   mFolderTree = new SimpleFolderTree( this, mainFolderTree, s, true );
00884   grid->addWidget( mFolderTree, 3, 0 );
00885 
00886   connect( mPipeRules, SIGNAL(clicked()),
00887             this, SLOT(processSelectionChange(void)) );
00888   connect( mMoveRules, SIGNAL(clicked()),
00889             this, SLOT(processSelectionChange(void)) );
00890   connect( mMarkRules, SIGNAL(clicked()),
00891             this, SLOT(processSelectionChange(void)) );
00892   connect( mMoveRules, SIGNAL( toggled( bool ) ),
00893            mMarkRules, SLOT( setEnabled( bool ) ) );
00894 }
00895 
00896 bool ASWizVirusRulesPage::pipeRulesSelected() const
00897 {
00898   return mPipeRules->isChecked();
00899 }
00900 
00901 
00902 bool ASWizVirusRulesPage::moveRulesSelected() const
00903 {
00904   return mMoveRules->isChecked();
00905 }
00906 
00907 bool ASWizVirusRulesPage::markReadRulesSelected() const
00908 {
00909   return mMarkRules->isChecked();
00910 }
00911 
00912 
00913 QString ASWizVirusRulesPage::selectedFolderName() const
00914 {
00915   QString name = "trash";
00916   if ( mFolderTree->folder() )
00917     name = mFolderTree->folder()->idString();
00918   return name;
00919 }
00920 
00921 void ASWizVirusRulesPage::processSelectionChange()
00922 {
00923   emit selectionChanged();
00924 }
00925 
00926 #include "antispamwizard.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Aug 23 18:21:04 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003