kmail

sievedebugdialog.cpp
00001 /*
00002     sievedebugdialog.cpp
00003 
00004     KMail, the KDE mail client.
00005     Copyright (c) 2005 Martijn Klingens <klingens@kde.org>
00006 
00007     This program is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License,
00009     version 2.0, as published by the Free Software Foundation.
00010     You should have received a copy of the GNU General Public License
00011     along with this program; if not, write to the Free Software Foundation,
00012     Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
00013 */
00014 
00015 // This file is only compiled when debug is enabled, it is
00016 // not useful enough for non-developers to have this in releases.
00017 #if !defined(NDEBUG)
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022 
00023 #include "sievedebugdialog.h"
00024 
00025 #include <cassert>
00026 #include <limits.h>
00027 
00028 #include <tqdatetime.h>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kmessagebox.h>
00033 
00034 #include <kmime_header_parsing.h>
00035 #include <ksieve/error.h>
00036 #include <ksieve/parser.h>
00037 #include <ksieve/scriptbuilder.h>
00038 #include <libkpimidentities/identity.h>
00039 #include <libkpimidentities/identitymanager.h>
00040 
00041 #include "kmacctimap.h"
00042 #include "accountmanager.h"
00043 using KMail::AccountManager;
00044 #include "kmkernel.h"
00045 #include "sievejob.h"
00046 #include <tqtextedit.h>
00047 
00048 using KMail::SieveJob;
00049 using KMime::Types::AddrSpecList;
00050 
00051 namespace
00052 {
00053 
00054 class SieveDebugDataExtractor : public KSieve::ScriptBuilder
00055 {
00056     enum Context
00057     {
00058         None = 0,
00059 
00060         // command itself:
00061         SieveDebugCommand,
00062 
00063         // tagged args:
00064         Days, Addresses
00065     };
00066 
00067 public:
00068     SieveDebugDataExtractor()
00069     :   KSieve::ScriptBuilder()
00070     {
00071         kdDebug( 5006 ) << k_funcinfo << endl;
00072     }
00073 
00074     virtual ~SieveDebugDataExtractor()
00075     {
00076         kdDebug( 5006 ) << k_funcinfo << endl;
00077     }
00078 
00079 private:
00080     void commandStart( const TQString & identifier )
00081     {
00082         kdDebug( 5006 ) << k_funcinfo << "Identifier: '" << identifier << "'" << endl;
00083         reset();
00084     }
00085 
00086     void commandEnd()
00087     {
00088         kdDebug( 5006 ) << k_funcinfo << endl;
00089     }
00090 
00091     void testStart( const TQString & )
00092     {
00093         kdDebug( 5006 ) << k_funcinfo << endl;
00094     }
00095 
00096     void testEnd()
00097     {
00098         kdDebug( 5006 ) << k_funcinfo << endl;
00099     }
00100 
00101     void testListStart()
00102     {
00103         kdDebug( 5006 ) << k_funcinfo << endl;
00104     }
00105 
00106     void testListEnd()
00107     {
00108         kdDebug( 5006 ) << k_funcinfo << endl;
00109     }
00110 
00111     void blockStart()
00112     {
00113         kdDebug( 5006 ) << k_funcinfo << endl;
00114     }
00115 
00116     void blockEnd()
00117     {
00118         kdDebug( 5006 ) << k_funcinfo << endl;
00119     }
00120 
00121     void hashComment( const TQString & )
00122     {
00123         kdDebug( 5006 ) << k_funcinfo << endl;
00124     }
00125 
00126     void bracketComment( const TQString & )
00127     {
00128         kdDebug( 5006 ) << k_funcinfo << endl;
00129     }
00130 
00131     void lineFeed()
00132     {
00133         kdDebug( 5006 ) << k_funcinfo << endl;
00134     }
00135 
00136     void error( const KSieve::Error & e )
00137     {
00138         kdDebug( 5006 ) << "### " << k_funcinfo << "Error: " <<
00139             e.asString() << " @ " << e.line() << "," << e.column() << endl;
00140     }
00141 
00142     void finished()
00143     {
00144         kdDebug( 5006 ) << k_funcinfo << endl;
00145     }
00146 
00147     void taggedArgument( const TQString & tag )
00148     {
00149         kdDebug( 5006 ) << k_funcinfo << "Tag: '" << tag << "'" << endl;
00150     }
00151 
00152     void stringArgument( const TQString & string, bool, const TQString & )
00153     {
00154         kdDebug( 5006 ) << k_funcinfo << "String: '" << string << "'" << endl;
00155     }
00156 
00157     void numberArgument( unsigned long number, char )
00158     {
00159         kdDebug( 5006 ) << k_funcinfo << "Number: " << number << endl;
00160     }
00161 
00162     void stringListArgumentStart()
00163     {
00164         kdDebug( 5006 ) << k_funcinfo << endl;
00165     }
00166 
00167     void stringListEntry( const TQString & string, bool, const TQString & )
00168     {
00169         kdDebug( 5006 ) << k_funcinfo << "String: '" << string << "'" << endl;
00170     }
00171 
00172     void stringListArgumentEnd()
00173     {
00174         kdDebug( 5006 ) << k_funcinfo << endl;
00175     }
00176 
00177 private:
00178     void reset()
00179     {
00180         kdDebug( 5006 ) << k_funcinfo << endl;
00181     }
00182 };
00183 
00184 } // Anon namespace
00185 
00186 namespace KMail
00187 {
00188 
00189 SieveDebugDialog::SieveDebugDialog( TQWidget *parent, const char *name )
00190 :   KDialogBase( parent, name, true, i18n( "Sieve Diagnostics" ), KDialogBase::Ok,
00191     KDialogBase::Ok, true ),
00192     mSieveJob( 0 )
00193 {
00194     // Collect all accounts
00195     AccountManager *am = kmkernel->acctMgr();
00196     assert( am );
00197     for ( KMAccount *a = am->first(); a; a = am->next() )
00198         mAccountList.append( a );
00199 
00200     mEdit = new TQTextEdit( this );
00201     mEdit->setReadOnly(true);
00202     setMainWidget( mEdit );
00203 
00204     mEdit->setText( i18n( "Collecting diagnostic information about Sieve support...\n\n" ) );
00205 
00206     setInitialSize( TQSize( 640, 480 ) );
00207 
00208     if ( !mAccountList.isEmpty() )
00209         TQTimer::singleShot( 0, this, TQT_SLOT( slotDiagNextAccount() ) );
00210 }
00211 
00212 SieveDebugDialog::~SieveDebugDialog()
00213 {
00214     if ( mSieveJob )
00215     {
00216         mSieveJob->kill();
00217         mSieveJob = 0;
00218     }
00219     kdDebug( 5006 ) << k_funcinfo << endl;
00220 }
00221 
00222 static KURL urlFromAccount( const KMail::ImapAccountBase * a ) {
00223     const SieveConfig sieve = a->sieveConfig();
00224     if ( !sieve.managesieveSupported() )
00225         return KURL();
00226 
00227     KURL u;
00228     if ( sieve.reuseConfig() ) {
00229         // assemble Sieve url from the settings of the account:
00230         u.setProtocol( "sieve" );
00231         u.setHost( a->host() );
00232         u.setUser( a->login() );
00233         u.setPass( a->passwd() );
00234         u.setPort( sieve.port() );
00235 
00236         // Translate IMAP LOGIN to PLAIN:
00237         u.addQueryItem( "x-mech", a->auth() == "*" ? "PLAIN" : a->auth() );
00238         if ( !a->useSSL() && !a->useTLS() )
00239             u.addQueryItem( "x-allow-unencrypted", "true" );
00240     } else {
00241         u = sieve.alternateURL();
00242         if ( u.protocol().lower() == "sieve" && !a->useSSL() && !a->useTLS() && u.queryItem("x-allow-unencrypted").isEmpty() )
00243             u.addQueryItem( "x-allow-unencrypted", "true" );
00244     }
00245     return u;
00246 }
00247 
00248 void SieveDebugDialog::slotDiagNextAccount()
00249 {
00250     if ( mAccountList.isEmpty() )
00251         return;
00252 
00253     KMAccount *acc = mAccountList.first();
00254     mAccountList.pop_front();
00255 
00256     mEdit->append( i18n( "Collecting data for account '%1'...\n" ).arg( acc->name() ) );
00257     mEdit->append( i18n( "------------------------------------------------------------\n" ) );
00258     mAccountBase = dynamic_cast<KMail::ImapAccountBase *>( acc );
00259     if ( mAccountBase )
00260     {
00261         // Detect URL for this IMAP account
00262         const KURL url = urlFromAccount( mAccountBase );
00263         if ( !url.isValid() )
00264         {
00265             mEdit->append( i18n( "(Account does not support Sieve)\n\n" ) );
00266         } else {
00267             mUrl = url;
00268 
00269             mSieveJob = SieveJob::list( mUrl );
00270 
00271             connect( mSieveJob, TQT_SIGNAL( gotList( KMail::SieveJob *, bool, const TQStringList &, const TQString & ) ),
00272                 TQT_SLOT( slotGetScriptList( KMail::SieveJob *, bool, const TQStringList &, const TQString & ) ) );
00273 
00274             // Bypass the singleShot timer -- it's fired when we get our data
00275             return;
00276         }
00277     } else {
00278         mEdit->append( i18n( "(Account is not an IMAP account)\n\n" ) );
00279     }
00280 
00281     // Handle next account async
00282     TQTimer::singleShot( 0, this, TQT_SLOT( slotDiagNextAccount() ) );
00283 }
00284 
00285 void SieveDebugDialog::slotDiagNextScript()
00286 {
00287     if ( mScriptList.isEmpty() )
00288     {
00289         // Continue handling accounts instead
00290         mScriptList.clear();
00291         TQTimer::singleShot( 0, this, TQT_SLOT( slotDiagNextAccount() ) );
00292         return;
00293     }
00294 
00295     TQString scriptFile = mScriptList.first();
00296     mScriptList.pop_front();
00297 
00298     mEdit->append( i18n( "Contents of script '%1':\n" ).arg( scriptFile ) );
00299 
00300     mUrl = urlFromAccount( mAccountBase );
00301     mUrl.setFileName( scriptFile );
00302 
00303     mSieveJob = SieveJob::get( mUrl );
00304 
00305     connect( mSieveJob, TQT_SIGNAL( gotScript( KMail::SieveJob *, bool, const TQString &, bool ) ),
00306         TQT_SLOT( slotGetScript( KMail::SieveJob *, bool, const TQString &, bool ) ) );
00307 }
00308 
00309 void SieveDebugDialog::slotGetScript( SieveJob * /* job */, bool success,
00310     const TQString &script, bool active )
00311 {
00312     kdDebug( 5006 ) << "SieveDebugDialog::slotGetScript( ??, " << success
00313               << ", ?, " << active << " )" << endl
00314               << "script:" << endl
00315               << script << endl;
00316     mSieveJob = 0; // job deletes itself after returning from this slot!
00317 
00318     if ( script.isEmpty() )
00319     {
00320         mEdit->append( i18n( "(This script is empty.)\n\n" ) );
00321     }
00322     else
00323     {
00324         mEdit->append( i18n(
00325             "------------------------------------------------------------\n"
00326             "%1\n"
00327             "------------------------------------------------------------\n\n" ).arg( script ) );
00328     }
00329 
00330     // Fetch next script
00331     TQTimer::singleShot( 0, this, TQT_SLOT( slotDiagNextScript() ) );
00332 }
00333 
00334 void SieveDebugDialog::slotGetScriptList( SieveJob *job, bool success,
00335     const TQStringList &scriptList, const TQString &activeScript )
00336 {
00337     kdDebug( 5006 ) << k_funcinfo << "Success: " << success << ", List: " << scriptList.join( ", " ) <<
00338         ", active: " << activeScript << endl;
00339     mSieveJob = 0; // job deletes itself after returning from this slot!
00340 
00341     mEdit->append( i18n( "Sieve capabilities:\n" ) );
00342     TQStringList caps = job->sieveCapabilities();
00343     if ( caps.isEmpty() )
00344     {
00345         mEdit->append( i18n( "(No special capabilities available)" ) );
00346     }
00347     else
00348     {
00349         for ( TQStringList::const_iterator it = caps.begin(); it != caps.end(); ++it )
00350             mEdit->append( "* " + *it + "\n" );
00351         mEdit->append( "\n" );
00352     }
00353 
00354     mEdit->append( i18n( "Available Sieve scripts:\n" ) );
00355 
00356     if ( scriptList.isEmpty() )
00357     {
00358         mEdit->append( i18n( "(No Sieve scripts available on this server)\n\n" ) );
00359     }
00360     else
00361     {
00362         mScriptList = scriptList;
00363         for ( TQStringList::const_iterator it = scriptList.begin(); it != scriptList.end(); ++it )
00364             mEdit->append( "* " + *it + "\n" );
00365         mEdit->append( "\n" );
00366         mEdit->append( i18n( "Active script: %1\n\n" ).arg( activeScript ) );
00367     }
00368 
00369     // Handle next job: dump scripts for this server
00370     TQTimer::singleShot( 0, this, TQT_SLOT( slotDiagNextScript() ) );
00371 }
00372 
00373 void SieveDebugDialog::slotDialogOk()
00374 {
00375     kdDebug(5006) << "SieveDebugDialog::slotDialogOk()" << endl;
00376 }
00377 
00378 void SieveDebugDialog::slotPutActiveResult( SieveJob * job, bool success )
00379 {
00380     handlePutResult( job, success, true );
00381 }
00382 
00383 void SieveDebugDialog::slotPutInactiveResult( SieveJob * job, bool success )
00384 {
00385     handlePutResult( job, success, false );
00386 }
00387 
00388 void SieveDebugDialog::handlePutResult( SieveJob *, bool success, bool activated )
00389 {
00390     if ( success )
00391     {
00392         KMessageBox::information( 0, activated ? i18n(
00393             "Sieve script installed successfully on the server.\n"
00394             "Out of Office reply is now active." )
00395             : i18n( "Sieve script installed successfully on the server.\n"
00396             "Out of Office reply has been deactivated." ) );
00397     }
00398 
00399     kdDebug( 5006 ) << "SieveDebugDialog::handlePutResult( ???, " << success << ", ? )" << endl;
00400     mSieveJob = 0; // job deletes itself after returning from this slot!
00401 }
00402 
00403 
00404 } // namespace KMail
00405 
00406 #include "sievedebugdialog.moc"
00407 
00408 #endif // NDEBUG
00409