00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036
00037 #include "vacation.h"
00038 #include <limits.h>
00039
00040 #include "vacationdialog.h"
00041 #include "sievejob.h"
00042 using KMail::SieveJob;
00043 #include "kmkernel.h"
00044 #include "kmacctmgr.h"
00045 #include "kmacctimap.h"
00046 #include "kmmessage.h"
00047 #include "globalsettings.h"
00048 #include <libkpimidentities/identitymanager.h>
00049 #include <libkpimidentities/identity.h>
00050
00051 #include <kmime_header_parsing.h>
00052 using KMime::Types::AddrSpecList;
00053
00054 #include <ksieve/parser.h>
00055 #include <ksieve/scriptbuilder.h>
00056 #include <ksieve/error.h>
00057
00058 #include <klocale.h>
00059 #include <kmessagebox.h>
00060 #include <kdebug.h>
00061
00062 #include <qdatetime.h>
00063
00064 #include <cassert>
00065 #include <vector>
00066 #include <map>
00067 #include <set>
00068
00069 namespace KSieveExt {
00070
00071 class MultiScriptBuilder : public KSieve::ScriptBuilder {
00072 std::vector<KSieve::ScriptBuilder*> mBuilders;
00073 public:
00074 MultiScriptBuilder() : KSieve::ScriptBuilder() {}
00075 MultiScriptBuilder( KSieve::ScriptBuilder * sb1 )
00076 : KSieve::ScriptBuilder(), mBuilders( 1 )
00077 {
00078 mBuilders[0] = sb1;
00079 assert( sb1 );
00080 }
00081 MultiScriptBuilder( KSieve::ScriptBuilder * sb1,
00082 KSieve::ScriptBuilder * sb2 )
00083 : KSieve::ScriptBuilder(), mBuilders( 2 )
00084 {
00085 mBuilders[0] = sb1;
00086 mBuilders[1] = sb2;
00087 assert( sb1 ); assert( sb2 );
00088 }
00089 MultiScriptBuilder( KSieve::ScriptBuilder * sb1,
00090 KSieve::ScriptBuilder * sb2,
00091 KSieve::ScriptBuilder * sb3 )
00092 : KSieve::ScriptBuilder(), mBuilders( 3 )
00093 {
00094 mBuilders[0] = sb1;
00095 mBuilders[1] = sb2;
00096 mBuilders[2] = sb3;
00097 assert( sb1 ); assert( sb2 ); assert( sb3 );
00098 }
00099 ~MultiScriptBuilder() {}
00100 private:
00101 #ifdef FOREACH
00102 #undef FOREACH
00103 #endif
00104 #define FOREACH for ( std::vector<KSieve::ScriptBuilder*>::const_iterator it = mBuilders.begin(), end = mBuilders.end() ; it != end ; ++it ) (*it)->
00105 void commandStart( const QString & identifier ) { FOREACH commandStart( identifier ); }
00106 void commandEnd() { FOREACH commandEnd(); }
00107 void testStart( const QString & identifier ) { FOREACH testStart( identifier ); }
00108 void testEnd() { FOREACH testEnd(); }
00109 void testListStart() { FOREACH testListStart(); }
00110 void testListEnd() { FOREACH testListEnd(); }
00111 void blockStart() { FOREACH blockStart(); }
00112 void blockEnd() { FOREACH blockEnd(); }
00113 void hashComment( const QString & comment ) { FOREACH hashComment( comment ); }
00114 void bracketComment( const QString & comment ) { FOREACH bracketComment( comment ); }
00115 void lineFeed() { FOREACH lineFeed(); }
00116 void error( const KSieve::Error & e ) { FOREACH error( e ); }
00117 void finished() { FOREACH finished(); }
00118 void taggedArgument( const QString & tag ) { FOREACH taggedArgument( tag ); }
00119 void stringArgument( const QString & string, bool multiline, const QString & fixme ) { FOREACH stringArgument( string, multiline, fixme ); }
00120 void numberArgument( unsigned long number, char quantifier ) { FOREACH numberArgument( number, quantifier ); }
00121 void stringListArgumentStart() { FOREACH stringListArgumentStart(); }
00122 void stringListEntry( const QString & string, bool multiline, const QString & fixme) { FOREACH stringListEntry( string, multiline, fixme ); }
00123 void stringListArgumentEnd() { FOREACH stringListArgumentEnd(); }
00124 #undef FOREACH
00125 };
00126
00127 }
00128
00129 namespace {
00130
00131 class GenericInformationExtractor : public KSieve::ScriptBuilder {
00132 public:
00133 enum BuilderMethod {
00134 Any,
00135 TaggedArgument,
00136 StringArgument,
00137 NumberArgument,
00138 CommandStart,
00139 CommandEnd,
00140 TestStart,
00141 TestEnd,
00142 TestListStart,
00143 TestListEnd,
00144 BlockStart,
00145 BlockEnd,
00146 StringListArgumentStart,
00147 StringListEntry,
00148 StringListArgumentEnd
00149 };
00150
00151 struct StateNode {
00152
00153 int depth;
00154 BuilderMethod method;
00155 const char * string;
00156
00157 int if_found;
00158 int if_not_found;
00159 const char * save_tag;
00160 };
00161
00162 const std::vector<StateNode> mNodes;
00163 std::map<QString,QString> mResults;
00164 std::set<unsigned int> mRecursionGuard;
00165 unsigned int mState;
00166 int mNestingDepth;
00167
00168 public:
00169 GenericInformationExtractor( const std::vector<StateNode> & nodes )
00170 : KSieve::ScriptBuilder(), mNodes( nodes ), mState( 0 ), mNestingDepth( 0 ) {}
00171
00172 const std::map<QString,QString> & results() const { return mResults; }
00173
00174 private:
00175 void process( BuilderMethod method, const QString & string=QString::null ) {
00176 doProcess( method, string );
00177 mRecursionGuard.clear();
00178 }
00179 void doProcess( BuilderMethod method, const QString & string ) {
00180 mRecursionGuard.insert( mState );
00181 bool found = true;
00182 const StateNode & expected = mNodes[mState];
00183 if ( expected.depth != -1 && mNestingDepth != expected.depth )
00184 found = false;
00185 if ( expected.method != Any && method != expected.method )
00186 found = false;
00187 if ( const char * str = expected.string )
00188 if ( string.lower() != QString::fromUtf8( str ).lower() )
00189 found = false;
00190 kdDebug(5006) << ( found ? "found: " : "not found: " )
00191 << mState << " -> "
00192 << ( found ? expected.if_found : expected.if_not_found ) << endl;
00193 mState = found ? expected.if_found : expected.if_not_found ;
00194 assert( mState < mNodes.size() );
00195 if ( found )
00196 if ( const char * save_tag = expected.save_tag )
00197 mResults[save_tag] = string;
00198 if ( !found && !mRecursionGuard.count( mState ) ) {
00199 doProcess( method, string );
00200 }
00201 }
00202 void commandStart( const QString & identifier ) { kdDebug(5006) << k_funcinfo << endl; process( CommandStart, identifier ); }
00203 void commandEnd() { kdDebug(5006) << k_funcinfo << endl; process( CommandEnd ); }
00204 void testStart( const QString & identifier ) { kdDebug(5006) << k_funcinfo << endl; process( TestStart, identifier ); }
00205 void testEnd() { kdDebug(5006) << k_funcinfo << endl; process( TestEnd ); }
00206 void testListStart() { kdDebug(5006) << k_funcinfo << endl; process( TestListStart ); }
00207 void testListEnd() { kdDebug(5006) << k_funcinfo << endl; process( TestListEnd ); }
00208 void blockStart() { kdDebug(5006) << k_funcinfo << endl; process( BlockStart ); ++mNestingDepth; }
00209 void blockEnd() { kdDebug(5006) << k_funcinfo << endl; --mNestingDepth; process( BlockEnd ); }
00210 void hashComment( const QString & ) { kdDebug(5006) << k_funcinfo << endl; }
00211 void bracketComment( const QString & ) { kdDebug(5006) << k_funcinfo << endl; }
00212 void lineFeed() { kdDebug(5006) << k_funcinfo << endl; }
00213 void error( const KSieve::Error & ) {
00214 kdDebug(5006) << k_funcinfo << endl;
00215 mState = 0;
00216 }
00217 void finished() { kdDebug(5006) << k_funcinfo << endl; }
00218
00219 void taggedArgument( const QString & tag ) { kdDebug(5006) << k_funcinfo << endl; process( TaggedArgument, tag ); }
00220 void stringArgument( const QString & string, bool, const QString & ) { kdDebug(5006) << k_funcinfo << endl; process( StringArgument, string ); }
00221 void numberArgument( unsigned long number, char ) { kdDebug(5006) << k_funcinfo << endl; process( NumberArgument, QString::number( number ) ); }
00222 void stringListArgumentStart() { kdDebug(5006) << k_funcinfo << endl; process( StringListArgumentStart ); }
00223 void stringListEntry( const QString & string, bool, const QString & ) { kdDebug(5006) << k_funcinfo << endl; process( StringListEntry, string ); }
00224 void stringListArgumentEnd() { kdDebug(5006) << k_funcinfo << endl; process( StringListArgumentEnd ); }
00225 };
00226
00227 typedef GenericInformationExtractor GIE;
00228 static const GenericInformationExtractor::StateNode spamNodes[] = {
00229 { 0, GIE::CommandStart, "if", 1, 0, 0 },
00230 { 0, GIE::TestStart, "header", 2, 0, 0 },
00231 { 0, GIE::TaggedArgument, "contains", 3, 0, 0 },
00232
00233
00234 { 0, GIE::StringArgument, "x-spam-flag", 9, 4, "x-spam-flag" },
00235 { 0, GIE::StringListArgumentStart, 0, 5, 0, 0 },
00236 { 0, GIE::StringListEntry, "x-spam-flag", 6, 7, "x-spam-flag" },
00237 { 0, GIE::StringListEntry, 0, 6, 8, 0 },
00238 { 0, GIE::StringListArgumentEnd, 0, 0, 5, 0 },
00239 { 0, GIE::StringListArgumentEnd, 0, 9, 0, 0 },
00240
00241
00242 { 0, GIE::StringArgument, "yes", 15, 10, "spam-flag-yes" },
00243 { 0, GIE::StringListArgumentStart, 0, 11, 0, 0 },
00244 { 0, GIE::StringListEntry, "yes", 12, 13, "spam-flag-yes" },
00245 { 0, GIE::StringListEntry, 0, 12, 14, 0 },
00246 { 0, GIE::StringListArgumentEnd, 0, 0, 11, 0 },
00247 { 0, GIE::StringListArgumentEnd, 0, 15, 0, 0 },
00248
00249 { 0, GIE::TestEnd, 0, 16, 0, 0 },
00250
00251
00252 { 0, GIE::BlockStart, 0, 17, 0, 0 },
00253 { 1, GIE::CommandStart, "stop", 20, 19, "stop" },
00254 { -1, GIE::Any, 0, 17, 0, 0 },
00255 { 0, GIE::BlockEnd, 0, 0, 18, 0 },
00256
00257 { -1, GIE::Any, 0, 20, 20, 0 },
00258 };
00259 static const unsigned int numSpamNodes = sizeof spamNodes / sizeof *spamNodes ;
00260
00261 class SpamDataExtractor : public GenericInformationExtractor {
00262 public:
00263 SpamDataExtractor()
00264 : GenericInformationExtractor( std::vector<StateNode>( spamNodes, spamNodes + numSpamNodes ) )
00265 {
00266
00267 }
00268
00269 bool found() const {
00270 return mResults.count( "x-spam-flag" ) &&
00271 mResults.count( "spam-flag-yes" ) &&
00272 mResults.count( "stop" ) ;
00273 }
00274 };
00275
00276
00277
00278
00279 static const GenericInformationExtractor::StateNode domainNodes[] = {
00280 { 0, GIE::CommandStart, "if", 1, 0, 0 },
00281 { 0, GIE::TestStart, "not", 2, 0, 0, },
00282 { 0, GIE::TestStart, "address", 3, 0, 0 },
00283
00284
00285 { 0, GIE::TaggedArgument, "domain", 4, 5, 0 },
00286 { 0, GIE::TaggedArgument, "contains", 7, 0, 0 },
00287 { 0, GIE::TaggedArgument, "contains", 6, 0, 0 },
00288 { 0, GIE::TaggedArgument, "domain", 7, 0, 0 },
00289
00290
00291 { 0, GIE::StringArgument, "from", 13, 8, "from" },
00292 { 0, GIE::StringListArgumentStart, 0, 9, 0, 0 },
00293 { 0, GIE::StringListEntry, "from", 10, 11, "from" },
00294 { 0, GIE::StringListEntry, 0, 10, 12, 0 },
00295 { 0, GIE::StringListArgumentEnd, 0, 0, 9, 0 },
00296 { 0, GIE::StringListArgumentEnd, 0, 13, 0, 0 },
00297
00298
00299 { 0, GIE::StringArgument, 0, 17, 14, "domainName" },
00300 { 0, GIE::StringListArgumentStart, 0, 15, 0, 0 },
00301 { 0, GIE::StringListEntry, 0, 15, 16, "domainName" },
00302 { 0, GIE::StringListArgumentEnd, 0, 17, 0, 0 },
00303
00304 { 0, GIE::TestEnd, 0, 18, 0, 0 },
00305 { 0, GIE::TestEnd, 0, 19, 0, 0 },
00306
00307
00308 { 0, GIE::BlockStart, 0, 20, 0, 0 },
00309 { 1, GIE::CommandStart, "stop", 23, 22, "stop" },
00310 { -1, GIE::Any, 0, 20, 0, 0 },
00311 { 0, GIE::BlockEnd, 0, 0, 21, 0 },
00312
00313 { -1, GIE::Any, 0, 23, 23, 0 }
00314 };
00315 static const unsigned int numDomainNodes = sizeof domainNodes / sizeof *domainNodes ;
00316
00317 class DomainRestrictionDataExtractor : public GenericInformationExtractor {
00318 public:
00319 DomainRestrictionDataExtractor()
00320 : GenericInformationExtractor( std::vector<StateNode>( domainNodes, domainNodes+numDomainNodes ) )
00321 {
00322
00323 }
00324
00325 QString domainName() {
00326 return mResults.count( "stop" ) && mResults.count( "from" )
00327 ? mResults["domainName"] : QString::null ;
00328 }
00329 };
00330
00331 class VacationDataExtractor : public KSieve::ScriptBuilder {
00332 enum Context {
00333 None = 0,
00334
00335 VacationCommand,
00336
00337 Days, Addresses
00338 };
00339 public:
00340 VacationDataExtractor()
00341 : KSieve::ScriptBuilder(),
00342 mContext( None ), mNotificationInterval( 0 )
00343 {
00344 kdDebug(5006) << "VacationDataExtractor instantiated" << endl;
00345 }
00346 virtual ~VacationDataExtractor() {}
00347
00348 int notificationInterval() const { return mNotificationInterval; }
00349 const QString & messageText() const { return mMessageText; }
00350 const QStringList & aliases() const { return mAliases; }
00351
00352 private:
00353 void commandStart( const QString & identifier ) {
00354 kdDebug( 5006 ) << "VacationDataExtractor::commandStart( \"" << identifier << "\" )" << endl;
00355 if ( identifier != "vacation" )
00356 return;
00357 reset();
00358 mContext = VacationCommand;
00359 }
00360
00361 void commandEnd() {
00362 kdDebug( 5006 ) << "VacationDataExtractor::commandEnd()" << endl;
00363 mContext = None;
00364 }
00365
00366 void testStart( const QString & ) {}
00367 void testEnd() {}
00368 void testListStart() {}
00369 void testListEnd() {}
00370 void blockStart() {}
00371 void blockEnd() {}
00372 void hashComment( const QString & ) {}
00373 void bracketComment( const QString & ) {}
00374 void lineFeed() {}
00375 void error( const KSieve::Error & e ) {
00376 kdDebug( 5006 ) << "VacationDataExtractor::error() ### "
00377 << e.asString() << " @ " << e.line() << "," << e.column()
00378 << endl;
00379 }
00380 void finished() {}
00381
00382 void taggedArgument( const QString & tag ) {
00383 kdDebug( 5006 ) << "VacationDataExtractor::taggedArgument( \"" << tag << "\" )" << endl;
00384 if ( mContext != VacationCommand )
00385 return;
00386 if ( tag == "days" )
00387 mContext = Days;
00388 else if ( tag == "addresses" )
00389 mContext = Addresses;
00390 }
00391
00392 void stringArgument( const QString & string, bool, const QString & ) {
00393 kdDebug( 5006 ) << "VacationDataExtractor::stringArgument( \"" << string << "\" )" << endl;
00394 if ( mContext == Addresses ) {
00395 mAliases.push_back( string );
00396 mContext = VacationCommand;
00397 } else if ( mContext == VacationCommand ) {
00398 mMessageText = string;
00399 mContext = VacationCommand;
00400 }
00401 }
00402
00403 void numberArgument( unsigned long number, char ) {
00404 kdDebug( 5006 ) << "VacationDataExtractor::numberArgument( \"" << number << "\" )" << endl;
00405 if ( mContext != Days )
00406 return;
00407 if ( number > INT_MAX )
00408 mNotificationInterval = INT_MAX;
00409 else
00410 mNotificationInterval = number;
00411 mContext = VacationCommand;
00412 }
00413
00414 void stringListArgumentStart() {}
00415 void stringListEntry( const QString & string, bool, const QString & ) {
00416 kdDebug( 5006 ) << "VacationDataExtractor::stringListEntry( \"" << string << "\" )" << endl;
00417 if ( mContext != Addresses )
00418 return;
00419 mAliases.push_back( string );
00420 }
00421 void stringListArgumentEnd() {
00422 kdDebug( 5006 ) << "VacationDataExtractor::stringListArgumentEnd()" << endl;
00423 if ( mContext != Addresses )
00424 return;
00425 mContext = VacationCommand;
00426 }
00427
00428 private:
00429 Context mContext;
00430 int mNotificationInterval;
00431 QString mMessageText;
00432 QStringList mAliases;
00433
00434 void reset() {
00435 kdDebug(5006) << "VacationDataExtractor::reset()" << endl;
00436 mContext = None;
00437 mNotificationInterval = 0;
00438 mAliases.clear();
00439 mMessageText = QString::null;
00440 }
00441 };
00442
00443 }
00444
00445 namespace KMail {
00446
00447 Vacation::Vacation( QObject * parent, const char * name )
00448 : QObject( parent, name ), mSieveJob( 0 ), mDialog( 0 ), mWasActive( false )
00449 {
00450 mUrl = findURL();
00451 kdDebug(5006) << "Vacation: found url \"" << mUrl.prettyURL() << "\"" << endl;
00452 if ( mUrl.isEmpty() )
00453 return;
00454 mUrl.setFileName( "kolab-vacation.siv" );
00455 mSieveJob = SieveJob::get( mUrl );
00456 connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
00457 SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) );
00458 }
00459
00460 Vacation::~Vacation() {
00461 if ( mSieveJob ) mSieveJob->kill(); mSieveJob = 0;
00462 delete mDialog; mDialog = 0;
00463 kdDebug(5006) << "~Vacation()" << endl;
00464 }
00465
00466 static inline QString dotstuff( QString s ) {
00467 if ( s.startsWith( "." ) )
00468 return '.' + s.replace( "\n.", "\n.." );
00469 else
00470 return s.replace( "\n.", "\n.." );
00471 }
00472
00473 QString Vacation::composeScript( const QString & messageText,
00474 int notificationInterval,
00475 const AddrSpecList & addrSpecs,
00476 bool sendForSpam, const QString & domain )
00477 {
00478 QString addressesArgument;
00479 QStringList aliases;
00480 if ( !addrSpecs.empty() ) {
00481 addressesArgument += ":addresses [ ";
00482 QStringList sl;
00483 for ( AddrSpecList::const_iterator it = addrSpecs.begin() ; it != addrSpecs.end() ; ++it ) {
00484 sl.push_back( '"' + (*it).asString().replace( '\\', "\\\\" ).replace( '"', "\\\"" ) + '"' );
00485 aliases.push_back( (*it).asString() );
00486 }
00487 addressesArgument += sl.join( ", " ) + " ] ";
00488 }
00489 QString script = QString::fromLatin1("require \"vacation\";\n\n");
00490
00491 if ( !sendForSpam )
00492 script += QString::fromLatin1( "if header :contains \"X-Spam-Flag\" \"YES\""
00493 " { keep; stop; }\n" );
00494
00495 if ( !domain.isEmpty() )
00496 script += QString::fromLatin1( "if not address :domain :contains \"from\" \"%1\" { keep; stop; }\n" ).arg( domain );
00497
00498 script += "vacation ";
00499 script += addressesArgument;
00500 if ( notificationInterval > 0 )
00501 script += QString::fromLatin1(":days %1 ").arg( notificationInterval );
00502 script += QString::fromLatin1("text:\n");
00503 script += dotstuff( messageText.isEmpty() ? defaultMessageText() : messageText );
00504 script += QString::fromLatin1( "\n.\n;\n" );
00505 return script;
00506 }
00507
00508 static KURL findUrlForAccount( const KMail::ImapAccountBase * a ) {
00509 assert( a );
00510 const SieveConfig sieve = a->sieveConfig();
00511 if ( !sieve.managesieveSupported() )
00512 return KURL();
00513 if ( sieve.reuseConfig() ) {
00514
00515 KURL u;
00516 u.setProtocol( "sieve" );
00517 u.setHost( a->host() );
00518 u.setUser( a->login() );
00519 u.setPass( a->passwd() );
00520 u.setPort( sieve.port() );
00521 return u;
00522 } else {
00523 return sieve.alternateURL();
00524 }
00525 }
00526
00527 KURL Vacation::findURL() const {
00528 KMAcctMgr * am = kmkernel->acctMgr();
00529 assert( am );
00530 for ( KMAccount * a = am->first() ; a ; a = am->next() )
00531 if ( KMail::ImapAccountBase * iab = dynamic_cast<KMail::ImapAccountBase*>( a ) ) {
00532 KURL u = findUrlForAccount( iab );
00533 if ( !u.isEmpty() )
00534 return u;
00535 }
00536 return KURL();
00537 }
00538
00539 bool Vacation::parseScript( const QString & script, QString & messageText,
00540 int & notificationInterval, QStringList & aliases,
00541 bool & sendForSpam, QString & domainName ) {
00542 if ( script.stripWhiteSpace().isEmpty() ) {
00543 messageText = defaultMessageText();
00544 notificationInterval = defaultNotificationInterval();
00545 aliases = defaultMailAliases();
00546 sendForSpam = defaultSendForSpam();
00547 domainName = defaultDomainName();
00548 return true;
00549 }
00550
00551
00552
00553
00554 const QCString scriptUTF8 = script.stripWhiteSpace().utf8();
00555 kdDebug(5006) << "scriptUtf8 = \"" + scriptUTF8 + "\"" << endl;
00556 KSieve::Parser parser( scriptUTF8.begin(),
00557 scriptUTF8.begin() + scriptUTF8.length() );
00558 VacationDataExtractor vdx;
00559 SpamDataExtractor sdx;
00560 DomainRestrictionDataExtractor drdx;
00561 KSieveExt::MultiScriptBuilder tsb( &vdx, &sdx, &drdx );
00562 parser.setScriptBuilder( &tsb );
00563 if ( !parser.parse() )
00564 return false;
00565 messageText = vdx.messageText().stripWhiteSpace();
00566 notificationInterval = vdx.notificationInterval();
00567 aliases = vdx.aliases();
00568 if ( !GlobalSettings::allowOutOfOfficeUploadButNoSettings() ) {
00569 sendForSpam = !sdx.found();
00570 domainName = drdx.domainName();
00571 }
00572 return true;
00573 }
00574
00575 QString Vacation::defaultMessageText() {
00576 return i18n("I am out of office till %1.\n"
00577 "\n"
00578 "In urgent cases, please contact Mrs. <vacation replacement>\n"
00579 "\n"
00580 "email: <email address of vacation replacement>\n"
00581 "phone: +49 711 1111 11\n"
00582 "fax.: +49 711 1111 12\n"
00583 "\n"
00584 "Yours sincerely,\n"
00585 "-- <enter your name and email address here>\n")
00586 .arg( KGlobal::locale()->formatDate( QDate::currentDate().addDays( 1 ) ) );
00587 }
00588
00589 int Vacation::defaultNotificationInterval() {
00590 return 7;
00591 }
00592
00593 QStringList Vacation::defaultMailAliases() {
00594 QStringList sl;
00595 for ( KPIM::IdentityManager::ConstIterator it = kmkernel->identityManager()->begin() ;
00596 it != kmkernel->identityManager()->end() ; ++it )
00597 if ( !(*it).emailAddr().isEmpty() )
00598 sl.push_back( (*it).emailAddr() );
00599 return sl;
00600 }
00601
00602 bool Vacation::defaultSendForSpam() {
00603 return GlobalSettings::outOfOfficeReactToSpam();
00604 }
00605
00606 QString Vacation::defaultDomainName() {
00607 return GlobalSettings::outOfOfficeDomain();
00608 }
00609
00610 void Vacation::slotGetResult( SieveJob * job, bool success,
00611 const QString & script, bool active ) {
00612 kdDebug(5006) << "Vacation::slotGetResult( ??, " << success
00613 << ", ?, " << active << " )" << endl
00614 << "script:" << endl
00615 << script << endl;
00616 mSieveJob = 0;
00617
00618 if ( mUrl.protocol() == "sieve" && !job->sieveCapabilities().isEmpty() &&
00619 !job->sieveCapabilities().contains("vacation") ) {
00620 KMessageBox::sorry( 0, i18n("Your server did not list \"vacation\" in "
00621 "its list of supported Sieve extensions;\n"
00622 "without it, KMail cannot install out-of-"
00623 "office replies for you.\n"
00624 "Please contact you system administrator.") );
00625 emit result( false );
00626 return;
00627 }
00628
00629 if ( !mDialog )
00630 mDialog = new VacationDialog( i18n("Configure \"Out of Office\" Replies"), 0, 0, false );
00631
00632 QString messageText = defaultMessageText();
00633 int notificationInterval = defaultNotificationInterval();
00634 QStringList aliases = defaultMailAliases();
00635 bool sendForSpam = defaultSendForSpam();
00636 QString domainName = defaultDomainName();
00637 if ( !success ) active = false;
00638
00639 if ( !success || !parseScript( script, messageText, notificationInterval, aliases, sendForSpam, domainName ) )
00640 KMessageBox::information( 0, i18n("Someone (probably you) changed the "
00641 "vacation script on the server.\n"
00642 "KMail is no longer able to determine "
00643 "the parameters for the autoreplies.\n"
00644 "Default values will be used." ) );
00645
00646 mWasActive = active;
00647 mDialog->setActivateVacation( active );
00648 mDialog->setMessageText( messageText );
00649 mDialog->setNotificationInterval( notificationInterval );
00650 mDialog->setMailAliases( aliases.join(", ") );
00651 mDialog->setSendForSpam( sendForSpam );
00652 mDialog->setDomainName( domainName );
00653 mDialog->enableDomainAndSendForSpam( !GlobalSettings::allowOutOfOfficeUploadButNoSettings() );
00654
00655 connect( mDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) );
00656 connect( mDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCancel()) );
00657 connect( mDialog, SIGNAL(defaultClicked()), SLOT(slotDialogDefaults()) );
00658
00659 mDialog->show();
00660 }
00661
00662 void Vacation::slotDialogDefaults() {
00663 if ( !mDialog )
00664 return;
00665 mDialog->setActivateVacation( true );
00666 mDialog->setMessageText( defaultMessageText() );
00667 mDialog->setNotificationInterval( defaultNotificationInterval() );
00668 mDialog->setMailAliases( defaultMailAliases().join(", ") );
00669 mDialog->setSendForSpam( defaultSendForSpam() );
00670 mDialog->setDomainName( defaultDomainName() );
00671 }
00672
00673 void Vacation::slotDialogOk() {
00674 kdDebug(5006) << "Vacation::slotDialogOk()" << endl;
00675
00676 const QString script = composeScript( mDialog->messageText(),
00677 mDialog->notificationInterval(),
00678 mDialog->mailAliases(),
00679 mDialog->sendForSpam(),
00680 mDialog->domainName() );
00681 const bool active = mDialog->activateVacation();
00682
00683 kdDebug(5006) << "script:" << endl << script << endl;
00684
00685
00686 mSieveJob = SieveJob::put( mUrl, script, active, mWasActive );
00687 connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
00688 active
00689 ? SLOT(slotPutActiveResult(KMail::SieveJob*,bool))
00690 : SLOT(slotPutInactiveResult(KMail::SieveJob*,bool)) );
00691
00692
00693 mDialog->delayedDestruct();
00694 mDialog = 0;
00695 }
00696
00697 void Vacation::slotDialogCancel() {
00698 kdDebug(5006) << "Vacation::slotDialogCancel()" << endl;
00699 mDialog->delayedDestruct();
00700 mDialog = 0;
00701 emit result( false );
00702 }
00703
00704 void Vacation::slotPutActiveResult( SieveJob * job, bool success ) {
00705 handlePutResult( job, success, true );
00706 }
00707
00708 void Vacation::slotPutInactiveResult( SieveJob * job, bool success ) {
00709 handlePutResult( job, success, false );
00710 }
00711
00712 void Vacation::handlePutResult( SieveJob *, bool success, bool activated ) {
00713 if ( success )
00714 KMessageBox::information( 0, activated
00715 ? i18n("Sieve script installed successfully on the server.\n"
00716 "Out of Office reply is now active.")
00717 : i18n("Sieve script installed successfully on the server.\n"
00718 "Out of Office reply has been deactivated.") );
00719
00720 kdDebug(5006) << "Vacation::handlePutResult( ???, " << success << ", ? )"
00721 << endl;
00722 mSieveJob = 0;
00723 emit result( success );
00724 }
00725
00726
00727 }
00728
00729 #include "vacation.moc"