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.
1759 lines
47 KiB
1759 lines
47 KiB
11 years ago
|
/***************************************************************************
|
||
|
ConfigElem.cpp - description
|
||
|
-------------------
|
||
|
begin : Tue May 9 2000
|
||
|
copyright : (C) 2000-2001 by Eggert Ehmke
|
||
|
email : eggert.ehmke@berlin.de
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "configelem.h"
|
||
|
|
||
|
int const ConfigElem::continueShowHeaders( 0 );
|
||
|
int const ConfigElem::cancelShowHeaders( 1 );
|
||
|
|
||
|
|
||
|
ConfigElem::ConfigElem( ) : QObject()
|
||
|
{
|
||
|
//initialize account
|
||
|
init();
|
||
|
|
||
|
//set default values
|
||
|
m_url.setProtocol( "pop3" );
|
||
|
m_url.setPort( 110 );
|
||
|
m_bActive = false;
|
||
|
appConfig = NULL;
|
||
|
m_strAccount = "";
|
||
|
}
|
||
|
|
||
|
ConfigElem::ConfigElem( ConfigList* config ) : QObject()
|
||
|
{
|
||
|
//initialize account
|
||
|
init();
|
||
|
|
||
|
m_url.setProtocol( "pop3" );
|
||
|
m_url.setPort (110);
|
||
|
|
||
|
m_bActive = false;
|
||
|
|
||
|
appConfig = config;
|
||
|
|
||
|
}
|
||
|
|
||
|
ConfigElem::ConfigElem( ConfigElem* pElem ) : QObject()
|
||
|
{
|
||
|
//initialize account
|
||
|
init();
|
||
|
|
||
|
//set active by default
|
||
|
m_bActive = pElem->isActive();
|
||
|
|
||
|
//copy some interesting stuff from the sample
|
||
|
//the url object contains all necessary information about the server
|
||
|
m_strAccount = pElem->getAccountName();
|
||
|
m_url = pElem->getURL();
|
||
|
appConfig = pElem->appConfig;
|
||
|
|
||
|
}
|
||
|
|
||
|
ConfigElem::ConfigElem( ConfigList* config, const QString& account ) : QObject()
|
||
|
{
|
||
|
//initialize account
|
||
|
init();
|
||
|
|
||
|
//set account name
|
||
|
m_strAccount = account;
|
||
|
|
||
|
//deactivate it by default
|
||
|
m_bActive = false;
|
||
|
|
||
|
//set the pointer to the general app configuration
|
||
|
appConfig = config;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::init( )
|
||
|
{
|
||
|
//initialize timeout timer
|
||
|
pop3Timer = new QTimer( this );
|
||
|
connect( pop3Timer, SIGNAL( timeout() ), this, SLOT( slotTimeout() ) );
|
||
|
|
||
|
//state is idle
|
||
|
state = AccountIdle;
|
||
|
|
||
|
//create new empty mail list
|
||
|
m_pshowrecord = new ShowRecord();
|
||
|
|
||
|
//the account has no appropriate account list view item yet
|
||
|
m_pViewItem = NULL;
|
||
|
|
||
|
//set default values
|
||
|
PasswordStorage = DEFAULT_ACCOUNT_PASSWORD_STORAGE;
|
||
|
filterApplied = false;
|
||
|
deletionPerformedByFilters = false;
|
||
|
refreshPerformedByFilters = false;
|
||
|
downloadActionsInvoked = false;
|
||
|
|
||
|
//initialize counters
|
||
|
moveCounter = 0;
|
||
|
nmbDeletedMailsLastRefresh = 0;
|
||
|
nmbDeletedMailsLastStart = 0;
|
||
|
nmbMovedMailsLastRefresh = 0;
|
||
|
nmbMovedMailsLastStart = 0;
|
||
|
nmbIgnoredMails = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
ConfigElem::~ConfigElem()
|
||
|
{
|
||
|
// do not delete m_pshowrecord here
|
||
|
}
|
||
|
|
||
|
void ConfigElem::saveOptions( QDomDocument& doc, QDomElement& parent )
|
||
|
{
|
||
|
//get application config
|
||
|
KConfig* config = KApplication::kApplication()->config();
|
||
|
|
||
|
//save the active state
|
||
|
config->setGroup( getAccountName() );
|
||
|
config->writeEntry( CONFIG_ENTRY_ACCOUNT_ACTIVE, m_bActive );
|
||
|
config->sync();
|
||
|
|
||
|
//save the stored mails inside this account
|
||
|
parent.setAttribute( ATTRIBUTE_ACCOUNT_NAME, m_strAccount );
|
||
|
m_pshowrecord->saveOptions( doc, parent );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::readStoredMails( QDomElement& parent )
|
||
|
{
|
||
|
//get mails
|
||
|
m_pshowrecord->readStoredMails( parent );
|
||
|
}
|
||
|
|
||
|
|
||
|
int ConfigElem::count()
|
||
|
{
|
||
|
return m_pshowrecord->count();
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::isActive( ) const
|
||
|
{
|
||
|
return m_bActive;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setActive( bool active )
|
||
|
{
|
||
|
m_bActive = active;
|
||
|
}
|
||
|
|
||
|
QString ConfigElem::getAccountName( ) const
|
||
|
{
|
||
|
return m_strAccount;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setAccountName( QString name )
|
||
|
{
|
||
|
if( name != NULL )
|
||
|
m_strAccount = name;
|
||
|
}
|
||
|
|
||
|
QString ConfigElem::getPassword( ) const
|
||
|
{
|
||
|
return m_url.pass();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setPassword( const QString& password )
|
||
|
{
|
||
|
m_url.setPass( password );
|
||
|
}
|
||
|
|
||
|
KURL ConfigElem::getURL( ) const
|
||
|
{
|
||
|
return m_url;
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::hasPassword( ) const
|
||
|
{
|
||
|
return m_url.hasPass();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setListViewItem( QListViewItem* item )
|
||
|
{
|
||
|
m_pViewItem = item;
|
||
|
}
|
||
|
|
||
|
QListViewItem * ConfigElem::getListViewItem( )
|
||
|
{
|
||
|
return m_pViewItem;
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::isSelected( ) const
|
||
|
{
|
||
|
if( m_pViewItem == NULL )
|
||
|
|
||
|
return false;
|
||
|
|
||
|
else
|
||
|
|
||
|
return m_pViewItem->isSelected();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::clearMailList( )
|
||
|
{
|
||
|
if( m_pshowrecord == NULL )
|
||
|
//there is no mail list yet, create a one
|
||
|
m_pshowrecord = new ShowRecord;
|
||
|
else
|
||
|
//clear the existing mail list
|
||
|
m_pshowrecord->clear();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setHost( const QString& host )
|
||
|
{
|
||
|
m_url.setHost( host );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setProtocol( const QString& protocol )
|
||
|
{
|
||
|
m_url.setProtocol( protocol );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setPort( unsigned short int port )
|
||
|
{
|
||
|
m_url.setPort( port );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setUser( const QString & user )
|
||
|
{
|
||
|
m_url.setUser( user );
|
||
|
}
|
||
|
|
||
|
QString ConfigElem::getUser( ) const
|
||
|
{
|
||
|
return m_url.user();
|
||
|
}
|
||
|
|
||
|
QString ConfigElem::getHost( ) const
|
||
|
{
|
||
|
return m_url.host();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::deleteSelectedMails( )
|
||
|
{
|
||
|
//return if this account has no selected mails or
|
||
|
//the account is not idle or the account is not active
|
||
|
if( !m_pshowrecord->hasSelectedMails() || state != AccountIdle || !isActive() )
|
||
|
{
|
||
|
emit sigDeleteReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//check whether we have a password for this account
|
||
|
//if not, ask for it
|
||
|
//return when no password is available
|
||
|
if( !assertPassword() )
|
||
|
{
|
||
|
emit sigDeleteReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//get the numbers of all selected mails
|
||
|
MailsToDelete = m_pshowrecord->getSelectedMails();
|
||
|
if( MailsToDelete.empty() )
|
||
|
{
|
||
|
kdError() << "ConfigElem::deleteSelectedMails (Account " << m_strAccount << "): The account has selected mails to delete but ShowRecord::getSelectedMails has returned an empty list." << endl;
|
||
|
emit sigDeleteReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//set account state
|
||
|
state = AccountDeleting;
|
||
|
|
||
|
//start the deleting of all mails in MailsToDelete
|
||
|
deleteNextMail();
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::assertPassword( bool force )
|
||
|
{
|
||
|
//is a password stored?
|
||
|
if ( !hasPassword() || force )
|
||
|
{
|
||
|
//no password found, we will ask the user!
|
||
|
//set normal cursor
|
||
|
while( QApplication::overrideCursor() )
|
||
|
QApplication::restoreOverrideCursor();
|
||
|
|
||
|
QCString password; //for the password dialog to store the password
|
||
|
int result = KPasswordDialog::getPassword( password, i18n( "Please type in the password for %1" ).arg( getAccountName() ) );
|
||
|
|
||
|
//set waiting cursor
|
||
|
QApplication::setOverrideCursor( Qt::waitCursor );
|
||
|
|
||
|
//let's look, what the user has done :o)
|
||
|
if( result == KPasswordDialog::Accepted )
|
||
|
{
|
||
|
//the user has clicked OK in the password dialog
|
||
|
//store the password
|
||
|
setPassword( password );
|
||
|
|
||
|
//save password in file or KWallet
|
||
|
KConfig* config = KApplication::kApplication()->config();
|
||
|
config->setGroup( getAccountName() );
|
||
|
|
||
|
if( PasswordStorage == CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_FILE )
|
||
|
config->writeEntry( CONFIG_ENTRY_ACCOUNT_PASSWORD, crypt( m_url ) );
|
||
|
else
|
||
|
config->writeEntry( CONFIG_ENTRY_ACCOUNT_PASSWORD, QString::null );
|
||
|
|
||
|
if( PasswordStorage == CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_KWALLET )
|
||
|
KWalletAccess::savePassword( getAccountName(), m_url.pass() );
|
||
|
|
||
|
config->sync();
|
||
|
|
||
|
//emit configuration changed signal
|
||
|
emit ( sigConfigChanged() );
|
||
|
|
||
|
//tell we have a password
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
//the user has clicked Cancel in the password dialog; we don't have a password
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
//we have already a password for this account
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::deleteNextMail( )
|
||
|
{
|
||
|
//if the list of mails to delete is empty, finalize the deletion and return
|
||
|
if( MailsToDelete.empty() )
|
||
|
{
|
||
|
if( deletionPerformedByFilters )
|
||
|
{
|
||
|
applyFiltersDeleted();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
commitDeletion();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/remove/%1" ).arg( *MailsToDelete.begin() ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotMailDeleted( KIO::Job* ) ) );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotMailDeleted( KIO::Job* job )
|
||
|
{
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error is occured, the deletion will be canceled
|
||
|
//or will ask for a new password
|
||
|
if( job->error() == KIO::ERR_COULD_NOT_LOGIN )
|
||
|
{
|
||
|
//login failed, ask for a new password
|
||
|
job->showErrorDialog();
|
||
|
bool res = assertPassword( true );
|
||
|
if( res == false )
|
||
|
{
|
||
|
//we have not got a new password; cancel delete
|
||
|
if( deletionPerformedByFilters )
|
||
|
{
|
||
|
applyFiltersDeleted();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
slotFinalizeDeletion( NULL );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
//if we have got a new password, it jumps to the end of the if-statement
|
||
|
}
|
||
|
else if( job->error() != 0 )
|
||
|
{
|
||
|
//unknown error, show message and cancel delete
|
||
|
job->showErrorDialog();
|
||
|
if( deletionPerformedByFilters )
|
||
|
{
|
||
|
applyFiltersDeleted();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
slotFinalizeDeletion( NULL );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//operation was successful
|
||
|
//remove the deleted mail from the internal mail list
|
||
|
m_pshowrecord->removeMail( *MailsToDelete.begin() );
|
||
|
|
||
|
//remove the first item of the list of mails to delete
|
||
|
MailsToDelete.remove( MailsToDelete.begin() );
|
||
|
|
||
|
//if the list of mails to delete is empty, finalize the deletion and return
|
||
|
if( MailsToDelete.empty() )
|
||
|
{
|
||
|
if( deletionPerformedByFilters )
|
||
|
{
|
||
|
applyFiltersDeleted();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
commitDeletion();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//delete next mail in list
|
||
|
deleteNextMail();
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotFinalizeDeletion( KIO::Job* )
|
||
|
{
|
||
|
//stop timeout time
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//set account state to idle
|
||
|
state = AccountIdle;
|
||
|
|
||
|
//emit signal to report the deletion is ready
|
||
|
emit sigDeleteReady( m_strAccount );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::startKIOJob( const QString & path )
|
||
|
{
|
||
|
KIO::MetaData options; //options for the pop3 job
|
||
|
|
||
|
//set options
|
||
|
options.insert( "progress", "off" );
|
||
|
options.insert( "pipelining", "off" );
|
||
|
|
||
|
if( useTLS )
|
||
|
options.insert( "tls", "on" );
|
||
|
else
|
||
|
options.insert( "tls", "off" );
|
||
|
|
||
|
//Where is secure login?
|
||
|
//I have decided against a configurable secure login because the used POP3 kioslave
|
||
|
//always tries to login with APOP, if the server has sent a timestap (inside of the greeting string) for this authentification type.
|
||
|
//It just follows the auth-metadata, if the server doesn't support APOP (no timestamp inside of the greeting string).
|
||
|
//But I think, there is no server, which support a SASL authentification without also provide APOP.
|
||
|
//Ulrich Weigelt
|
||
|
|
||
|
//set the given command and parameters
|
||
|
m_url.setPath( path );
|
||
|
|
||
|
//print debug message
|
||
|
kdDebug() << "ConfigElem::startKIOJob: start KIO job on URL " << m_url.url() << endl;
|
||
|
|
||
|
//start the job and get handle to it
|
||
|
pop3Job = KIO::get( m_url, false, false );
|
||
|
|
||
|
//put options to the job
|
||
|
pop3Job->addMetaData( options );
|
||
|
|
||
|
//start timeout timer
|
||
|
pop3Timer->start( getTimeoutTime() * 1000, true );
|
||
|
}
|
||
|
|
||
|
Types::AccountState_Type ConfigElem::getState( )
|
||
|
{
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::commitDeletion( )
|
||
|
{
|
||
|
//start job to commit
|
||
|
startKIOJob( QString( "/commit" ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotFinalizeDeletion( KIO::Job* ) ) );
|
||
|
}
|
||
|
|
||
|
unsigned int ConfigElem::getTimeoutTime( )
|
||
|
{
|
||
|
//return default time, if the configuration is not accessable
|
||
|
if( appConfig == NULL )
|
||
|
return DEFAULT_TIMEOUT_TIME;
|
||
|
|
||
|
//get time from configuration
|
||
|
unsigned int time = appConfig->getTimeoutTime();
|
||
|
|
||
|
//take minimum time, if get time is less
|
||
|
if( time < MINIMUM_TIMEOUT_TIME )
|
||
|
time = MINIMUM_TIMEOUT_TIME;
|
||
|
|
||
|
return time;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotTimeout( )
|
||
|
{
|
||
|
//kill a running job
|
||
|
if( pop3Job != NULL )
|
||
|
pop3Job->kill( true );
|
||
|
|
||
|
//show error message (during refresh if desired only)
|
||
|
kdError() << "Timeout error!" << endl;
|
||
|
|
||
|
if( state != AccountRefreshing || appConfig->showConnectionErrors() )
|
||
|
KMessageBox::error( NULL, QString( i18n( "Time out on %1. The operation could not be finished on time" ) ).arg( m_strAccount ), i18n( "Time Out" ) );
|
||
|
|
||
|
//call the appropriate finalize methode
|
||
|
switch( state )
|
||
|
{
|
||
|
case AccountIdle : break;
|
||
|
case AccountDeleting : slotFinalizeDeletion( NULL ); break;
|
||
|
case AccountDownloading : slotFinalizeShowMail( NULL ); break;
|
||
|
case AccountRefreshing : cancelRefresh(); break;
|
||
|
|
||
|
default : break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QStringList ConfigElem::getSelectedSubjects( ) const
|
||
|
{
|
||
|
return m_pshowrecord->getSelectedSubjects();
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::hasSelectedMails( )
|
||
|
{
|
||
|
return m_pshowrecord->hasSelectedMails();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::showSelectedMails( )
|
||
|
{
|
||
|
//return if this account has no selected mails or
|
||
|
//the account is not idle or the account is not active
|
||
|
if( !m_pshowrecord->hasSelectedMails() || state != AccountIdle || !isActive() )
|
||
|
{
|
||
|
emit sigShowBodiesReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//check whether we have a password for this account
|
||
|
//if not, ask for it
|
||
|
//return when no password is available
|
||
|
if( !assertPassword() )
|
||
|
{
|
||
|
emit sigShowBodiesReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//get the numbers of all selected mails
|
||
|
MailsToShow = m_pshowrecord->getSelectedMails();
|
||
|
if( MailsToShow.empty() )
|
||
|
{
|
||
|
kdError() << "ConfigElem::showSelectedMails (Account " << m_strAccount << "): The account has selected mails to show but ShowRecord::getSelectedMails has returned an empty list." << endl;
|
||
|
emit sigShowBodiesReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//set account state
|
||
|
state = AccountDownloading;
|
||
|
|
||
|
//start the deleting of all mails in MailsToDelete
|
||
|
showNextMail();
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::showNextMail( )
|
||
|
{
|
||
|
//if the list of mails to show is empty, finalize it and return
|
||
|
if( MailsToShow.empty() )
|
||
|
{
|
||
|
slotFinalizeShowMail( NULL );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//clear the class variable mailbody, which contains the downloaded mail body
|
||
|
mailbody.resize( 0 );
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/download/%1" ).arg( *MailsToShow.begin() ) );
|
||
|
connect( pop3Job, SIGNAL( data( KIO::Job*, const QByteArray & ) ), SLOT( slotDataMailBody( KIO::Job*, const QByteArray & ) ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotBodyDownloaded( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotBodyDownloaded( KIO::Job * job )
|
||
|
{
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error has occured, the download will be canceled
|
||
|
//or will ask for a new password
|
||
|
if( job->error() == KIO::ERR_COULD_NOT_LOGIN )
|
||
|
{
|
||
|
//login failed, ask for a new password
|
||
|
job->showErrorDialog();
|
||
|
bool res = assertPassword( true );
|
||
|
if( res == false )
|
||
|
{
|
||
|
//we have not got a new password; cancel delete
|
||
|
slotFinalizeShowMail( NULL );
|
||
|
return;
|
||
|
}
|
||
|
//if we have got a new password, jump to the end of the if-statement
|
||
|
}
|
||
|
else if( job->error() != 0 )
|
||
|
{
|
||
|
job->showErrorDialog();
|
||
|
slotFinalizeShowMail( NULL );
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//succesful download
|
||
|
//show mail
|
||
|
int currentMail = *MailsToShow.begin();
|
||
|
QString tsender = m_pshowrecord->getSenderOf( currentMail );
|
||
|
QString tdate = m_pshowrecord->getDateOf( currentMail );
|
||
|
QString tsize = m_pshowrecord->getSizeOf( currentMail );
|
||
|
QString tsubject = m_pshowrecord->getSubjectOf( currentMail );
|
||
|
QString tmailbody( m_pshowrecord->decodeMailBody( mailbody, currentMail, appConfig->allowHTML() ) );
|
||
|
|
||
|
//emit signal to notify the opening of a window
|
||
|
emit sigMessageWindowOpened();
|
||
|
|
||
|
//create and open the window
|
||
|
ShowMailDialog dlg( kapp->mainWidget(), m_strAccount, appConfig->allowHTML(), tsender, tdate, tsize, tsubject, tmailbody );
|
||
|
int ret = dlg.exec();
|
||
|
|
||
|
//emit signal to notify the closing of a window
|
||
|
emit sigMessageWindowClosed();
|
||
|
|
||
|
//cancel the download if desired
|
||
|
if( ret == KDialogBase::Rejected )
|
||
|
{
|
||
|
MailsToShow.clear();
|
||
|
commitDownloading();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//remove the first item of the list of mails to show
|
||
|
MailsToShow.remove( MailsToShow.begin() );
|
||
|
|
||
|
//if the list of mails is empty, finalize the showing and return
|
||
|
if( MailsToShow.empty() )
|
||
|
{
|
||
|
commitDownloading();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//show next mail in list
|
||
|
showNextMail();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotFinalizeShowMail( KIO::Job* )
|
||
|
{
|
||
|
//stop timeout time
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//set account state to idle
|
||
|
state = AccountIdle;
|
||
|
|
||
|
//emit signal to report the download is ready
|
||
|
emit sigShowBodiesReady( m_strAccount );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotDataMailBody( KIO::Job *, const QByteArray & datas )
|
||
|
{
|
||
|
if( !datas.isEmpty() )
|
||
|
{
|
||
|
//we get the next part of the mail
|
||
|
//append it
|
||
|
uint lastSize = mailbody.size();
|
||
|
mailbody.resize( lastSize + datas.size() );
|
||
|
for( uint i = 0; i < datas.size(); i++ )
|
||
|
mailbody[ lastSize + i ] = datas[ i ];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ConfigElem::commitDownloading( )
|
||
|
{
|
||
|
//start job to commit
|
||
|
startKIOJob( QString( "/commit" ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotFinalizeShowMail( KIO::Job* ) ) );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::refreshMailList( FilterLog* log )
|
||
|
{
|
||
|
//store pointer to log
|
||
|
if( log != NULL )
|
||
|
FLog = log;
|
||
|
|
||
|
//return, if account is not active
|
||
|
if( !isActive() )
|
||
|
{
|
||
|
emit sigRefreshReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//check whether we have a password for this account
|
||
|
//if not, ask for it
|
||
|
//return when no password is available
|
||
|
if( !assertPassword() )
|
||
|
{
|
||
|
emit sigRefreshReady( m_strAccount );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//create a new ShowRecord instance
|
||
|
//When the refresh has finished successfully, this will
|
||
|
//replace the old mail list
|
||
|
tempMailList = new ShowRecord();
|
||
|
|
||
|
//set account state
|
||
|
state = AccountRefreshing;
|
||
|
|
||
|
//init counter
|
||
|
if( !refreshPerformedByFilters )
|
||
|
{
|
||
|
nmbDeletedMailsLastRefresh = 0;
|
||
|
nmbMovedMailsLastRefresh = 0;
|
||
|
nmbIgnoredMails = 0;
|
||
|
}
|
||
|
|
||
|
//the first step is to get the UIDs
|
||
|
getUIDs();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::getUIDs( )
|
||
|
{
|
||
|
//clears the QString list, which contains all received UIDs
|
||
|
receivedUIDs.clear();
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/uidl" ) );
|
||
|
connect( pop3Job, SIGNAL( data( KIO::Job*, const QByteArray & ) ), SLOT( slotReceiveUID( KIO::Job*, const QByteArray & ) ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotUIDsReceived( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotReceiveUID( KIO::Job*, const QByteArray& data )
|
||
|
{
|
||
|
//return, when data is empty
|
||
|
if( data.isEmpty() ) return;
|
||
|
|
||
|
//cast the data to QString
|
||
|
QString uid( data );
|
||
|
|
||
|
//insert the uid at the end of the UID list
|
||
|
receivedUIDs.append( uid );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotUIDsReceived( KIO::Job * job )
|
||
|
{
|
||
|
int number; //an extracted mail number
|
||
|
QString uid; //an extracted uid
|
||
|
bool corruptData = false; //set to TRUE, if a data is corrupt
|
||
|
bool isNew = false; //state of the received mail
|
||
|
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error has occured, the refresh will be canceled
|
||
|
//or will ask for a new password
|
||
|
if( job->error() == KIO::ERR_COULD_NOT_LOGIN )
|
||
|
{
|
||
|
//login failed, ask for a new password
|
||
|
job->showErrorDialog();
|
||
|
bool res = assertPassword( true );
|
||
|
if( res == true )
|
||
|
{
|
||
|
//we have got a new password, try again
|
||
|
delete tempMailList;
|
||
|
refreshMailList();
|
||
|
}
|
||
|
else
|
||
|
//we have not got a new password; cancel refresh
|
||
|
cancelRefresh();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
else if( job->error() != 0 )
|
||
|
{
|
||
|
//show error message if desired
|
||
|
if( appConfig->showConnectionErrors() )
|
||
|
job->showErrorDialog();
|
||
|
|
||
|
cancelRefresh();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//analyze UIDs
|
||
|
if( !receivedUIDs.isEmpty() )
|
||
|
{
|
||
|
//iterate over all UIDs in the list
|
||
|
for ( QStringList::Iterator it = receivedUIDs.begin(); it != receivedUIDs.end(); ++it )
|
||
|
{
|
||
|
QString line = *it;
|
||
|
|
||
|
//every line has the format "number UID", e.g.: 1 bf10d38018de7c1d628d65288d722f6a
|
||
|
//get the position of the separating space
|
||
|
int positionOfSpace = line.find( " " );
|
||
|
|
||
|
//if no space was found, the line is corrupt
|
||
|
if( positionOfSpace == -1 )
|
||
|
{
|
||
|
kdError() << "ConfigElem::slotUIDsReceived: get a corrupt UID from " << dynamic_cast<KIO::SimpleJob*>(job)->url().host() << ". No space. : " << line << endl;
|
||
|
corruptData = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//extract mail number and uid
|
||
|
bool isNumber;
|
||
|
number = line.left( positionOfSpace ).toInt( &isNumber );
|
||
|
//check number
|
||
|
if( !isNumber )
|
||
|
{
|
||
|
//the first part is not a number
|
||
|
kdError() << "ConfigElem::slotUIDsReceived: get a corrupt UID from " << dynamic_cast<KIO::SimpleJob*>(job)->url().host() << ". No number found at begin. : " << line << endl;
|
||
|
corruptData = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//number is ok; extract uid
|
||
|
uid = line.mid( positionOfSpace + 1 );
|
||
|
|
||
|
//determine about new mail or not
|
||
|
if( !m_pshowrecord->hasMail( uid ) )
|
||
|
{
|
||
|
//the old list doesn't contain a mail with this uid
|
||
|
//the mail is new
|
||
|
isNew = true;
|
||
|
}
|
||
|
else if( ( appConfig->keepNew() || refreshPerformedByFilters ) && m_pshowrecord->isNew( uid ) )
|
||
|
{
|
||
|
//the mail is already in the old list
|
||
|
//but we will leave the state of formerly new mails, because the user wants it or this refresh is performed by filters
|
||
|
isNew = true;
|
||
|
}
|
||
|
else
|
||
|
isNew = false;
|
||
|
|
||
|
//append mail to the list
|
||
|
tempMailList->appendNewMail( number, uid, isNew );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//if the data are ok, start the second step: get sizes
|
||
|
//otherwise cancel the refresh
|
||
|
if( !corruptData )
|
||
|
getSizes();
|
||
|
else
|
||
|
cancelRefresh();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//we haven't received any UIDs. The account has no mails.
|
||
|
//finalize the refresh
|
||
|
swapMailLists();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::cancelRefresh()
|
||
|
{
|
||
|
//print error message
|
||
|
kdError() << m_strAccount << ": " << "Refresh canceled" << endl;
|
||
|
|
||
|
//delete the new mail list
|
||
|
delete tempMailList;
|
||
|
|
||
|
//delete old mail list and create a new empty one
|
||
|
delete m_pshowrecord;
|
||
|
m_pshowrecord = new ShowRecord();
|
||
|
|
||
|
//emit signal
|
||
|
emit sigRefreshReady( m_strAccount );
|
||
|
|
||
|
//set account state to idle
|
||
|
state = AccountIdle;
|
||
|
|
||
|
//we don't need an error message, because the KIO job has shown one
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotFinalizeRefresh( KIO::Job* )
|
||
|
{
|
||
|
//stop timeout time
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//unset the flag
|
||
|
refreshPerformedByFilters = false;
|
||
|
|
||
|
//emit signal
|
||
|
emit sigRefreshReady( m_strAccount );
|
||
|
|
||
|
//set account state to idle
|
||
|
state = AccountIdle;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::commitRefresh( )
|
||
|
{
|
||
|
//start job to commit
|
||
|
startKIOJob( QString( "/commit" ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotFinalizeRefresh( KIO::Job* ) ) );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::getSizes( )
|
||
|
{
|
||
|
//clears the QString list, which contains all received UIDs
|
||
|
receivedSizes.clear();
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/index" ) );
|
||
|
connect( pop3Job, SIGNAL( data( KIO::Job*, const QByteArray & ) ), SLOT( slotReceiveSize( KIO::Job*, const QByteArray & ) ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotSizesReceived( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotSizesReceived( KIO::Job * job )
|
||
|
{
|
||
|
int number; //an extracted mail number
|
||
|
long size; //an extracted size
|
||
|
bool corruptData = false; //set to TRUE, if a data is corrupt
|
||
|
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error has occured, the refresh will be canceled
|
||
|
if( job->error() != 0 )
|
||
|
{
|
||
|
//show error message if desired
|
||
|
if( appConfig->showConnectionErrors() )
|
||
|
job->showErrorDialog();
|
||
|
cancelRefresh();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//analyze UIDs
|
||
|
if( !receivedSizes.isEmpty() )
|
||
|
{
|
||
|
//iterate over all sizes in the list
|
||
|
for ( QStringList::Iterator it = receivedSizes.begin(); it != receivedSizes.end(); ++it )
|
||
|
{
|
||
|
QString line = *it;
|
||
|
|
||
|
//every line has the format "number size", e.g.: 1 1234
|
||
|
//get the position of the separating space
|
||
|
int positionOfSpace = line.find( " " );
|
||
|
|
||
|
//if no space was found, the line is corrupt
|
||
|
if( positionOfSpace == -1 )
|
||
|
{
|
||
|
kdError() << "ConfigElem::slotSizesReceived: get a corrupt size from " << dynamic_cast<KIO::SimpleJob*>(job)->url().host() << ". No space. : " << line << endl;
|
||
|
corruptData = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//extract mail number and size
|
||
|
bool isNumber;
|
||
|
number = line.left( positionOfSpace ).toInt( &isNumber );
|
||
|
//check number
|
||
|
if( !isNumber )
|
||
|
{
|
||
|
//the first part is not a number
|
||
|
kdError() << "ConfigElem::slotSizesReceived: get a corrupt size from " << dynamic_cast<KIO::SimpleJob*>(job)->url().host() << ". No number found at begin. : " << line << endl;
|
||
|
corruptData = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//number is ok; extract size
|
||
|
size = line.mid( positionOfSpace + 1 ).toLong( &isNumber );
|
||
|
|
||
|
//check size
|
||
|
if( !isNumber )
|
||
|
{
|
||
|
//the second part of the string is not a number
|
||
|
kdError() << "ConfigElem::slotSizesReceived: get a corrupt size from " << dynamic_cast<KIO::SimpleJob*>(job)->url().host() << ". No size found at end. : " << line << endl;
|
||
|
corruptData = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//size is ok
|
||
|
//set it
|
||
|
tempMailList->setSize( number, size );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//if the data are ok, start the third step: get headers
|
||
|
//otherwise cancel the refresh
|
||
|
if( !corruptData )
|
||
|
getHeaders();
|
||
|
else
|
||
|
cancelRefresh();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotReceiveSize( KIO::Job *, const QByteArray & data )
|
||
|
{
|
||
|
//return, when data is empty
|
||
|
if( data.isEmpty() ) return;
|
||
|
|
||
|
//cast the data to QString
|
||
|
QString size( data );
|
||
|
|
||
|
//insert the uid at the end of the sizes list
|
||
|
receivedSizes.append( size );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::getHeaders( )
|
||
|
{
|
||
|
//get the numbers of all new mails
|
||
|
newMails = tempMailList->getNewMails();
|
||
|
if( newMails.empty() )
|
||
|
{
|
||
|
//no new mails available; copy the known headers from the old mail list
|
||
|
copyHeaders();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//get the headers
|
||
|
getNextHeader();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::getNextHeader( )
|
||
|
{
|
||
|
//if the list of mails empty, copy the known headers from the old mail list
|
||
|
if( newMails.empty() )
|
||
|
{
|
||
|
copyHeaders();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//clear temporary header store
|
||
|
receivedHeader.resize( 0 );
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/headers/%1" ).arg( *newMails.begin() ) );
|
||
|
connect( pop3Job, SIGNAL( data( KIO::Job*, const QByteArray & ) ), this, SLOT( slotReceiveHeader( KIO::Job*, const QByteArray & ) ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotHeaderDownloaded( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotHeaderDownloaded( KIO::Job * job )
|
||
|
{
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error is occured, the download will be canceled
|
||
|
if( job->error() != 0 )
|
||
|
{
|
||
|
//show error message if desired
|
||
|
if( appConfig->showConnectionErrors() )
|
||
|
job->showErrorDialog();
|
||
|
|
||
|
cancelRefresh();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//store header
|
||
|
tempMailList->setHeader( *newMails.begin(), QString( receivedHeader ) );
|
||
|
|
||
|
//remove the first item of the list of new mails
|
||
|
newMails.remove( newMails.begin() );
|
||
|
|
||
|
//if the list of new mails is empty, copy the headers of old mails to the new list
|
||
|
if( newMails.empty() )
|
||
|
{
|
||
|
copyHeaders();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//get next header
|
||
|
getNextHeader();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::copyHeaders( )
|
||
|
{
|
||
|
//get the UIDs of the old mails in the temporary mail list
|
||
|
QStringList UIDs = tempMailList->getUIDsOfOldMails();
|
||
|
|
||
|
//iterate over all members of the list,
|
||
|
//get the header from the old list and store it in the new one
|
||
|
QStringList::iterator it;
|
||
|
for ( it = UIDs.begin(); it != UIDs.end(); ++it )
|
||
|
{
|
||
|
QString header = m_pshowrecord->getHeaderOf( *it );
|
||
|
tempMailList->setHeader( *it, header );
|
||
|
}
|
||
|
|
||
|
//now we have the a complete new mail list
|
||
|
swapMailLists();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotReceiveHeader( KIO::Job *, const QByteArray & data )
|
||
|
{
|
||
|
if( !data.isEmpty() )
|
||
|
{
|
||
|
//we get the next part of the mail
|
||
|
//append it
|
||
|
uint lastSize = receivedHeader.size();
|
||
|
receivedHeader.resize( lastSize + data.size() );
|
||
|
for( uint i = 0; i < data.size(); i++ )
|
||
|
receivedHeader[ lastSize + i ] = data[ i ];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ConfigElem::getNumberNewMails( )
|
||
|
{
|
||
|
return m_pshowrecord->getNumberNewMails();
|
||
|
}
|
||
|
|
||
|
int ConfigElem::getNumberMails( )
|
||
|
{
|
||
|
return m_pshowrecord->getNumberMails();
|
||
|
}
|
||
|
|
||
|
long ConfigElem::getTotalSize( )
|
||
|
{
|
||
|
return m_pshowrecord->getTotalSize();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::fillMailListView( KshowmailView* view )
|
||
|
{
|
||
|
m_pshowrecord->fillMailListView( view, m_strAccount );
|
||
|
}
|
||
|
|
||
|
void ConfigElem::refreshAccountListItem( )
|
||
|
{
|
||
|
if( m_pViewItem != NULL )
|
||
|
{
|
||
|
if( isActive() )
|
||
|
{
|
||
|
m_pViewItem->setText( 4, QString( "%1" ).arg( getNumberMails(), 3 ) );
|
||
|
m_pViewItem->setText( 5, QString( "%1" ).arg( getTotalSize(), 8 ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pViewItem->setText( 4, QString( "???" ) );
|
||
|
m_pViewItem->setText( 5, QString( "???" ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ConfigElem::killPOP3Job( )
|
||
|
{
|
||
|
//just try to kill, if it is not idle
|
||
|
if( state != AccountIdle )
|
||
|
{
|
||
|
//kill a running job
|
||
|
if( pop3Job != NULL )
|
||
|
pop3Job->kill( true );
|
||
|
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//call the appropriate finalize method
|
||
|
switch( state )
|
||
|
{
|
||
|
case AccountDeleting : slotFinalizeDeletion( NULL ); break;
|
||
|
case AccountDownloading : slotFinalizeShowMail( NULL ); break;
|
||
|
case AccountRefreshing : cancelRefresh(); break;
|
||
|
|
||
|
default : break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ConfigElem::showSelectedHeaders( )
|
||
|
{
|
||
|
//return, if no mails are selected
|
||
|
if( !hasSelectedMails() )
|
||
|
return ConfigElem::continueShowHeaders;
|
||
|
|
||
|
//order the mail list to show the headers of the selected mails
|
||
|
int ret = m_pshowrecord->showSelectedHeaders( m_strAccount );
|
||
|
|
||
|
return ret == ShowRecord::continueShowHeaders ? ConfigElem::continueShowHeaders : ConfigElem::cancelShowHeaders;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::printSetup( ) const
|
||
|
{
|
||
|
kdDebug() << "Setup of " << m_strAccount << ":" << endl;
|
||
|
kdDebug() << "Host: " << m_url.host() << endl;
|
||
|
kdDebug() << "Protocol: " << m_url.protocol() << endl;
|
||
|
kdDebug() << "Port: " << m_url.port() << endl;
|
||
|
kdDebug() << "User: " << m_url.user() << endl;
|
||
|
kdDebug() << "Password: " << m_url.pass() << endl;
|
||
|
|
||
|
switch( PasswordStorage )
|
||
|
{
|
||
|
case CONFIG_VALUE_ACCOUNT_PASSWORD_DONT_SAVE : kdDebug() << "Password Storage: don't save" << endl; break;
|
||
|
case CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_FILE : kdDebug() << "Password Storage: save in file" << endl; break;
|
||
|
case CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_KWALLET : kdDebug() << "Password Storage: use KWallet" << endl; break;
|
||
|
default : kdDebug() << "Password Storage: invalid value" << endl;
|
||
|
|
||
|
}
|
||
|
|
||
|
kdDebug() << "active: " << m_bActive << endl << endl;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setPasswordStorage( int storage )
|
||
|
{
|
||
|
if( storage == CONFIG_VALUE_ACCOUNT_PASSWORD_DONT_SAVE ||
|
||
|
storage == CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_FILE ||
|
||
|
storage == CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_KWALLET )
|
||
|
|
||
|
PasswordStorage = storage;
|
||
|
|
||
|
else
|
||
|
|
||
|
PasswordStorage = DEFAULT_ACCOUNT_PASSWORD_STORAGE;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::getPasswordStorage( ) const
|
||
|
{
|
||
|
return PasswordStorage;
|
||
|
}
|
||
|
|
||
|
QString ConfigElem::getProtocol( bool upperCase ) const
|
||
|
{
|
||
|
if( upperCase )
|
||
|
return m_url.protocol().upper();
|
||
|
else
|
||
|
return m_url.protocol();
|
||
|
}
|
||
|
|
||
|
unsigned short int ConfigElem::getPort( ) const
|
||
|
{
|
||
|
return m_url.port();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::setTLS( bool tls )
|
||
|
{
|
||
|
useTLS = tls;
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::getTLS( ) const
|
||
|
{
|
||
|
return useTLS;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::reloadFilterSettings( )
|
||
|
{
|
||
|
headerFilter.load();
|
||
|
}
|
||
|
|
||
|
void ConfigElem::applyFilters( )
|
||
|
{
|
||
|
//are we executed by the MOVE routines?
|
||
|
if( !downloadActionsInvoked )
|
||
|
{
|
||
|
//this is the first call (at the current refresh cycle) of this methode
|
||
|
//we get the lists of mails to delete an move and call the MOVE routines if necessary
|
||
|
|
||
|
//OK, the filters were applied
|
||
|
filterApplied = true;
|
||
|
|
||
|
//order the mail list to apply the header filters
|
||
|
//it returns lists of mail numbers which shall be deleted or moved
|
||
|
//the marking will be done by the mail list itself
|
||
|
//the mail list removes all mails which shall be ignored itself
|
||
|
MailsToDelete.clear();
|
||
|
m_pshowrecord->applyHeaderFilter( &headerFilter, getAccountName(), MailsToDelete, MailsToDownload, nmbIgnoredMails, FLog );
|
||
|
nmbDeletedMailsLastRefresh += MailsToDelete.count();
|
||
|
nmbDeletedMailsLastStart += MailsToDelete.count();
|
||
|
|
||
|
//This part will be executed, if mails shall be downloaded
|
||
|
if( !MailsToDownload.empty() )
|
||
|
{
|
||
|
downloadActionsInvoked = true;
|
||
|
doDownloadActions();
|
||
|
|
||
|
//we quit this methode at this point, because after the bodies are downloaded and written this methode will recalled.
|
||
|
//At this time the else branch of this IF-statement will be executed and the methode continues
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//this is the second call (at the current refresh cycle) of this methode.
|
||
|
//it is called by the Move routines.
|
||
|
//the downloading of the mailbodies and writing it to the mailboxes has ended.
|
||
|
//A second call was just exceuted, if there was mails to move
|
||
|
downloadActionsInvoked = false;
|
||
|
|
||
|
//after an move error there are maybe some mails leftover in MailsToMove
|
||
|
MailsToDownload.clear();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//we have get the list of mails to delete and the all mails to move are written to its mailboxes
|
||
|
//now we delete this mails (the moved mails too)
|
||
|
|
||
|
if( !MailsToDelete.empty() )
|
||
|
{
|
||
|
//there are mails to delete
|
||
|
//we delete they
|
||
|
//after the delete cycle has done its job, it will call applyFiltersDeleted()
|
||
|
deletionPerformedByFilters = true; //this is set to indicate the deletion is performed by filters and not by user
|
||
|
//the deletion methodes need it to decide on branch targets
|
||
|
deleteNextMail();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//if we need not to start a second refresh cycle (no mails was deleted or moved)
|
||
|
//we just commit the refresh and let the filter applied flag to false for the next regular refresh
|
||
|
commitRefresh();
|
||
|
filterApplied = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ConfigElem::swapMailLists( )
|
||
|
{
|
||
|
//delete old mail list
|
||
|
delete m_pshowrecord;
|
||
|
|
||
|
//assign the new list
|
||
|
if( tempMailList != NULL )
|
||
|
m_pshowrecord = tempMailList;
|
||
|
else
|
||
|
m_pshowrecord = new ShowRecord();
|
||
|
|
||
|
//if the filters were not applied yet, we do it now
|
||
|
//applyFilters() will either start a second refresh cycle if it did some deletions
|
||
|
//or call commitRefresh() to commit the refresh cycle.
|
||
|
//if the filters were already applied we commit the refresh.
|
||
|
if( filterApplied | !headerFilter.isActive() )
|
||
|
{
|
||
|
commitRefresh();
|
||
|
filterApplied = false;
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ConfigElem::applyFiltersDeleted( )
|
||
|
{
|
||
|
//unset the flag
|
||
|
deletionPerformedByFilters = false;
|
||
|
|
||
|
//start the second refresh cycle
|
||
|
refreshPerformedByFilters = true;
|
||
|
|
||
|
//this sends a commit and restart the refresh
|
||
|
commitBeforeRefresh();
|
||
|
return;
|
||
|
//refreshMailList();
|
||
|
}
|
||
|
|
||
|
|
||
|
bool ConfigElem::writeToMailBox( const QString & mail, const QString & box )
|
||
|
{
|
||
|
QDir mailDir( box );
|
||
|
|
||
|
//check whether the given path is a maildir
|
||
|
if( !isMailDir( mailDir ) )
|
||
|
{
|
||
|
//show an error message
|
||
|
KMessageBox::error( NULL, i18n( QString( "%1 is not a mailbox." ).arg( box ) ) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//create unique file name according http://cr.yp.to/proto/maildir.html
|
||
|
QString partTime = QString::number( time( NULL ) ); //left part, output of time()
|
||
|
|
||
|
char hname[256]; //right part, the hostname
|
||
|
QString partHostname;
|
||
|
if( gethostname( hname, 255 ) == 0 )
|
||
|
partHostname = QString( hname );
|
||
|
else
|
||
|
{
|
||
|
//the hostname is not readable
|
||
|
//show an error message and exit
|
||
|
KMessageBox::error( NULL, i18n( QString( "Can't read the hostname of your computer. But KShowmail need it to write a mail into the mailbox." ) ) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
QString partPID = QString::number( getpid() ); //middle part, the PID
|
||
|
|
||
|
QString partCounter = QString::number( moveCounter++ );
|
||
|
|
||
|
QString uniqueName( partTime + "." + partPID + partCounter + "." + partHostname );
|
||
|
|
||
|
//build absolute path
|
||
|
mailDir.cd( "tmp" );
|
||
|
QString absFile = mailDir.filePath( uniqueName );
|
||
|
|
||
|
//and writing!
|
||
|
QFile file( absFile );
|
||
|
if( file.open( IO_WriteOnly ) )
|
||
|
{
|
||
|
QTextStream stream( &file );
|
||
|
stream << mail << endl;
|
||
|
file.close();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
KMessageBox::detailedError( NULL, i18n( QString( "Could not file a mail to %1." ) ).arg( box ), i18n( file.errorString() ) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//now we move it to the "new" subdirectory
|
||
|
mailDir.cdUp();
|
||
|
mailDir.cd( "new" );
|
||
|
QString absNewFile = mailDir.filePath( uniqueName );
|
||
|
|
||
|
if( rename( absFile.ascii(), absNewFile.ascii() ) == -1 )
|
||
|
{
|
||
|
KMessageBox::error( NULL, i18n( QString( "Could not move a mail from %1 to %2." ) ).arg( absFile ).arg( absNewFile ) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//the writing was successful
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::doDownloadActions()
|
||
|
{
|
||
|
//get first mail
|
||
|
getNextMailForDownloadActions();
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::isMailDir( const QDir & path )
|
||
|
{
|
||
|
//get a list of all subdirectories in this directory
|
||
|
const QStringList entries = path.entryList( QDir::Dirs | QDir::Readable | QDir::Writable | QDir::Hidden, QDir::Name | QDir::IgnoreCase | QDir::LocaleAware );
|
||
|
|
||
|
//a maildir folder must contains the folders "cur", "new" and "tmp"
|
||
|
bool curFound = false;
|
||
|
bool newFound = false;
|
||
|
bool tmpFound = false;
|
||
|
|
||
|
//iterate over all directories and look for the three necessary dirs
|
||
|
QStringList::const_iterator it = entries.begin();
|
||
|
while( it != entries.end() && !( curFound && newFound && tmpFound ) )
|
||
|
{
|
||
|
if( *it == "tmp" )
|
||
|
tmpFound = true;
|
||
|
else if( *it == "cur" )
|
||
|
curFound = true;
|
||
|
else if( *it == "new" )
|
||
|
newFound = true;
|
||
|
|
||
|
++it;
|
||
|
}
|
||
|
|
||
|
return curFound && newFound && tmpFound;
|
||
|
}
|
||
|
|
||
|
void ConfigElem::getNextMailForDownloadActions()
|
||
|
{
|
||
|
//if the list of mails to move is empty return to applyFilters
|
||
|
if( MailsToDownload.empty() )
|
||
|
{
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//clear the class variable mailbody, which contains the downloaded mail body
|
||
|
mailbody.resize( 0 );
|
||
|
|
||
|
//start job
|
||
|
startKIOJob( QString( "/download/%1" ).arg( MailsToDownload.begin().key() ) );
|
||
|
connect( pop3Job, SIGNAL( data( KIO::Job*, const QByteArray & ) ), SLOT( slotDataMailBody( KIO::Job*, const QByteArray & ) ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotMailDownloadedForAction( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotMailDownloadedForAction(KIO::Job * job)
|
||
|
{
|
||
|
//stop timeout timer
|
||
|
pop3Timer->stop();
|
||
|
|
||
|
//check for errors
|
||
|
//if an error has occured, the download will be canceled
|
||
|
//or will ask for a new password
|
||
|
if( job->error() == KIO::ERR_COULD_NOT_LOGIN )
|
||
|
{
|
||
|
//login failed, ask for a new password
|
||
|
job->showErrorDialog();
|
||
|
bool res = assertPassword( true );
|
||
|
if( res == false )
|
||
|
{
|
||
|
//we have not got a new password; cancel delete
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
//if we have got a new password, jump to the end of the if-statement
|
||
|
}
|
||
|
else if( job->error() != 0 )
|
||
|
{
|
||
|
job->showErrorDialog();
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//succesful download
|
||
|
//do action
|
||
|
MailToDownloadMap_Type::Iterator firstMail = MailsToDownload.begin();
|
||
|
int currentMailNumber = firstMail.key(); //get mail number
|
||
|
QString currentMailBox( firstMail.data().mailbox ); //get mailbox
|
||
|
QString mail( mailbody ); //convert mailtext
|
||
|
FilterAction_Type action = firstMail.data().action; //get action
|
||
|
|
||
|
bool resultMove = false; //TRUE - mail is written into the mailbox
|
||
|
bool resultSpam = false; //TRUE - mail is Spam
|
||
|
bool deleteIt = false; //TRUE - mail shall be deleted
|
||
|
bool resultAction = false; //True - the action was succesful performed
|
||
|
|
||
|
switch( action )
|
||
|
{
|
||
|
case FActMove : resultMove = writeToMailBox( mail, currentMailBox );
|
||
|
//log entry is made by ShowRecordElem::applyHeaderFilter
|
||
|
if( resultMove == true )
|
||
|
{
|
||
|
nmbMovedMailsLastRefresh++;
|
||
|
nmbMovedMailsLastStart++;
|
||
|
|
||
|
resultAction = true;
|
||
|
deleteIt = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
resultAction = false;
|
||
|
deleteIt = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case FActSpamcheck : resultSpam = isSpam( mailbody ); //it is spam?
|
||
|
if( resultSpam == true ) //yes, it is spam! Arrgghh! Torture it!!!
|
||
|
{
|
||
|
switch( appConfig->getSpamAction() )
|
||
|
{
|
||
|
case FActMove : resultMove = writeToMailBox( mail, appConfig->getSpamMailbox() );
|
||
|
if( resultMove == true )
|
||
|
{
|
||
|
nmbMovedMailsLastRefresh++;
|
||
|
nmbMovedMailsLastStart++;
|
||
|
|
||
|
if( FLog != NULL )
|
||
|
m_pshowrecord->writeToMoveLog( FLog, currentMailNumber, getAccountName(), appConfig->getSpamMailbox() );
|
||
|
resultAction = true;
|
||
|
deleteIt = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
resultAction = false;
|
||
|
deleteIt = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case FActMark : m_pshowrecord->setMarkAtNextViewRefresh( currentMailNumber );
|
||
|
resultAction = true;
|
||
|
deleteIt = false;
|
||
|
break;
|
||
|
|
||
|
case FActDelete : if( FLog != NULL )
|
||
|
m_pshowrecord->writeToDeleteLog( FLog, currentMailNumber, getAccountName() );
|
||
|
|
||
|
nmbDeletedMailsLastRefresh++;
|
||
|
nmbDeletedMailsLastStart++;
|
||
|
resultAction = true;
|
||
|
deleteIt = true;
|
||
|
break;
|
||
|
|
||
|
default : kdError() << "invalid action for spam mail" << endl;
|
||
|
resultAction = false;
|
||
|
deleteIt = false;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else //mail is not spam
|
||
|
{
|
||
|
resultAction = true;
|
||
|
deleteIt = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default : deleteIt = false;
|
||
|
resultAction = false;
|
||
|
|
||
|
}
|
||
|
|
||
|
if( resultAction == true )
|
||
|
{
|
||
|
//Action was successful
|
||
|
//remove this mail from the list
|
||
|
MailsToDownload.remove( firstMail );
|
||
|
|
||
|
//maybe add this mail to list of mails to delete
|
||
|
if( deleteIt )
|
||
|
MailsToDelete.append( currentMailNumber );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Action was not successful
|
||
|
//returns to applyFilters() to continue the filtering
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
//if the list of mails is empty, return to applyFilters() to continue the filtering
|
||
|
if( MailsToDownload.empty() )
|
||
|
{
|
||
|
applyFilters();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//show next mail in list
|
||
|
getNextMailForDownloadActions();
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::isSpam( QByteArray mail ) const
|
||
|
{
|
||
|
//check for a running spamassassin
|
||
|
if( !isSpamAssassinRunning() )
|
||
|
{
|
||
|
KMessageBox::information( NULL, i18n( "You want to check your mails for spam, but SpamAssassin is not running.\nKShowmail skips the spam check." ), i18n( "SpamAssassin is not running" ), "ConfigElemNoSpamAssassinRunning" );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//append an \0 at the end of the string
|
||
|
int size = mail.size();
|
||
|
if( mail[ size - 1 ] != '\0' )
|
||
|
{
|
||
|
mail.resize( size + 1 );
|
||
|
mail[ size ] = '\0';
|
||
|
}
|
||
|
|
||
|
//calls spmac and get an file pointer to stdin of it
|
||
|
FILE *write_fp;
|
||
|
write_fp = popen( "spamc -E", "w" );
|
||
|
|
||
|
//forward the mail to SpamAssassin
|
||
|
if( write_fp != NULL )
|
||
|
{
|
||
|
fwrite( mail.data(), sizeof( char), mail.size(), write_fp );
|
||
|
|
||
|
//check exit code of spamc and return result
|
||
|
int excode = pclose( write_fp );
|
||
|
if( excode == 0 )
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kdError() << "Could not call the command spamc of SpamAssassin." << endl;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool ConfigElem::isSpamAssassinRunning( ) const
|
||
|
{
|
||
|
FILE *read_fp;
|
||
|
char buffer[ BUFSIZ + 1 ];
|
||
|
int chars_read;
|
||
|
bool found = false;
|
||
|
|
||
|
memset( buffer, '\0', sizeof( buffer ) );
|
||
|
read_fp = popen( "ps -eo comm", "r" );
|
||
|
if( read_fp != NULL )
|
||
|
{
|
||
|
chars_read = fread( buffer, sizeof( char ), BUFSIZ, read_fp );
|
||
|
while( chars_read > 0 )
|
||
|
{
|
||
|
buffer[ chars_read - 1 ] = '\0';
|
||
|
QString output( buffer );
|
||
|
found = output.contains( NAME_SPAMASSASSIN_DAEMON ) > 0;
|
||
|
chars_read = fread( buffer, sizeof( char ), BUFSIZ, read_fp );
|
||
|
}
|
||
|
pclose( read_fp );
|
||
|
}
|
||
|
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::numberDeletedMailsLastRefresh( )
|
||
|
{
|
||
|
return nmbDeletedMailsLastRefresh;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::numberDeletedMailsStart( )
|
||
|
{
|
||
|
return nmbDeletedMailsLastStart;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::numberMovedMailsLastRefresh( )
|
||
|
{
|
||
|
return nmbMovedMailsLastRefresh;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::numberMovedMailsStart( )
|
||
|
{
|
||
|
return nmbMovedMailsLastStart;
|
||
|
}
|
||
|
|
||
|
int ConfigElem::numberIgnoredMails( )
|
||
|
{
|
||
|
return nmbIgnoredMails;
|
||
|
}
|
||
|
|
||
|
QStringList ConfigElem::getSelectedSenders( ) const
|
||
|
{
|
||
|
return m_pshowrecord->getSelectedSenders();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void ConfigElem::commitBeforeRefresh()
|
||
|
{
|
||
|
//start job to commit
|
||
|
startKIOJob( QString( "/commit" ) );
|
||
|
connect( pop3Job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotCommitBeforeRefreshDone( KIO::Job* ) ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
void ConfigElem::slotCommitBeforeRefreshDone(KIO::Job *)
|
||
|
{
|
||
|
//after a commit was send, we start a new refresh cyle
|
||
|
refreshMailList();
|
||
|
}
|