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