You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
927 lines
35 KiB
927 lines
35 KiB
/* |
|
This file is part of KMail. |
|
Copyright (c) 2003 Andreas Gungl <a.gungl@gmx.de> |
|
|
|
KMail is free software; you can redistribute it and/or modify it |
|
under the terms of the GNU General Public License, version 2, as |
|
published by the Free Software Foundation. |
|
|
|
KMail is distributed in the hope that it will be useful, but |
|
WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program; if not, write to the Free Software |
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
|
|
In addition, as a special exception, the copyright holders give |
|
permission to link the code of this program with any edition of |
|
the Qt library by Trolltech AS, Norway (or with modified versions |
|
of Qt that use the same license as Qt), and distribute linked |
|
combinations including the two. You must obey the GNU General |
|
Public License in all respects for all of the code used other than |
|
Qt. If you modify this file, you may extend this exception to |
|
your version of the file, but you are not obligated to do so. If |
|
you do not wish to do so, delete this exception statement from |
|
your version. |
|
*/ |
|
|
|
#include "antispamwizard.h" |
|
#include "kcursorsaver.h" |
|
#include "kmfilter.h" |
|
#include "kmfilteraction.h" |
|
#include "kmfiltermgr.h" |
|
#include "kmkernel.h" |
|
#include "kmfolderseldlg.h" |
|
#include "kmfoldertree.h" |
|
#include "kmmainwin.h" |
|
|
|
#include <kaction.h> |
|
#include <kapplication.h> |
|
#include <kdebug.h> |
|
#include <kdialog.h> |
|
#include <klocale.h> |
|
#include <kmessagebox.h> |
|
#include <kprocess.h> |
|
|
|
#include <qdom.h> |
|
#include <qlabel.h> |
|
#include <qlayout.h> |
|
#include <qtooltip.h> |
|
#include <qwhatsthis.h> |
|
|
|
using namespace KMail; |
|
|
|
AntiSpamWizard::AntiSpamWizard( WizardMode mode, |
|
QWidget* parent, KMFolderTree * mainFolderTree, |
|
KActionCollection * collection ) |
|
: KWizard( parent ), |
|
mSpamRulesPage( 0 ), |
|
mVirusRulesPage( 0 ), |
|
mMode( mode ) |
|
{ |
|
// read the configuration for the anti-spam tools |
|
ConfigReader reader( mMode, mToolList ); |
|
reader.readAndMergeConfig(); |
|
mToolList = reader.getToolList(); |
|
|
|
#ifndef NDEBUG |
|
if ( mMode == AntiSpam ) |
|
kdDebug(5006) << endl << "Considered anti-spam tools: " << endl; |
|
else |
|
kdDebug(5006) << endl << "Considered anti-virus tools: " << endl; |
|
#endif |
|
QStringList descriptionList; |
|
QStringList whatsThisList; |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
descriptionList.append( (*it).getVisibleName() ); |
|
whatsThisList.append( (*it).getWhatsThisText() ); |
|
#ifndef NDEBUG |
|
kdDebug(5006) << "Predefined tool: " << (*it).getId() << endl; |
|
kdDebug(5006) << "Config version: " << (*it).getVersion() << endl; |
|
kdDebug(5006) << "Displayed name: " << (*it).getVisibleName() << endl; |
|
kdDebug(5006) << "Executable: " << (*it).getExecutable() << endl; |
|
kdDebug(5006) << "WhatsThis URL: " << (*it).getWhatsThisText() << endl; |
|
kdDebug(5006) << "Filter name: " << (*it).getFilterName() << endl; |
|
kdDebug(5006) << "Detection command: " << (*it).getDetectCmd() << endl; |
|
kdDebug(5006) << "Learn spam command: " << (*it).getSpamCmd() << endl; |
|
kdDebug(5006) << "Learn ham command: " << (*it).getHamCmd() << endl; |
|
kdDebug(5006) << "Detection header: " << (*it).getDetectionHeader() << endl; |
|
kdDebug(5006) << "Detection pattern: " << (*it).getDetectionPattern() << endl; |
|
kdDebug(5006) << "Use as RegExp: " << (*it).isUseRegExp() << endl; |
|
kdDebug(5006) << "Supports Bayes Filter: " << (*it).useBayesFilter() << endl; |
|
kdDebug(5006) << "Type: " << (*it).getType() << endl << endl; |
|
#endif |
|
} |
|
|
|
mActionCollection = collection; |
|
|
|
setCaption( ( mMode == AntiSpam ) ? i18n( "Anti-Spam Wizard" ) |
|
: i18n( "Anti-Virus Wizard" ) ); |
|
mInfoPage = new ASWizInfoPage( mMode, 0, "" ); |
|
addPage( mInfoPage, |
|
( mMode == AntiSpam ) |
|
? i18n( "Welcome to the KMail Anti-Spam Wizard" ) |
|
: i18n( "Welcome to the KMail Anti-Virus Wizard" ) ); |
|
mProgramsPage = new ASWizProgramsPage( 0, "", descriptionList, whatsThisList ); |
|
addPage( mProgramsPage, i18n( "Please select the tools to be used by KMail" )); |
|
connect( mProgramsPage, SIGNAL( selectionChanged( void ) ), |
|
this, SLOT( checkProgramsSelections( void ) ) ); |
|
|
|
if ( mMode == AntiSpam ) { |
|
mSpamRulesPage = new ASWizSpamRulesPage( 0, "", mainFolderTree ); |
|
connect( mSpamRulesPage, SIGNAL( selectionChanged( void ) ), |
|
this, SLOT( checkSpamRulesSelections( void ) ) ); |
|
} |
|
else { |
|
mVirusRulesPage = new ASWizVirusRulesPage( 0, "", mainFolderTree ); |
|
connect( mVirusRulesPage, SIGNAL( selectionChanged( void ) ), |
|
this, SLOT( checkVirusRulesSelections( void ) ) ); |
|
} |
|
|
|
connect( this, SIGNAL( helpClicked( void) ), |
|
this, SLOT( slotHelpClicked( void ) ) ); |
|
|
|
setNextEnabled( mInfoPage, false ); |
|
setNextEnabled( mProgramsPage, false ); |
|
|
|
QTimer::singleShot( 0, this, SLOT( checkToolAvailability( void ) ) ); |
|
} |
|
|
|
|
|
void AntiSpamWizard::accept() |
|
{ |
|
if ( mSpamRulesPage ) |
|
kdDebug( 5006 ) << "Folder name for spam is " |
|
<< mSpamRulesPage->selectedFolderName() << endl; |
|
if ( mVirusRulesPage ) |
|
kdDebug( 5006 ) << "Folder name for viruses is " |
|
<< mVirusRulesPage->selectedFolderName() << endl; |
|
|
|
KMFilterActionDict dict; |
|
QPtrList<KMFilter> filterList; |
|
|
|
// Let's start with virus detection and handling, |
|
// so we can avoid spam checks for viral messages |
|
if ( mMode == AntiVirus ) { |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) && |
|
( mVirusRulesPage->pipeRulesSelected() && (*it).isVirusTool() ) ) |
|
{ |
|
// pipe messages through the anti-virus tools, |
|
// one single filter for each tool |
|
// (could get combined but so it's easier to understand for the user) |
|
KMFilter* pipeFilter = new KMFilter(); |
|
QPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions(); |
|
KMFilterAction* pipeFilterAction = dict["filter app"]->create(); |
|
pipeFilterAction->argsFromString( (*it).getDetectCmd() ); |
|
pipeFilterActions->append( pipeFilterAction ); |
|
KMSearchPattern* pipeFilterPattern = pipeFilter->pattern(); |
|
pipeFilterPattern->setName( (*it).getFilterName() ); |
|
pipeFilterPattern->append( KMSearchRule::createInstance( "<size>", |
|
KMSearchRule::FuncIsGreaterOrEqual, "0" ) ); |
|
pipeFilter->setApplyOnOutbound( FALSE); |
|
pipeFilter->setApplyOnInbound(); |
|
pipeFilter->setApplyOnExplicit(); |
|
pipeFilter->setStopProcessingHere( FALSE ); |
|
pipeFilter->setConfigureShortcut( FALSE ); |
|
|
|
filterList.append( pipeFilter ); |
|
} |
|
} |
|
|
|
if ( mVirusRulesPage->moveRulesSelected() ) |
|
{ |
|
// Sort out viruses depending on header fields set by the tools |
|
KMFilter* virusFilter = new KMFilter(); |
|
QPtrList<KMFilterAction>* virusFilterActions = virusFilter->actions(); |
|
KMFilterAction* virusFilterAction1 = dict["transfer"]->create(); |
|
virusFilterAction1->argsFromString( mVirusRulesPage->selectedFolderName() ); |
|
virusFilterActions->append( virusFilterAction1 ); |
|
if ( mVirusRulesPage->markReadRulesSelected() ) { |
|
KMFilterAction* virusFilterAction2 = dict["set status"]->create(); |
|
virusFilterAction2->argsFromString( "R" ); // Read |
|
virusFilterActions->append( virusFilterAction2 ); |
|
} |
|
KMSearchPattern* virusFilterPattern = virusFilter->pattern(); |
|
virusFilterPattern->setName( i18n( "Virus handling" ) ); |
|
virusFilterPattern->setOp( KMSearchPattern::OpOr ); |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() )) |
|
{ |
|
if ( (*it).isVirusTool() ) |
|
{ |
|
const QCString header = (*it).getDetectionHeader().ascii(); |
|
const QString & pattern = (*it).getDetectionPattern(); |
|
if ( (*it).isUseRegExp() ) |
|
virusFilterPattern->append( |
|
KMSearchRule::createInstance( header, |
|
KMSearchRule::FuncRegExp, pattern ) ); |
|
else |
|
virusFilterPattern->append( |
|
KMSearchRule::createInstance( header, |
|
KMSearchRule::FuncContains, pattern ) ); |
|
} |
|
} |
|
} |
|
virusFilter->setApplyOnOutbound( FALSE); |
|
virusFilter->setApplyOnInbound(); |
|
virusFilter->setApplyOnExplicit(); |
|
virusFilter->setStopProcessingHere( TRUE ); |
|
virusFilter->setConfigureShortcut( FALSE ); |
|
|
|
filterList.append( virusFilter ); |
|
} |
|
} |
|
else { // AntiSpam mode |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) && |
|
( mSpamRulesPage->pipeRulesSelected() && (*it).isSpamTool() ) ) |
|
{ |
|
// pipe messages through the anti-spam tools, |
|
// one single filter for each tool |
|
// (could get combined but so it's easier to understand for the user) |
|
KMFilter* pipeFilter = new KMFilter(); |
|
QPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions(); |
|
KMFilterAction* pipeFilterAction = dict["filter app"]->create(); |
|
pipeFilterAction->argsFromString( (*it).getDetectCmd() ); |
|
pipeFilterActions->append( pipeFilterAction ); |
|
KMSearchPattern* pipeFilterPattern = pipeFilter->pattern(); |
|
pipeFilterPattern->setName( (*it).getFilterName() ); |
|
pipeFilterPattern->append( KMSearchRule::createInstance( "<size>", |
|
KMSearchRule::FuncIsLessOrEqual, "256000" ) ); |
|
pipeFilter->setApplyOnOutbound( FALSE); |
|
pipeFilter->setApplyOnInbound(); |
|
pipeFilter->setApplyOnExplicit(); |
|
pipeFilter->setStopProcessingHere( FALSE ); |
|
pipeFilter->setConfigureShortcut( FALSE ); |
|
|
|
filterList.append( pipeFilter ); |
|
} |
|
} |
|
|
|
if ( mSpamRulesPage->moveRulesSelected() ) |
|
{ |
|
// Sort out spam depending on header fields set by the tools |
|
KMFilter* spamFilter = new KMFilter(); |
|
QPtrList<KMFilterAction>* spamFilterActions = spamFilter->actions(); |
|
KMFilterAction* spamFilterAction1 = dict["transfer"]->create(); |
|
spamFilterAction1->argsFromString( mSpamRulesPage->selectedFolderName() ); |
|
spamFilterActions->append( spamFilterAction1 ); |
|
KMFilterAction* spamFilterAction2 = dict["set status"]->create(); |
|
spamFilterAction2->argsFromString( "P" ); // Spam |
|
spamFilterActions->append( spamFilterAction2 ); |
|
if ( mSpamRulesPage->markReadRulesSelected() ) { |
|
KMFilterAction* spamFilterAction3 = dict["set status"]->create(); |
|
spamFilterAction3->argsFromString( "R" ); // Read |
|
spamFilterActions->append( spamFilterAction3 ); |
|
} |
|
KMSearchPattern* spamFilterPattern = spamFilter->pattern(); |
|
spamFilterPattern->setName( i18n( "Spam handling" ) ); |
|
spamFilterPattern->setOp( KMSearchPattern::OpOr ); |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) ) |
|
{ |
|
if ( (*it).isSpamTool() ) |
|
{ |
|
const QCString header = (*it).getDetectionHeader().ascii(); |
|
const QString & pattern = (*it).getDetectionPattern(); |
|
if ( (*it).isUseRegExp() ) |
|
spamFilterPattern->append( |
|
KMSearchRule::createInstance( header, |
|
KMSearchRule::FuncRegExp, pattern ) ); |
|
else |
|
spamFilterPattern->append( |
|
KMSearchRule::createInstance( header, |
|
KMSearchRule::FuncContains, pattern ) ); |
|
} |
|
} |
|
} |
|
spamFilter->setApplyOnOutbound( FALSE); |
|
spamFilter->setApplyOnInbound(); |
|
spamFilter->setApplyOnExplicit(); |
|
spamFilter->setStopProcessingHere( TRUE ); |
|
spamFilter->setConfigureShortcut( FALSE ); |
|
|
|
filterList.append( spamFilter ); |
|
} |
|
|
|
if ( mSpamRulesPage->classifyRulesSelected() ) |
|
{ |
|
// Classify messages manually as Spam |
|
KMFilter* classSpamFilter = new KMFilter(); |
|
classSpamFilter->setIcon( "mark_as_spam" ); |
|
QPtrList<KMFilterAction>* classSpamFilterActions = classSpamFilter->actions(); |
|
KMFilterAction* classSpamFilterActionFirst = dict["set status"]->create(); |
|
classSpamFilterActionFirst->argsFromString( "P" ); |
|
classSpamFilterActions->append( classSpamFilterActionFirst ); |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) |
|
&& (*it).useBayesFilter() ) |
|
{ |
|
KMFilterAction* classSpamFilterAction = dict["execute"]->create(); |
|
classSpamFilterAction->argsFromString( (*it).getSpamCmd() ); |
|
classSpamFilterActions->append( classSpamFilterAction ); |
|
} |
|
} |
|
KMFilterAction* classSpamFilterActionLast = dict["transfer"]->create(); |
|
classSpamFilterActionLast->argsFromString( mSpamRulesPage->selectedFolderName() ); |
|
classSpamFilterActions->append( classSpamFilterActionLast ); |
|
|
|
KMSearchPattern* classSpamFilterPattern = classSpamFilter->pattern(); |
|
classSpamFilterPattern->setName( i18n( "Classify as spam" ) ); |
|
classSpamFilterPattern->append( KMSearchRule::createInstance( "<size>", |
|
KMSearchRule::FuncIsGreaterOrEqual, "0" ) ); |
|
classSpamFilter->setApplyOnOutbound( FALSE); |
|
classSpamFilter->setApplyOnInbound( FALSE ); |
|
classSpamFilter->setApplyOnExplicit( FALSE ); |
|
classSpamFilter->setStopProcessingHere( TRUE ); |
|
classSpamFilter->setConfigureShortcut( TRUE ); |
|
classSpamFilter->setConfigureToolbar( TRUE ); |
|
filterList.append( classSpamFilter ); |
|
|
|
// Classify messages manually as not Spam / as Ham |
|
KMFilter* classHamFilter = new KMFilter(); |
|
classHamFilter->setIcon( "mark_as_ham" ); |
|
QPtrList<KMFilterAction>* classHamFilterActions = classHamFilter->actions(); |
|
KMFilterAction* classHamFilterActionFirst = dict["set status"]->create(); |
|
classHamFilterActionFirst->argsFromString( "H" ); |
|
classHamFilterActions->append( classHamFilterActionFirst ); |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) |
|
&& (*it).useBayesFilter() ) |
|
{ |
|
KMFilterAction* classHamFilterAction = dict["execute"]->create(); |
|
classHamFilterAction->argsFromString( (*it).getHamCmd() ); |
|
classHamFilterActions->append( classHamFilterAction ); |
|
} |
|
} |
|
KMSearchPattern* classHamFilterPattern = classHamFilter->pattern(); |
|
classHamFilterPattern->setName( i18n( "Classify as NOT spam" ) ); |
|
classHamFilterPattern->append( KMSearchRule::createInstance( "<size>", |
|
KMSearchRule::FuncIsGreaterOrEqual, "0" ) ); |
|
classHamFilter->setApplyOnOutbound( FALSE); |
|
classHamFilter->setApplyOnInbound( FALSE ); |
|
classHamFilter->setApplyOnExplicit( FALSE ); |
|
classHamFilter->setStopProcessingHere( TRUE ); |
|
classHamFilter->setConfigureShortcut( TRUE ); |
|
classHamFilter->setConfigureToolbar( TRUE ); |
|
filterList.append( classHamFilter ); |
|
} |
|
|
|
/* Now that all the filters have been added to the list, tell |
|
* the filter manager about it. That will emit filterListUpdate |
|
* which will result in the filter list in kmmainwidget being |
|
* initialized. This should happend only once. */ |
|
KMKernel::self()->filterMgr()->appendFilters( filterList ); |
|
} |
|
|
|
QDialog::accept(); |
|
} |
|
|
|
|
|
void AntiSpamWizard::checkProgramsSelections() |
|
{ |
|
bool status = false; |
|
bool canClassify = false; |
|
mSpamToolsUsed = false; |
|
mVirusToolsUsed = false; |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
if ( mProgramsPage->isProgramSelected( (*it).getVisibleName() ) ) |
|
{ |
|
status = true; |
|
if ( (*it).isSpamTool() ) { |
|
mSpamToolsUsed = true; |
|
if ( (*it).useBayesFilter() ) |
|
canClassify = true; |
|
} |
|
if ( (*it).isVirusTool() ) |
|
mVirusToolsUsed = true; |
|
} |
|
} |
|
|
|
if ( mSpamRulesPage ) |
|
mSpamRulesPage->allowClassification( canClassify ); |
|
|
|
if ( mSpamRulesPage ) |
|
removePage( mSpamRulesPage ); |
|
if ( mVirusRulesPage ) |
|
removePage( mVirusRulesPage ); |
|
if ( ( mMode == AntiSpam ) && mSpamToolsUsed ) |
|
{ |
|
addPage( mSpamRulesPage, i18n( "Please select the spam filters to be created inside KMail." )); |
|
checkSpamRulesSelections(); |
|
} |
|
if ( ( mMode == AntiVirus ) && mVirusToolsUsed ) |
|
{ |
|
addPage( mVirusRulesPage, i18n( "Please select the virus filters to be created inside KMail." )); |
|
checkVirusRulesSelections(); |
|
} |
|
|
|
setNextEnabled( mProgramsPage, status ); |
|
} |
|
|
|
|
|
void AntiSpamWizard::checkSpamRulesSelections() |
|
{ |
|
setFinishEnabled( mSpamRulesPage, anySpamOptionChecked() ); |
|
} |
|
|
|
void AntiSpamWizard::checkVirusRulesSelections() |
|
{ |
|
setFinishEnabled( mVirusRulesPage, anyVirusOptionChecked() ); |
|
} |
|
|
|
|
|
void AntiSpamWizard::checkToolAvailability() |
|
{ |
|
KCursorSaver busy(KBusyPtr::busy()); // this can take some time to find the tools |
|
|
|
// checkboxes for the tools |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
QString text( i18n("Scanning for %1...").arg( (*it).getId() ) ); |
|
mInfoPage->setScanProgressText( text ); |
|
KApplication::kApplication()->processEvents( 200 ); |
|
int rc = checkForProgram( (*it).getExecutable() ); |
|
mProgramsPage->setProgramAsFound( (*it).getVisibleName(), !rc ); |
|
} |
|
mInfoPage->setScanProgressText( ( mMode == AntiSpam ) |
|
? i18n("Scanning for anti-spam tools finished.") |
|
: i18n("Scanning for anti-virus tools finished.") ); |
|
setNextEnabled( mInfoPage, true ); |
|
} |
|
|
|
|
|
int AntiSpamWizard::checkForProgram( QString executable ) |
|
{ |
|
kdDebug(5006) << "Testing for executable:" << executable << endl; |
|
KProcess process; |
|
process << executable; |
|
process.setUseShell( true ); |
|
process.start( KProcess::Block ); |
|
return process.exitStatus(); |
|
} |
|
|
|
|
|
void AntiSpamWizard::slotHelpClicked() |
|
{ |
|
if ( mMode == AntiSpam ) |
|
kapp->invokeHelp( "the-anti-spam-wizard", "kmail" ); |
|
else |
|
kapp->invokeHelp( "the-anti-virus-wizard", "kmail" ); |
|
} |
|
|
|
|
|
bool AntiSpamWizard::anySpamOptionChecked() |
|
{ |
|
return ( mSpamRulesPage->moveRulesSelected() |
|
|| mSpamRulesPage->pipeRulesSelected() |
|
|| mSpamRulesPage->classifyRulesSelected() ); |
|
} |
|
|
|
bool AntiSpamWizard::anyVirusOptionChecked() |
|
{ |
|
return ( mVirusRulesPage->moveRulesSelected() |
|
|| mVirusRulesPage->pipeRulesSelected() ); |
|
} |
|
|
|
|
|
//--------------------------------------------------------------------------- |
|
AntiSpamWizard::SpamToolConfig::SpamToolConfig(QString toolId, |
|
int configVersion,QString name, QString exec, |
|
QString url, QString filter, QString detection, QString spam, QString ham, |
|
QString header, QString pattern, bool regExp, bool bayesFilter, WizardMode type) |
|
: mId( toolId ), mVersion( configVersion ), |
|
mVisibleName( name ), mExecutable( exec ), mWhatsThisText( url ), |
|
mFilterName( filter ), mDetectCmd( detection ), mSpamCmd( spam ), |
|
mHamCmd( ham ), mDetectionHeader( header ), mDetectionPattern( pattern ), |
|
mUseRegExp( regExp ), mSupportsBayesFilter( bayesFilter ), mType( type ) |
|
{ |
|
} |
|
|
|
|
|
//--------------------------------------------------------------------------- |
|
AntiSpamWizard::ConfigReader::ConfigReader( WizardMode mode, |
|
QValueList<SpamToolConfig> & configList ) |
|
: mToolList( configList ), |
|
mMode( mode ) |
|
{ |
|
if ( mMode == AntiSpam ) |
|
mConfig = new KConfig( "kmail.antispamrc", true ); |
|
else |
|
mConfig = new KConfig( "kmail.antivirusrc", true ); |
|
} |
|
|
|
AntiSpamWizard::ConfigReader::~ConfigReader( ) |
|
{ |
|
delete mConfig; |
|
} |
|
|
|
|
|
void AntiSpamWizard::ConfigReader::readAndMergeConfig() |
|
{ |
|
QString groupName = ( mMode == AntiSpam ) |
|
? QString("Spamtool #%1") |
|
: QString("Virustool #%1"); |
|
// read the configuration from the global config file |
|
mConfig->setReadDefaults( true ); |
|
KConfigGroup general( mConfig, "General" ); |
|
int registeredTools = general.readNumEntry( "tools", 0 ); |
|
for (int i = 1; i <= registeredTools; i++) |
|
{ |
|
KConfigGroup toolConfig( mConfig, groupName.arg( i ) ); |
|
mToolList.append( readToolConfig( toolConfig ) ); |
|
} |
|
|
|
// read the configuration from the user config file |
|
// and merge newer config data |
|
mConfig->setReadDefaults( false ); |
|
KConfigGroup user_general( mConfig, "General" ); |
|
int user_registeredTools = user_general.readNumEntry( "tools", 0 ); |
|
for (int i = 1; i <= user_registeredTools; i++) |
|
{ |
|
KConfigGroup toolConfig( mConfig, groupName.arg( i ) ); |
|
mergeToolConfig( readToolConfig( toolConfig ) ); |
|
} |
|
// Make sure to have add least one tool listed even when the |
|
// config file was not found or whatever went wrong |
|
// Currently only works for spam tools |
|
if ( mMode == AntiSpam ) { |
|
if ( registeredTools < 1 && user_registeredTools < 1 ) |
|
mToolList.append( createDummyConfig() ); |
|
} |
|
} |
|
|
|
|
|
AntiSpamWizard::SpamToolConfig |
|
AntiSpamWizard::ConfigReader::readToolConfig( KConfigGroup & configGroup ) |
|
{ |
|
QString id = configGroup.readEntry( "Ident" ); |
|
int version = configGroup.readNumEntry( "Version" ); |
|
#ifndef NDEBUG |
|
kdDebug(5006) << "Found predefined tool: " << id << endl; |
|
kdDebug(5006) << "With config version : " << version << endl; |
|
#endif |
|
QString name = configGroup.readEntry( "VisibleName" ); |
|
QString executable = configGroup.readEntry( "Executable" ); |
|
QString url = configGroup.readEntry( "URL" ); |
|
QString filterName = configGroup.readEntry( "PipeFilterName" ); |
|
QString detectCmd = configGroup.readEntry( "PipeCmdDetect" ); |
|
QString spamCmd = configGroup.readEntry( "ExecCmdSpam" ); |
|
QString hamCmd = configGroup.readEntry( "ExecCmdHam" ); |
|
QString header = configGroup.readEntry( "DetectionHeader" ); |
|
QString pattern = configGroup.readEntry( "DetectionPattern" ); |
|
bool useRegExp = configGroup.readBoolEntry( "UseRegExp" ); |
|
bool supportsBayes = configGroup.readBoolEntry( "SupportsBayes", false ); |
|
return SpamToolConfig( id, version, name, executable, url, |
|
filterName, detectCmd, spamCmd, hamCmd, |
|
header, pattern, useRegExp, supportsBayes, mMode ); |
|
} |
|
|
|
|
|
AntiSpamWizard::SpamToolConfig AntiSpamWizard::ConfigReader::createDummyConfig() |
|
{ |
|
return SpamToolConfig( "spamassassin", 0, |
|
"&SpamAssassin", "spamassassin -V", |
|
"http://spamassassin.org", "SpamAssassin Check", |
|
"spamassassin -L", |
|
"sa-learn -L --spam --no-rebuild --single", |
|
"sa-learn -L --ham --no-rebuild --single", |
|
"X-Spam-Flag", "yes", |
|
false, true, AntiSpam ); |
|
} |
|
|
|
|
|
void AntiSpamWizard::ConfigReader::mergeToolConfig( AntiSpamWizard::SpamToolConfig config ) |
|
{ |
|
bool found = false; |
|
for ( QValueListIterator<SpamToolConfig> it = mToolList.begin(); |
|
it != mToolList.end(); ++it ) { |
|
#ifndef NDEBUG |
|
kdDebug(5006) << "Check against tool: " << (*it).getId() << endl; |
|
kdDebug(5006) << "Against version : " << (*it).getVersion() << endl; |
|
#endif |
|
if ( (*it).getId() == config.getId() ) |
|
{ |
|
found = true; |
|
if ( (*it).getVersion() < config.getVersion() ) |
|
{ |
|
#ifndef NDEBUG |
|
kdDebug(5006) << "Replacing config ..." << endl; |
|
#endif |
|
mToolList.remove( it ); |
|
mToolList.append( config ); |
|
} |
|
break; |
|
} |
|
} |
|
if ( !found ) |
|
mToolList.append( config ); |
|
} |
|
|
|
|
|
//--------------------------------------------------------------------------- |
|
ASWizInfoPage::ASWizInfoPage( AntiSpamWizard::WizardMode mode, |
|
QWidget * parent, const char * name ) |
|
: QWidget( parent, name ) |
|
{ |
|
QGridLayout *grid = new QGridLayout( this, 1, 1, KDialog::marginHint(), |
|
KDialog::spacingHint() ); |
|
grid->setColStretch( 1, 10 ); |
|
|
|
mIntroText = new QLabel( this ); |
|
mIntroText->setText( |
|
( mode == AntiSpamWizard::AntiSpam ) |
|
? i18n( |
|
"<p>Here you can get some assistance in setting up KMail's filter " |
|
"rules to use some commonly-known anti-spam tools.</p>" |
|
"<p>The wizard can detect those tools on your computer as " |
|
"well as create filter rules to classify messages using these " |
|
"tools and to separate messages classified as spam. " |
|
"The wizard will not take any existing filter " |
|
"rules into consideration: it will always append the new rules.</p>" |
|
"<p><b>Warning:</b> As KMail is blocked during the scan of the " |
|
"messages for spam, you may encounter problems with " |
|
"the responsiveness of KMail because anti-spam tool " |
|
"operations are usually time consuming; please consider " |
|
"deleting the filter rules created by the wizard to get " |
|
"back to the former behavior." |
|
) |
|
: i18n( |
|
"<p>Here you can get some assistance in setting up KMail's filter " |
|
"rules to use some commonly-known anti-virus tools.</p>" |
|
"<p>The wizard can detect those tools on your computer as " |
|
"well as create filter rules to classify messages using these " |
|
"tools and to separate messages containing viruses. " |
|
"The wizard will not take any existing filter " |
|
"rules into consideration: it will always append the new rules.</p>" |
|
"<p><b>Warning:</b> As KMail is blocked during the scan of the " |
|
"messages for viruses, you may encounter problems with " |
|
"the responsiveness of KMail because anti-virus tool " |
|
"operations are usually time consuming; please consider " |
|
"deleting the filter rules created by the wizard to get " |
|
"back to the former behavior." |
|
) ); |
|
grid->addWidget( mIntroText, 0, 0 ); |
|
|
|
mScanProgressText = new QLabel( this ); |
|
mScanProgressText->setText( "" ) ; |
|
grid->addWidget( mScanProgressText, 1, 0 ); |
|
} |
|
|
|
void ASWizInfoPage::setScanProgressText( const QString &toolName ) |
|
{ |
|
mScanProgressText->setText( toolName ); |
|
} |
|
|
|
//--------------------------------------------------------------------------- |
|
ASWizProgramsPage::ASWizProgramsPage( QWidget * parent, const char * name, |
|
QStringList &checkBoxTextList, |
|
QStringList &checkBoxWhatsThisList ) |
|
: QWidget( parent, name ) |
|
{ |
|
QGridLayout *grid = new QGridLayout( this, 3, 1, KDialog::marginHint(), |
|
KDialog::spacingHint() ); |
|
// checkboxes for the tools |
|
int row = 0; |
|
QStringList::Iterator it1 = checkBoxTextList.begin(); |
|
QStringList::Iterator it2 = checkBoxWhatsThisList.begin(); |
|
while ( it1 != checkBoxTextList.end() ) |
|
{ |
|
QCheckBox *box = new QCheckBox( *it1, this ); |
|
if ( it2 != checkBoxWhatsThisList.end() ) |
|
{ |
|
QWhatsThis::add( box, *it2 ); |
|
QToolTip::add( box, *it2 ); |
|
++it2; |
|
} |
|
grid->addWidget( box, row++, 0 ); |
|
connect( box, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
mProgramDict.insert( *it1, box ); |
|
++it1; |
|
} |
|
|
|
// hint text |
|
QLabel *introText = new QLabel( this ); |
|
introText->setText( i18n( |
|
"<p>For these tools it is possible to let the " |
|
"wizard create filter rules. KMail tried to find the tools " |
|
"in the PATH of your system; the wizard does not allow you " |
|
"to create rules for tools which were not found: " |
|
"this is to keep your configuration consistent and " |
|
"to minimize the risk of unpredicted behavior.</p>" |
|
) ); |
|
grid->addWidget( introText, row++, 0 ); |
|
} |
|
|
|
|
|
bool ASWizProgramsPage::isProgramSelected( const QString &visibleName ) |
|
{ |
|
if ( mProgramDict[visibleName] ) |
|
return mProgramDict[visibleName]->isChecked(); |
|
else |
|
return false; |
|
} |
|
|
|
|
|
void ASWizProgramsPage::setProgramAsFound( const QString &visibleName, bool found ) |
|
{ |
|
QCheckBox * box = mProgramDict[visibleName]; |
|
if ( box ) |
|
{ |
|
QString foundText( i18n("(found on this system)") ); |
|
QString notFoundText( i18n("(not found on this system)") ); |
|
QString labelText = visibleName; |
|
labelText += " "; |
|
if ( found ) |
|
labelText += foundText; |
|
else |
|
{ |
|
labelText += notFoundText; |
|
box->setEnabled( false ); |
|
} |
|
box->setText( labelText ); |
|
} |
|
} |
|
|
|
|
|
void ASWizProgramsPage::processSelectionChange() |
|
{ |
|
emit selectionChanged(); |
|
} |
|
|
|
//--------------------------------------------------------------------------- |
|
ASWizSpamRulesPage::ASWizSpamRulesPage( QWidget * parent, const char * name, |
|
KMFolderTree * mainFolderTree ) |
|
: QWidget( parent, name ) |
|
{ |
|
QGridLayout *grid = new QGridLayout( this, 5, 1, KDialog::marginHint(), |
|
KDialog::spacingHint() ); |
|
|
|
mClassifyRules = new QCheckBox( i18n("Classify messages manually as spam"), this ); |
|
QWhatsThis::add( mClassifyRules, |
|
i18n( "Sometimes messages are classified wrongly or even not at all; " |
|
"the latter might be by intention, because you perhaps filter " |
|
"out messages from mailing lists before you let the anti-spam " |
|
"tools classify the rest of the messages. You can correct these " |
|
"wrong or missing classifications manually by using the " |
|
"appropriate toolbar buttons which trigger special filters " |
|
"created by this wizard." ) ); |
|
grid->addWidget( mClassifyRules, 0, 0 ); |
|
|
|
mPipeRules = new QCheckBox( i18n("Classify messages using the anti-spam tools"), this ); |
|
QWhatsThis::add( mPipeRules, |
|
i18n( "Let the anti-spam tools classify your messages. The wizard " |
|
"will create appropriate filters. The messages are usually " |
|
"marked by the tools so that following filters can react " |
|
"on this and, for example, move spam messages to a special folder.") ); |
|
grid->addWidget( mPipeRules, 1, 0 ); |
|
|
|
mMoveRules = new QCheckBox( i18n("Move detected spam messages to the selected folder"), this ); |
|
QWhatsThis::add( mMoveRules, |
|
i18n( "A filter to detect messages classified as spam and to move " |
|
"those messages into a predefined folder is created. The " |
|
"default folder is the trash folder, but you may change that " |
|
"in the folder view.") ); |
|
grid->addWidget( mMoveRules, 2, 0 ); |
|
|
|
mMarkRules = new QCheckBox( i18n("Additionally, mark detected spam messages as read"), this ); |
|
mMarkRules->setEnabled( false ); |
|
QWhatsThis::add( mMarkRules, |
|
i18n( "Mark messages which have been classified as " |
|
"spam as read, as well as moving them to the selected " |
|
"folder.") ); |
|
grid->addWidget( mMarkRules, 3, 0 ); |
|
|
|
QString s = "trash"; |
|
mFolderTree = new SimpleFolderTree( this, mainFolderTree, s, true ); |
|
grid->addWidget( mFolderTree, 4, 0 ); |
|
|
|
connect( mPipeRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mClassifyRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMoveRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMarkRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMoveRules, SIGNAL( toggled( bool ) ), |
|
mMarkRules, SLOT( setEnabled( bool ) ) ); |
|
} |
|
|
|
bool ASWizSpamRulesPage::pipeRulesSelected() const |
|
{ |
|
return mPipeRules->isChecked(); |
|
} |
|
|
|
|
|
bool ASWizSpamRulesPage::classifyRulesSelected() const |
|
{ |
|
return mClassifyRules->isChecked(); |
|
} |
|
|
|
|
|
bool ASWizSpamRulesPage::moveRulesSelected() const |
|
{ |
|
return mMoveRules->isChecked(); |
|
} |
|
|
|
bool ASWizSpamRulesPage::markReadRulesSelected() const |
|
{ |
|
return mMarkRules->isChecked(); |
|
} |
|
|
|
|
|
QString ASWizSpamRulesPage::selectedFolderName() const |
|
{ |
|
QString name = "trash"; |
|
if ( mFolderTree->folder() ) |
|
name = mFolderTree->folder()->idString(); |
|
return name; |
|
} |
|
|
|
void ASWizSpamRulesPage::processSelectionChange() |
|
{ |
|
emit selectionChanged(); |
|
} |
|
|
|
|
|
void ASWizSpamRulesPage::allowClassification( bool enabled ) |
|
{ |
|
if ( enabled ) |
|
mClassifyRules->setEnabled( true ); |
|
else |
|
{ |
|
mClassifyRules->setChecked( false ); |
|
mClassifyRules->setEnabled( false ); |
|
} |
|
} |
|
|
|
//--------------------------------------------------------------------------- |
|
ASWizVirusRulesPage::ASWizVirusRulesPage( QWidget * parent, const char * name, |
|
KMFolderTree * mainFolderTree ) |
|
: QWidget( parent, name ) |
|
{ |
|
QGridLayout *grid = new QGridLayout( this, 5, 1, KDialog::marginHint(), |
|
KDialog::spacingHint() ); |
|
|
|
mPipeRules = new QCheckBox( i18n("Check messages using the anti-virus tools"), this ); |
|
QWhatsThis::add( mPipeRules, |
|
i18n( "Let the anti-virus tools check your messages. The wizard " |
|
"will create appropriate filters. The messages are usually " |
|
"marked by the tools so that following filters can react " |
|
"on this and, for example, move virus messages to a special folder.") ); |
|
grid->addWidget( mPipeRules, 0, 0 ); |
|
|
|
mMoveRules = new QCheckBox( i18n("Move detected viral messages to the selected folder"), this ); |
|
QWhatsThis::add( mMoveRules, |
|
i18n( "A filter to detect messages classified as virus-infected and to move " |
|
"those messages into a predefined folder is created. The " |
|
"default folder is the trash folder, but you may change that " |
|
"in the folder view.") ); |
|
grid->addWidget( mMoveRules, 1, 0 ); |
|
|
|
mMarkRules = new QCheckBox( i18n("Additionally, mark detected viral messages as read"), this ); |
|
mMarkRules->setEnabled( false ); |
|
QWhatsThis::add( mMarkRules, |
|
i18n( "Mark messages which have been classified as " |
|
"virus-infected as read, as well as moving them " |
|
"to the selected folder.") ); |
|
grid->addWidget( mMarkRules, 2, 0 ); |
|
|
|
QString s = "trash"; |
|
mFolderTree = new SimpleFolderTree( this, mainFolderTree, s, true ); |
|
grid->addWidget( mFolderTree, 3, 0 ); |
|
|
|
connect( mPipeRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMoveRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMarkRules, SIGNAL(clicked()), |
|
this, SLOT(processSelectionChange(void)) ); |
|
connect( mMoveRules, SIGNAL( toggled( bool ) ), |
|
mMarkRules, SLOT( setEnabled( bool ) ) ); |
|
} |
|
|
|
bool ASWizVirusRulesPage::pipeRulesSelected() const |
|
{ |
|
return mPipeRules->isChecked(); |
|
} |
|
|
|
|
|
bool ASWizVirusRulesPage::moveRulesSelected() const |
|
{ |
|
return mMoveRules->isChecked(); |
|
} |
|
|
|
bool ASWizVirusRulesPage::markReadRulesSelected() const |
|
{ |
|
return mMarkRules->isChecked(); |
|
} |
|
|
|
|
|
QString ASWizVirusRulesPage::selectedFolderName() const |
|
{ |
|
QString name = "trash"; |
|
if ( mFolderTree->folder() ) |
|
name = mFolderTree->folder()->idString(); |
|
return name; |
|
} |
|
|
|
void ASWizVirusRulesPage::processSelectionChange() |
|
{ |
|
emit selectionChanged(); |
|
} |
|
|
|
#include "antispamwizard.moc"
|
|
|