Index: trunk/kdepim/kmail/sieveconfig.cpp =================================================================== --- trunk/kdepim/kmail/sieveconfig.cpp (revision 378238) +++ trunk/kdepim/kmail/sieveconfig.cpp (revision 378239) @@ -1,159 +1,159 @@ /* -*- c++ -*- sieveconfig.cpp KMail, the KDE mail client. Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #ifdef HAVE_CONFIG_H #include #endif #include "sieveconfig.h" #include #include #include #include #include #include #include #include namespace KMail { void SieveConfig::readConfig( const KConfigBase & config ) { mManagesieveSupported = config.readBoolEntry( "sieve-support", false ); mReuseConfig = config.readBoolEntry( "sieve-reuse-config", true ); int port = config.readNumEntry( "sieve-port", 2000 ); if ( port < 1 || port > USHRT_MAX ) port = 2000; mPort = static_cast( port ); mAlternateURL = config.readEntry( "sieve-alternate-url" ); - mFileName = config.readEntry( "sieve-filename", "kmail-vacation.siv" ); + mVacationFileName = config.readEntry( "sieve-vacation-filename", "kmail-vacation.siv" ); } void SieveConfig::writeConfig( KConfigBase & config ) const { config.writeEntry( "sieve-support", managesieveSupported() ); config.writeEntry( "sieve-reuse-config", reuseConfig() ); config.writeEntry( "sieve-port", port() ); config.writeEntry( "sieve-alternate-url", mAlternateURL.url() ); - config.writeEntry( "sieve-filename", mFileName ); + config.writeEntry( "sieve-vacation-filename", mVacationFileName ); } SieveConfigEditor::SieveConfigEditor( QWidget * parent, const char * name ) : QWidget( parent, name ) { // tmp. vars: int row = -1; QLabel * label; QGridLayout * glay = new QGridLayout( this, 5, 2, 0, KDialog::spacingHint() ); glay->setRowStretch( 4, 1 ); glay->setColStretch( 1, 1 ); // "Server supports sieve" checkbox: ++row; mManagesieveCheck = new QCheckBox( i18n("&Server supports Sieve"), this ); glay->addMultiCellWidget( mManagesieveCheck, row, row, 0, 1 ); connect( mManagesieveCheck, SIGNAL(toggled(bool)), SLOT(slotEnableWidgets()) ); // "reuse host and login config" checkbox: ++row; mSameConfigCheck = new QCheckBox( i18n("&Reuse host and login configuration"), this ); mSameConfigCheck->setChecked( true ); mSameConfigCheck->setEnabled( false ); glay->addMultiCellWidget( mSameConfigCheck, row, row, 0, 1 ); connect( mSameConfigCheck, SIGNAL(toggled(bool)), SLOT(slotEnableWidgets()) ); // "Managesieve port" spinbox and label: ++row; mPortSpin = new KIntSpinBox( 1, USHRT_MAX, 1, 2000, 10, this ); mPortSpin->setEnabled( false ); label = new QLabel( mPortSpin, i18n("Managesieve &port:"), this ); glay->addWidget( label, row, 0 ); glay->addWidget( mPortSpin, row, 1 ); // "Alternate URL" lineedit and label: ++row; mAlternateURLEdit = new KLineEdit( this ); mAlternateURLEdit->setEnabled( false ); glay->addWidget( new QLabel( mAlternateURLEdit, i18n("&Alternate URL:"), this ), row, 0 ); glay->addWidget( mAlternateURLEdit, row, 1 ); // row 4 is spacer } void SieveConfigEditor::slotEnableWidgets() { bool haveSieve = mManagesieveCheck->isChecked(); bool reuseConfig = mSameConfigCheck->isChecked(); mSameConfigCheck->setEnabled( haveSieve ); mPortSpin->setEnabled( haveSieve && reuseConfig ); mAlternateURLEdit->setEnabled( haveSieve && !reuseConfig ); } bool SieveConfigEditor::managesieveSupported() const { return mManagesieveCheck->isChecked(); } void SieveConfigEditor::setManagesieveSupported( bool enable ) { mManagesieveCheck->setChecked( enable ); } bool SieveConfigEditor::reuseConfig() const { return mSameConfigCheck->isChecked(); } void SieveConfigEditor::setReuseConfig( bool reuse ) { mSameConfigCheck->setChecked( reuse ); } unsigned short SieveConfigEditor::port() const { return static_cast( mPortSpin->value() ); } void SieveConfigEditor::setPort( unsigned short port ) { mPortSpin->setValue( port ); } KURL SieveConfigEditor::alternateURL() const { KURL url ( mAlternateURLEdit->text() ); if ( !url.isValid() ) return KURL(); if ( url.hasPass() ) url.setPass( QString::null ); return url; } void SieveConfigEditor::setAlternateURL( const KURL & url ) { mAlternateURLEdit->setText( url.url() ); } void SieveConfigEditor::setConfig( const SieveConfig & config ) { setManagesieveSupported( config.managesieveSupported() ); setReuseConfig( config.reuseConfig() ); setPort( config.port() ); setAlternateURL( config.alternateURL() ); } } // namespace KMail #include "sieveconfig.moc" Index: trunk/kdepim/kmail/sieveconfig.h =================================================================== --- trunk/kdepim/kmail/sieveconfig.h (revision 378238) +++ trunk/kdepim/kmail/sieveconfig.h (revision 378239) @@ -1,121 +1,121 @@ /* -*- c++ -*- sieveconfig.h KMail, the KDE mail client. Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #ifndef __KMAIL_SIEVECONFIG_H__ #define __KMAIL_SIEVECONFIG_H__ #include #include class QCheckBox; class QLineEdit; class KIntSpinBox; class KConfigBase; namespace KMail { class SieveConfig { public: SieveConfig( bool managesieveSupported=false, bool reuseConfig=true, unsigned int port=2000, const KURL & alternateURL=KURL() ) : mManagesieveSupported( managesieveSupported ), mReuseConfig( reuseConfig ), mPort( port ), mAlternateURL( alternateURL ) {} SieveConfig( const SieveConfig & other ) : mManagesieveSupported( other.managesieveSupported() ), mReuseConfig( other.reuseConfig() ), mPort( other.port() ), mAlternateURL( other.alternateURL() ) {} bool managesieveSupported() const { return mManagesieveSupported; } void setManagesieveSupported( bool enable ) { mManagesieveSupported = enable; } bool reuseConfig() const { return mReuseConfig; } void setReuseConfig( bool reuse ) { mReuseConfig = reuse; } unsigned short port() const { return mPort; } void setPort( unsigned short port ) { mPort = port; } KURL alternateURL() const { return mAlternateURL; } void setAlternateURL( const KURL & url ) { mAlternateURL = url; } - QString fileName() const { return mFileName; } + QString vacationFileName() const { return mVacationFileName; } void readConfig( const KConfigBase & config ); void writeConfig( KConfigBase & config ) const; protected: bool mManagesieveSupported; bool mReuseConfig; unsigned short mPort; KURL mAlternateURL; - QString mFileName; + QString mVacationFileName; }; class SieveConfigEditor : public QWidget { Q_OBJECT public: SieveConfigEditor( QWidget * parent=0, const char * name=0 ); bool managesieveSupported() const; virtual void setManagesieveSupported( bool enable ); bool reuseConfig() const; virtual void setReuseConfig( bool reuse ); unsigned short port() const; virtual void setPort( unsigned short port ); KURL alternateURL() const; virtual void setAlternateURL( const KURL & url ); SieveConfig config() const { return SieveConfig( managesieveSupported(), reuseConfig(), port(), alternateURL() ); } virtual void setConfig( const SieveConfig & config ); protected slots: void slotEnableWidgets(); protected: QCheckBox * mManagesieveCheck; QCheckBox * mSameConfigCheck; KIntSpinBox * mPortSpin; QLineEdit * mAlternateURLEdit; }; } // namespace KMail #endif // __KMAIL_SIEVECONFIG_H__ Index: trunk/kdepim/kmail/vacation.cpp =================================================================== --- trunk/kdepim/kmail/vacation.cpp (revision 378238) +++ trunk/kdepim/kmail/vacation.cpp (revision 378239) @@ -1,416 +1,416 @@ /* -*- c++ -*- vacation.cpp KMail, the KDE mail client. Copyright (c) 2002 Marc Mutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. 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, US */ #ifdef HAVE_CONFIG_H #include #endif #include "vacation.h" #include #include "vacationdialog.h" #include "sievejob.h" using KMail::SieveJob; #include "kmkernel.h" #include "kmacctmgr.h" #include "kmacctimap.h" #include "kmmessage.h" #include #include #include using KMime::Types::AddrSpecList; #include #include #include #include #include #include #include #include namespace { class VacationDataExtractor : public KSieve::ScriptBuilder { enum Context { None = 0, // command itself: VacationCommand, // tagged args: Days, Addresses }; public: VacationDataExtractor() : KSieve::ScriptBuilder(), mContext( None ), mNotificationInterval( 0 ) { kdDebug(5006) << "VacationDataExtractor instantiated" << endl; } virtual ~VacationDataExtractor() {} int notificationInterval() const { return mNotificationInterval; } const QString & messageText() const { return mMessageText; } const QStringList & aliases() const { return mAliases; } private: void commandStart( const QString & identifier ) { kdDebug( 5006 ) << "VacationDataExtractor::commandStart( \"" << identifier << "\" )" << endl; if ( identifier != "vacation" ) return; reset(); mContext = VacationCommand; } void commandEnd() { kdDebug( 5006 ) << "VacationDataExtractor::commandEnd()" << endl; mContext = None; } void testStart( const QString & ) {} void testEnd() {} void testListStart() {} void testListEnd() {} void blockStart() {} void blockEnd() {} void hashComment( const QString & ) {} void bracketComment( const QString & ) {} void lineFeed() {} void error( const KSieve::Error & e ) { kdDebug( 5006 ) << "VacationDataExtractor::error() ### " << e.asString() << " @ " << e.line() << "," << e.column() << endl; } void finished() {} void taggedArgument( const QString & tag ) { kdDebug( 5006 ) << "VacationDataExtractor::taggedArgument( \"" << tag << "\" )" << endl; if ( mContext != VacationCommand ) return; if ( tag == "days" ) mContext = Days; else if ( tag == "addresses" ) mContext = Addresses; } void stringArgument( const QString & string, bool, const QString & ) { kdDebug( 5006 ) << "VacationDataExtractor::stringArgument( \"" << string << "\" )" << endl; if ( mContext == Addresses ) { mAliases.push_back( string ); mContext = VacationCommand; } else if ( mContext == VacationCommand ) { mMessageText = string; mContext = VacationCommand; } } void numberArgument( unsigned long number, char ) { kdDebug( 5006 ) << "VacationDataExtractor::numberArgument( \"" << number << "\" )" << endl; if ( mContext != Days ) return; if ( number > INT_MAX ) mNotificationInterval = INT_MAX; else mNotificationInterval = number; mContext = VacationCommand; } void stringListArgumentStart() {} void stringListEntry( const QString & string, bool, const QString & ) { kdDebug( 5006 ) << "VacationDataExtractor::stringListEntry( \"" << string << "\" )" << endl; if ( mContext != Addresses ) return; mAliases.push_back( string ); } void stringListArgumentEnd() { kdDebug( 5006 ) << "VacationDataExtractor::stringListArgumentEnd()" << endl; if ( mContext != Addresses ) return; mContext = VacationCommand; } private: Context mContext; int mNotificationInterval; QString mMessageText; QStringList mAliases; void reset() { kdDebug(5006) << "VacationDataExtractor::reset()" << endl; mContext = None; mNotificationInterval = 0; mAliases.clear(); mMessageText = QString::null; } }; } namespace KMail { Vacation::Vacation( QObject * parent, const char * name ) : QObject( parent, name ), mSieveJob( 0 ), mDialog( 0 ), mWasActive( false ) { mUrl = findURL(); kdDebug(5006) << "Vacation: found url \"" << mUrl.prettyURL() << "\"" << endl; if ( mUrl.isEmpty() ) // nothing to do... return; mSieveJob = SieveJob::get( mUrl ); connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)), SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) ); } Vacation::~Vacation() { if ( mSieveJob ) mSieveJob->kill(); mSieveJob = 0; delete mDialog; mDialog = 0; kdDebug(5006) << "~Vacation()" << endl; } static inline QString dotstuff( QString s ) { if ( s.startsWith( "." ) ) return '.' + s.replace( "\n.", "\n.." ); else return s.replace( "\n.", "\n.." ); } QString Vacation::composeScript( const QString & messageText, int notificationInterval, const AddrSpecList & addrSpecs ) { QString addressesArgument; QStringList aliases; if ( !addrSpecs.empty() ) { addressesArgument += ":addresses [ "; QStringList sl; for ( AddrSpecList::const_iterator it = addrSpecs.begin() ; it != addrSpecs.end() ; ++it ) { sl.push_back( '"' + (*it).asString().replace( '\\', "\\\\" ).replace( '"', "\\\"" ) + '"' ); aliases.push_back( (*it).asString() ); } addressesArgument += sl.join( ", " ) + " ] "; } QString script = QString::fromLatin1("require \"vacation\";\n" "\n" "vacation "); script += addressesArgument; if ( notificationInterval > 0 ) script += QString::fromLatin1(":days %1 ").arg( notificationInterval ); script += QString::fromLatin1("text:\n"); script += dotstuff( messageText.isEmpty() ? defaultMessageText() : messageText ); script += QString::fromLatin1( "\n.\n;\n" ); return script; } static KURL findUrlForAccount( const KMail::ImapAccountBase * a ) { assert( a ); SieveConfig sieve = a->sieveConfig(); if ( !sieve.managesieveSupported() ) return KURL(); if ( sieve.reuseConfig() ) { // assemble Sieve url from the settings of the account: KURL u; u.setProtocol( "sieve" ); u.setHost( a->host() ); u.setUser( a->login() ); u.setPass( a->passwd() ); u.setPort( sieve.port() ); u.setQuery( "x-mech=" + (a->auth() == "*" ? "PLAIN" : a->auth()) ); //translate IMAP LOGIN to PLAIN - u.setFileName( sieve.fileName() ); + u.setFileName( sieve.vacationFileName() ); return u; } else { KURL u = sieve.alternateURL(); - u.setFileName( sieve.fileName() ); + u.setFileName( sieve.vacationFileName() ); return u; } } KURL Vacation::findURL() const { KMAcctMgr * am = kmkernel->acctMgr(); assert( am ); for ( KMAccount * a = am->first() ; a ; a = am->next() ) if ( KMail::ImapAccountBase * iab = dynamic_cast( a ) ) { KURL u = findUrlForAccount( iab ); if ( !u.isEmpty() ) return u; } return KURL(); } bool Vacation::parseScript( const QString & script, QString & messageText, int & notificationInterval, QStringList & aliases ) { if ( script.stripWhiteSpace().isEmpty() ) { messageText = defaultMessageText(); notificationInterval = defaultNotificationInterval(); aliases = defaultMailAliases(); return true; } // The stripWhiteSpace() call below prevents parsing errors. The // slave somehow omits the last \n, which results in a lone \r at // the end, leading to a parse error. const QCString scriptUTF8 = script.stripWhiteSpace().utf8(); kdDebug(5006) << "scriptUtf8 = \"" + scriptUTF8 + "\"" << endl; KSieve::Parser parser( scriptUTF8.begin(), scriptUTF8.begin() + scriptUTF8.length() ); VacationDataExtractor vdx; parser.setScriptBuilder( &vdx ); if ( !parser.parse() ) return false; messageText = vdx.messageText().stripWhiteSpace(); notificationInterval = vdx.notificationInterval(); aliases = vdx.aliases(); return true; } QString Vacation::defaultMessageText() { return i18n("I am out of office till %1.\n" "\n" "In urgent cases, please contact Mrs. \n" "\n" "email: \n" "phone: +49 711 1111 11\n" "fax.: +49 711 1111 12\n" "\n" "Yours sincerely,\n" "-- \n") .arg( KGlobal::locale()->formatDate( QDate::currentDate().addDays( 1 ) ) ); } int Vacation::defaultNotificationInterval() { return 7; // days } QStringList Vacation::defaultMailAliases() { QStringList sl; for ( KPIM::IdentityManager::ConstIterator it = kmkernel->identityManager()->begin() ; it != kmkernel->identityManager()->end() ; ++it ) if ( !(*it).emailAddr().isEmpty() ) sl.push_back( (*it).emailAddr() ); return sl; } void Vacation::slotGetResult( SieveJob * job, bool success, const QString & script, bool active ) { kdDebug(5006) << "Vacation::slotGetResult( ??, " << success << ", ?, " << active << " )" << endl << "script:" << endl << script << endl; mSieveJob = 0; // job deletes itself after returning from this slot! if ( mUrl.protocol() == "sieve" && !job->sieveCapabilities().isEmpty() && !job->sieveCapabilities().contains("vacation") ) { KMessageBox::sorry( 0, i18n("Your server did not list \"vacation\" in " "its list of supported Sieve extensions;\n" "without it, KMail cannot install out-of-" "office replies for you.\n" "Please contact you system administrator.") ); emit result( false ); return; } if ( !mDialog ) mDialog = new VacationDialog( i18n("Configure \"Out of Office\" Replies"), 0, 0, false ); QString messageText = defaultMessageText(); int notificationInterval = defaultNotificationInterval(); QStringList aliases = defaultMailAliases(); if ( !success ) active = false; // default to inactive if ( !success || !parseScript( script, messageText, notificationInterval, aliases ) ) KMessageBox::information( 0, i18n("Someone (probably you) changed the " "vacation script on the server.\n" "KMail is no longer able to determine " "the parameters for the autoreplies.\n" "Default values will be used." ) ); mWasActive = active; mDialog->setActivateVacation( active ); mDialog->setMessageText( messageText ); mDialog->setNotificationInterval( notificationInterval ); mDialog->setMailAliases( aliases.join(", ") ); connect( mDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) ); connect( mDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCancel()) ); connect( mDialog, SIGNAL(defaultClicked()), SLOT(slotDialogDefaults()) ); mDialog->show(); } void Vacation::slotDialogDefaults() { if ( !mDialog ) return; mDialog->setActivateVacation( true ); mDialog->setMessageText( defaultMessageText() ); mDialog->setNotificationInterval( defaultNotificationInterval() ); mDialog->setMailAliases( defaultMailAliases().join(", ") ); } void Vacation::slotDialogOk() { kdDebug(5006) << "Vacation::slotDialogOk()" << endl; // compose a new script: const QString script = composeScript( mDialog->messageText(), mDialog->notificationInterval(), mDialog->mailAliases() ); const bool active = mDialog->activateVacation(); kdDebug(5006) << "script:" << endl << script << endl; // and commit the dialog's settings to the server: mSieveJob = SieveJob::put( mUrl, script, active, mWasActive ); connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)), active ? SLOT(slotPutActiveResult(KMail::SieveJob*,bool)) : SLOT(slotPutInactiveResult(KMail::SieveJob*,bool)) ); // destroy the dialog: mDialog->delayedDestruct(); mDialog = 0; } void Vacation::slotDialogCancel() { kdDebug(5006) << "Vacation::slotDialogCancel()" << endl; mDialog->delayedDestruct(); mDialog = 0; emit result( false ); } void Vacation::slotPutActiveResult( SieveJob * job, bool success ) { handlePutResult( job, success, true ); } void Vacation::slotPutInactiveResult( SieveJob * job, bool success ) { handlePutResult( job, success, false ); } void Vacation::handlePutResult( SieveJob *, bool success, bool activated ) { if ( success ) KMessageBox::information( 0, activated ? i18n("Sieve script installed successfully on the server.\n" "Out of Office reply is now active.") : i18n("Sieve script installed successfully on the server.\n" "Out of Office reply has been deactivated.") ); kdDebug(5006) << "Vacation::handlePutResult( ???, " << success << ", ? )" << endl; mSieveJob = 0; // job deletes itself after returning from this slot! emit result( success ); } } // namespace KMail #include "vacation.moc"