kmail

sievejob.cpp

00001 /*  -*- c++ -*-
00002     sievejob.h
00003 
00004     KMail, the KDE mail client.
00005     Copyright (c) 2002 Marc Mutz <mutz@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 #ifdef HAVE_CONFIG_H
00016 #include <config.h>
00017 #endif
00018 
00019 #include "sievejob.h"
00020 
00021 #include <kio/job.h>
00022 using KIO::Job;
00023 // <kio/global.h>
00024 using KIO::UDSAtomTypes;
00025 using KIO::UDSEntryList;
00026 using KIO::UDSEntry;
00027 #include <kdebug.h>
00028 
00029 #include <qtextcodec.h>
00030 
00031 #include <cassert>
00032 
00033 namespace KMail {
00034 
00035   SieveJob::SieveJob( const KURL & url, const QString & script,
00036               const QValueStack<Command> & commands,
00037               QObject * parent, const char * name )
00038     : QObject( parent, name ),
00039       mUrl( url ), mJob( 0 ), mDec( 0 ),
00040       mScript( script ), mFileExists( DontKnow ), mCommands( commands )
00041   {
00042     assert( !commands.isEmpty() );
00043     schedule( commands.top() );
00044   }
00045 
00046   SieveJob::~SieveJob() {
00047     kill();
00048     delete mDec;
00049     kdDebug(5006) << "~SieveJob()" << endl;
00050   }
00051 
00052   void SieveJob::kill( bool quiet ) {
00053     if ( mJob ) mJob->kill( quiet );
00054   }
00055 
00056   void SieveJob::schedule( Command command ) {
00057     switch ( command ) {
00058     case Get:
00059       kdDebug(5006) << "SieveJob::schedule: get( " << mUrl.prettyURL() << " )" << endl;
00060       mJob = KIO::get( mUrl );
00061       connect( mJob, SIGNAL(data(KIO::Job*,const QByteArray&)),
00062            SLOT(slotData(KIO::Job*,const QByteArray&)) );
00063       break;
00064     case Put:
00065       kdDebug(5006) << "SieveJob::schedule: put( " << mUrl.prettyURL() << " )" << endl;
00066       mJob = KIO::put( mUrl, 0600, true /*overwrite*/, false /*resume*/ );
00067       connect( mJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
00068            SLOT(slotDataReq(KIO::Job*,QByteArray&)) );
00069       break;
00070     case Activate:
00071       kdDebug(5006) << "SieveJob::schedule: chmod( " << mUrl.prettyURL() << ", 0700 )"
00072         << endl;
00073       mJob = KIO::chmod( mUrl, 0700 );
00074       break;
00075     case Deactivate:
00076       kdDebug(5006) << "SieveJob::schedule: chmod( " << mUrl.prettyURL() << ", 0600 )"
00077         << endl;
00078       mJob = KIO::chmod( mUrl, 0600 );
00079       break;
00080     case SearchActive:
00081       kdDebug(5006) << "SieveJob::schedule: listDir( " << mUrl.prettyURL() << " )" << endl;
00082       {
00083     KURL url = mUrl;
00084     QString query = url.query(); //save query part, because KURL::cd() erases it
00085     if ( !url.fileName().isEmpty() )
00086         url.cd("..");
00087     url.setQuery( query );
00088     kdDebug(5006) << "SieveJob::schedule: listDir's real URL: " << url.prettyURL()
00089           << endl;
00090     mJob = KIO::listDir( url );
00091     connect( mJob, SIGNAL(entries(KIO::Job*,const KIO::UDSEntryList&)),
00092          SLOT(slotEntries(KIO::Job*,const KIO::UDSEntryList&)) );
00093     break;
00094       }
00095     case List:
00096       kdDebug(5006) << "SieveJob::schedule: listDir( " << mUrl.prettyURL() << " )" << endl;
00097       {
00098     mJob = KIO::listDir( mUrl );
00099     connect( mJob, SIGNAL( entries(KIO::Job *, const KIO::UDSEntryList & ) ),
00100          SLOT( slotEntries( KIO::Job *, const KIO::UDSEntryList & ) ) );
00101     break;
00102       }
00103     case Delete:
00104       kdDebug(5006) << "SieveJob::schedule: delete( " << mUrl.prettyURL() << " )" << endl;
00105       mJob = KIO::del( mUrl );
00106       break;
00107     default:
00108       assert( 0 );
00109     }
00110     // common to all jobs:
00111     connect( mJob, SIGNAL(result(KIO::Job*)), SLOT(slotResult(KIO::Job*)) );
00112   }
00113 
00114   void SieveJob::slotData( Job *, const QByteArray & data ) {
00115     // check for end-of-data marker:
00116     if ( data.size() == 0 )
00117       return;
00118 
00119     // make sure we have a textdecoder;
00120     if ( !mDec )
00121       mDec = QTextCodec::codecForMib( 106 /*utf8*/ )->makeDecoder();
00122 
00123     // decode utf8; add to mScript:
00124     mScript += mDec->toUnicode( data.data(), data.size() );
00125   }
00126 
00127   void SieveJob::slotDataReq( Job *, QByteArray & data ) {
00128     // check whether we have already sent our data:
00129     if ( mScript.isEmpty() ) {
00130       data = QByteArray(); // end-of-data marker
00131       return;
00132     }
00133 
00134     // Convert mScript into UTF-8:
00135     data = mScript.utf8();
00136 
00137     // "data" contains a trailing NUL, remove:
00138     if ( data.size() > 0 && data[(int)data.size() - 1] == '\0' )
00139       data.resize( data.size() - 1 );
00140 
00141     // mark mScript sent:
00142     mScript = QString::null;
00143   }
00144 
00145   void SieveJob::slotEntries( Job *, const UDSEntryList & l ) {
00146     // loop over entries:
00147     for ( UDSEntryList::const_iterator it = l.begin() ; it != l.end() ; ++it ) {
00148       // Loop over all UDS atoms to find the UDS_ACCESS and UDS_NAME atoms;
00149       // note if we find an exec'able file ( == active script )
00150       // or the requested filename (mUrl.fileName()).
00151       QString filename;
00152       bool isActive = false;
00153       for ( UDSEntry::const_iterator et = (*it).begin() ; et != (*it).end() ; ++ et ) {
00154     if ( ( *et ).m_uds == KIO::UDS_NAME ) {
00155       filename = ( *et ).m_str;
00156       mAvailableScripts.append( filename );
00157     } else if ( ( *et ).m_uds == KIO::UDS_ACCESS && ( *et ).m_long == 0700 )
00158       isActive = true;
00159       }
00160 
00161       if ( isActive )
00162     mActiveScriptName = filename;
00163 
00164       if ( mFileExists == DontKnow && filename == mUrl.fileName() )
00165     mFileExists = Yes;
00166       emit item( this, filename, isActive );
00167       if ( mFileExists == Yes && !mActiveScriptName.isEmpty() )
00168     return; // early return if we have all information
00169     }
00170   }
00171 
00172   void SieveJob::slotResult( Job * job ) {
00173     Command lastCmd = mCommands.top();
00174 
00175     // First, let's see if we come back from a SearchActive. If so, set
00176     // mFileExists to No if we didn't see the mUrl.fileName() during
00177     // listDir...
00178     if ( lastCmd == SearchActive && mFileExists == DontKnow && !job->error() )
00179       mFileExists = No;
00180     // prepare for next round:
00181     mCommands.pop();
00182     delete mDec; mDec = 0;
00183 
00184     if ( mSieveCapabilities.empty() ) {
00185       mSieveCapabilities = QStringList::split( ' ', job->queryMetaData( "sieveExtensions" ) );
00186       kdDebug(5006) << "Received Sieve extensions supported:" << endl
00187             << mSieveCapabilities.join("\n") << endl;
00188     }
00189 
00190     // check for errors:
00191     if ( job->error() ) {
00192       job->showErrorDialog( 0 );
00193 
00194       emit result( this, false, mScript, mUrl.fileName() == mActiveScriptName );
00195 
00196       if ( lastCmd == List )
00197     emit gotList( this, false, mAvailableScripts, mActiveScriptName );
00198       else
00199     emit gotScript( this, false, mScript, mUrl.fileName() == mActiveScriptName );
00200 
00201       mJob = 0;
00202       delete this;
00203       return;
00204     }
00205 
00206     // check for new tasks:
00207     if ( !mCommands.empty() ) {
00208       // Don't fail get'ting a non-existant script:
00209       if ( mCommands.top() == Get && mFileExists == No ) {
00210     mScript = QString::null;
00211     mCommands.pop();
00212       }
00213     }
00214 
00215     if ( mCommands.empty() ) {
00216       // was last command; report success and delete this object:
00217       emit result( this, true, mScript, mUrl.fileName() == mActiveScriptName );
00218       if ( lastCmd == List )
00219     emit gotList( this, true, mAvailableScripts, mActiveScriptName );
00220       else
00221     emit gotScript( this, true, mScript, mUrl.fileName() == mActiveScriptName );
00222 
00223       mJob = 0; // deletes itself on returning from this slot
00224       delete this;
00225       return;
00226     } else {
00227       // schedule the next command:
00228       schedule( mCommands.top() );
00229     }
00230   }
00231 
00232   SieveJob * SieveJob::put( const KURL & dest, const QString & script,
00233                 bool makeActive, bool wasActive ) {
00234     QValueStack<Command> commands;
00235     if ( makeActive )
00236       commands.push( Activate );
00237     if ( wasActive )
00238       commands.push( Deactivate );
00239     commands.push( Put );
00240     return new SieveJob( dest, script, commands );
00241   }
00242 
00243   SieveJob * SieveJob::get( const KURL & src ) {
00244     QValueStack<Command> commands;
00245     commands.push( Get );
00246     commands.push( SearchActive );
00247     return new SieveJob( src, QString::null, commands );
00248   }
00249 
00250   SieveJob * SieveJob::list( const KURL & src ) {
00251     QValueStack<Command> commands;
00252     commands.push( List );
00253     return new SieveJob( src, QString::null, commands );
00254   }
00255   SieveJob * SieveJob::del( const KURL & url ) {
00256     QValueStack<Command> commands;
00257     commands.push( Delete );
00258     return new SieveJob( url, QString::null, commands );
00259   }
00260 
00261   SieveJob * SieveJob::activate( const KURL & url ) {
00262     QValueStack<Command> commands;
00263     commands.push( Activate );
00264     commands.push( Deactivate );
00265     return new SieveJob( url, QString::null, commands );
00266   }
00267 
00268 } // namespace KMail
00269 
00270 #include "sievejob.moc"
00271 
00272 // vim: set noet sts=2 ts=8 sw=2:
00273 
KDE Home | KDE Accessibility Home | Description of Access Keys