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