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 <tqtextcodec.h> 00030 00031 #include <cassert> 00032 00033 namespace KMail { 00034 00035 SieveJob::SieveJob( const KURL & url, const TQString & script, 00036 const TQValueStack<Command> & commands, 00037 TQObject * parent, const char * name ) 00038 : TQObject( 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 TQString & script, 00048 const TQValueStack<Command> & commands, 00049 bool showProgressInfo, 00050 TQObject * parent, const char * name ) 00051 : TQObject( 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, TQT_SIGNAL(data(KIO::Job*,const TQByteArray&)), 00076 TQT_SLOT(slotData(KIO::Job*,const TQByteArray&)) ); 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, TQT_SIGNAL(dataReq(KIO::Job*,TQByteArray&)), 00082 TQT_SLOT(slotDataReq(KIO::Job*,TQByteArray&)) ); 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 TQString 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, TQT_SIGNAL(entries(KIO::Job*,const KIO::UDSEntryList&)), 00106 TQT_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, TQT_SIGNAL( entries(KIO::Job *, const KIO::UDSEntryList & ) ), 00114 TQT_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, TQT_SIGNAL(result(KIO::Job*)), TQT_SLOT(slotResult(KIO::Job*)) ); 00127 } 00128 00129 void SieveJob::slotData( Job *, const TQByteArray & 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 = TQTextCodec::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 *, TQByteArray & data ) { 00143 // check whether we have already sent our data: 00144 if ( mScript.isEmpty() ) { 00145 data = TQByteArray(); // 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 = TQString(); 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 TQString 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 = TQStringList::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 = TQString(); 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 TQString & script, 00250 bool makeActive, bool wasActive ) { 00251 TQValueStack<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 TQValueStack<Command> commands; 00262 commands.push( Get ); 00263 commands.push( SearchActive ); 00264 return new SieveJob( src, TQString(), commands, showProgressInfo ); 00265 } 00266 00267 SieveJob * SieveJob::list( const KURL & src ) { 00268 TQValueStack<Command> commands; 00269 commands.push( List ); 00270 return new SieveJob( src, TQString(), commands ); 00271 } 00272 SieveJob * SieveJob::del( const KURL & url ) { 00273 TQValueStack<Command> commands; 00274 commands.push( Delete ); 00275 return new SieveJob( url, TQString(), commands ); 00276 } 00277 00278 SieveJob * SieveJob::desactivate( const KURL & url ) { 00279 TQValueStack<Command> commands; 00280 commands.push( Deactivate ); 00281 return new SieveJob( url, TQString(), commands ); 00282 } 00283 00284 SieveJob * SieveJob::activate( const KURL & url ) { 00285 TQValueStack<Command> commands; 00286 commands.push( Activate ); 00287 return new SieveJob( url, TQString(), commands ); 00288 } 00289 00290 } // namespace KMail 00291 00292 #include "sievejob.moc" 00293 00294 // vim: set noet sts=2 ts=8 sw=2: 00295