kmail

sievejob.cpp

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