kmail Library API Documentation

cachedimapjob.cpp

00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002  *
00003  *  This file is part of KMail, the KDE mail client.
00004  *  Copyright (c) 2002-2004  Bo Thorsen <bo@sonofthor.dk>
00005  *                2002-2003  Steffen Hansen <hansen@kde.org>
00006  *                2002-2003  Zack Rusin <zack@kde.org>
00007  *
00008  *  KMail is free software; you can redistribute it and/or modify it
00009  *  under the terms of the GNU General Public License, version 2, as
00010  *  published by the Free Software Foundation.
00011  *
00012  *  KMail is distributed in the hope that it will be useful, but
00013  *  WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  *  In addition, as a special exception, the copyright holders give
00022  *  permission to link the code of this program with any edition of
00023  *  the Qt library by Trolltech AS, Norway (or with modified versions
00024  *  of Qt that use the same license as Qt), and distribute linked
00025  *  combinations including the two.  You must obey the GNU General
00026  *  Public License in all respects for all of the code used other than
00027  *  Qt.  If you modify this file, you may extend this exception to
00028  *  your version of the file, but you are not obligated to do so.  If
00029  *  you do not wish to do so, delete this exception statement from
00030  *  your version.
00031  */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "cachedimapjob.h"
00038 #include "imapaccountbase.h"
00039 
00040 #include "kmfoldermgr.h"
00041 #include "kmfolder.h"
00042 #include "kmfoldercachedimap.h"
00043 #include "kmailicalifaceimpl.h"
00044 #include "kmacctcachedimap.h"
00045 #include "kmmsgdict.h"
00046 #include "maildirjob.h"
00047 
00048 #include <kio/scheduler.h>
00049 #include <kio/job.h>
00050 
00051 #include <klocale.h>
00052 #include <kdebug.h>
00053 
00054 
00055 namespace KMail {
00056 
00057 // Get messages
00058 CachedImapJob::CachedImapJob( const QValueList<MsgForDownload>& msgs,
00059                               JobType type, KMFolderCachedImap* folder )
00060   : FolderJob( type ), mFolder( folder ), mMsgsForDownload( msgs ),
00061     mTotalBytes(0), mMsg(0), mParentFolder( 0 )
00062 {
00063   QValueList<MsgForDownload>::ConstIterator it = msgs.begin();
00064   for ( ; it != msgs.end() ; ++it )
00065     mTotalBytes += (*it).size;
00066 }
00067 
00068 // Put messages
00069 CachedImapJob::CachedImapJob( const QPtrList<KMMessage>& msgs, JobType type,
00070                               KMFolderCachedImap* folder )
00071   : FolderJob( msgs, QString::null, type, folder?folder->folder():0 ), mFolder( folder ),
00072     mTotalBytes( msgs.count() ), // we abuse it as "total number of messages"
00073     mMsg( 0 ), mParentFolder( 0 )
00074 {
00075 }
00076 
00077 CachedImapJob::CachedImapJob( const QValueList<unsigned long>& msgs,
00078                   JobType type, KMFolderCachedImap* folder )
00079   : FolderJob( QPtrList<KMMessage>(), QString::null, type, folder?folder->folder():0 ),
00080     mFolder( folder ), mSerNumMsgList( msgs ), mTotalBytes( msgs.count() ), mMsg( 0 ),
00081     mParentFolder ( 0 )
00082 {
00083 }
00084 
00085 // Add sub folders
00086 CachedImapJob::CachedImapJob( const QValueList<KMFolderCachedImap*>& fList,
00087                               JobType type, KMFolderCachedImap* folder )
00088   : FolderJob( type ), mFolder( folder ), mFolderList( fList ), mMsg( 0 ),
00089     mParentFolder ( 0 )
00090 {
00091 }
00092 
00093 // Rename folder
00094 CachedImapJob::CachedImapJob( const QString& string1, JobType type,
00095                               KMFolderCachedImap* folder )
00096   : FolderJob( type ), mFolder(folder), mMsg( 0 ), mString( string1 ),
00097     mParentFolder ( 0 )
00098 {
00099   assert( folder );
00100   assert( type != tDeleteMessage ); // moved to another ctor
00101 }
00102 
00103 // Delete folders or messages
00104 CachedImapJob::CachedImapJob( const QStringList& foldersOrMsgs, JobType type,
00105                               KMFolderCachedImap* folder )
00106   : FolderJob( type ), mFolder( folder ), mFoldersOrMessages( foldersOrMsgs ),
00107     mMsg( 0 ), mParentFolder( 0 )
00108 {
00109   assert( folder );
00110 }
00111 
00112 // Other jobs (list messages,expunge folder, check uid validity)
00113 CachedImapJob::CachedImapJob( JobType type, KMFolderCachedImap* folder )
00114   : FolderJob( type ), mFolder( folder ), mMsg( 0 ), mParentFolder ( 0 )
00115 {
00116   assert( folder );
00117 }
00118 
00119 CachedImapJob::~CachedImapJob()
00120 {
00121   mAccount->mJobList.remove(this);
00122 }
00123 
00124 void CachedImapJob::execute()
00125 {
00126   mSentBytes = 0;
00127 
00128   if( !mFolder ) {
00129     if( !mMsgList.isEmpty() ) {
00130       mFolder = static_cast<KMFolderCachedImap*>(mMsgList.first()->storage());
00131     }
00132   }
00133   assert( mFolder );
00134   mAccount = mFolder->account();
00135   assert( mAccount != 0 );
00136   if( mAccount->makeConnection() != ImapAccountBase::Connected ) {
00137     // No connection to the IMAP server
00138     kdDebug(5006) << "mAccount->makeConnection() failed" << endl;
00139     mPassiveDestructor = true;
00140     deleteLater();
00141     return;
00142   } else
00143     mPassiveDestructor = false;
00144 
00145   // All necessary conditions have been met. Register this job
00146   mAccount->mJobList.append(this);
00147 
00148   switch( mType ) {
00149   case tGetMessage:       slotGetNextMessage();     break;
00150   case tPutMessage:       slotPutNextMessage();     break;
00151   case tDeleteMessage:    slotDeleteNextMessages(); break;
00152   case tExpungeFolder:    expungeFolder();          break;
00153   case tAddSubfolders:    slotAddNextSubfolder();   break;
00154   case tDeleteFolders:    slotDeleteNextFolder();   break;
00155   case tCheckUidValidity: checkUidValidity();       break;
00156   case tRenameFolder:     renameFolder(mString);    break;
00157   case tListMessages:     listMessages();           break;
00158   default:
00159     assert( 0 );
00160   }
00161 }
00162 
00163 void CachedImapJob::listMessages()
00164 {
00165   KURL url = mAccount->getUrl();
00166   url.setPath( mFolder->imapPath() + ";UID=1:*;SECTION=FLAGS RFC822.SIZE");
00167 
00168   KIO::SimpleJob *job = KIO::get(url, false, false);
00169   KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00170   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00171   jd.cancellable = true;
00172   mAccount->insertJob( job, jd );
00173   connect( job, SIGNAL( result(KIO::Job *) ),
00174            this, SLOT( slotListMessagesResult( KIO::Job* ) ) );
00175   // send the data directly for KMFolderCachedImap
00176   connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00177            mFolder, SLOT( slotGetMessagesData( KIO::Job* , const QByteArray& ) ) );
00178 }
00179 
00180 void CachedImapJob::slotDeleteNextMessages( KIO::Job* job )
00181 {
00182   if (job) {
00183     KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00184     if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00185       deleteLater();
00186       return;
00187     }
00188 
00189     if( job->error() ) {
00190       mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00191       return;
00192     }
00193     mAccount->removeJob(it);
00194   }
00195 
00196   if( mFoldersOrMessages.isEmpty() ) {
00197     // No more messages to delete
00198     deleteLater();
00199     return;
00200   }
00201 
00202   QString uids = mFoldersOrMessages.front(); mFoldersOrMessages.pop_front();
00203 
00204   KURL url = mAccount->getUrl();
00205   url.setPath( mFolder->imapPath() +
00206                QString::fromLatin1(";UID=%1").arg(uids) );
00207 
00208   KIO::SimpleJob *simpleJob = KIO::file_delete( url, false );
00209   KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob );
00210   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00211   mAccount->insertJob( simpleJob, jd );
00212   connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00213            this, SLOT( slotDeleteNextMessages(KIO::Job *) ) );
00214 }
00215 
00216 void CachedImapJob::expungeFolder()
00217 {
00218   KURL url = mAccount->getUrl();
00219   // Special URL that means EXPUNGE
00220   url.setPath( mFolder->imapPath() + QString::fromLatin1(";UID=*") );
00221 
00222   KIO::SimpleJob *job = KIO::file_delete( url, false );
00223   KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00224   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00225   mAccount->insertJob( job, jd );
00226   connect( job, SIGNAL( result(KIO::Job *) ),
00227            this, SLOT( slotExpungeResult(KIO::Job *) ) );
00228 }
00229 
00230 void CachedImapJob::slotExpungeResult( KIO::Job * job )
00231 {
00232   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00233   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00234     deleteLater();
00235     return;
00236   }
00237 
00238   if (job->error()) {
00239     mErrorCode = job->error();
00240     mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00241   }
00242   else
00243     mAccount->removeJob(it);
00244 
00245   deleteLater();
00246 }
00247 
00248 void CachedImapJob::slotGetNextMessage(KIO::Job * job)
00249 {
00250   if (job) {
00251     KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00252     if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00253       deleteLater();
00254       return;
00255     }
00256 
00257     if (job->error()) {
00258       mErrorCode = job->error();
00259       mAccount->handleJobError( job, i18n( "Error while retrieving message on the server: " ) + '\n' );
00260       deleteLater();
00261       return;
00262     }
00263 
00264     ulong size = 0;
00265     if ((*it).data.size() > 0) {
00266       ulong uid = mMsg->UID();
00267       size = mMsg->msgSizeServer();
00268 
00269       // Convert CR/LF to LF.
00270       size_t dataSize = (*it).data.size();
00271       dataSize = FolderStorage::crlf2lf( (*it).data.data(), dataSize ); // always <=
00272       (*it).data.resize( dataSize );
00273 
00274       mMsg->setComplete( true );
00275       mMsg->fromByteArray( (*it).data );
00276       mMsg->setUID(uid);
00277       mMsg->setMsgSizeServer(size);
00278       mMsg->setTransferInProgress( false );
00279       int index = 0;
00280       mFolder->addMsgInternal( mMsg, true, &index );
00281 
00282       if ( kmkernel->iCalIface().isResourceFolder( mFolder->folder() ) ) {
00283         mFolder->setStatus( index, KMMsgStatusRead, false );
00284       }
00285 
00286       emit messageRetrieved( mMsg );
00287       if ( index > 0 ) mFolder->unGetMsg( index );
00288     } else {
00289       emit messageRetrieved( 0 );
00290     }
00291     mMsg = 0;
00292 
00293     mSentBytes += size;
00294     emit progress( mSentBytes, mTotalBytes );
00295     mAccount->removeJob(it);
00296   }
00297 
00298   if( mMsgsForDownload.isEmpty() ) {
00299     deleteLater();
00300     return;
00301   }
00302 
00303   MsgForDownload mfd = mMsgsForDownload.front(); mMsgsForDownload.pop_front();
00304 
00305   mMsg = new KMMessage;
00306   mMsg->setUID(mfd.uid);
00307   mMsg->setMsgSizeServer(mfd.size);
00308   if( mfd.flags > 0 )
00309     KMFolderImap::flagsToStatus(mMsg, mfd.flags);
00310   KURL url = mAccount->getUrl();
00311   url.setPath(mFolder->imapPath() + QString(";UID=%1;SECTION=BODY.PEEK[]").arg(mfd.uid));
00312 
00313   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00314   jd.cancellable = true;
00315   mMsg->setTransferInProgress(true);
00316   KIO::SimpleJob *simpleJob = KIO::get(url, false, false);
00317   KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00318   mAccount->insertJob(simpleJob, jd);
00319   connect(simpleJob, SIGNAL(processedSize(KIO::Job *, KIO::filesize_t)),
00320           this, SLOT(slotProcessedSize(KIO::Job *, KIO::filesize_t)));
00321   connect(simpleJob, SIGNAL(result(KIO::Job *)),
00322           this, SLOT(slotGetNextMessage(KIO::Job *)));
00323   connect(simpleJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00324           mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00325 }
00326 
00327 void CachedImapJob::slotProcessedSize(KIO::Job *, KIO::filesize_t processed)
00328 {
00329   emit progress( mSentBytes + processed, mTotalBytes );
00330 }
00331 
00332 void CachedImapJob::slotPutNextMessage()
00333 {
00334   mMsg = 0;
00335 
00336   // First try the message list
00337   if( !mMsgList.isEmpty() ) {
00338     mMsg = mMsgList.first();
00339     mMsgList.removeFirst();
00340   }
00341 
00342   // Now try the serial number list
00343   while( mMsg == 0 && !mSerNumMsgList.isEmpty() ) {
00344     unsigned long serNum = mSerNumMsgList.first();
00345     mSerNumMsgList.pop_front();
00346 
00347     // Find the message with this serial number
00348     int i = 0;
00349     KMFolder* aFolder = 0;
00350     kmkernel->msgDict()->getLocation( serNum, &aFolder, &i );
00351     if( mFolder->folder() != aFolder )
00352       // This message was moved or something
00353       continue;
00354     mMsg = mFolder->getMsg( i );
00355   }
00356 
00357   if( !mMsg ) {
00358     // No message found for upload
00359     deleteLater();
00360     return;
00361   }
00362 
00363   KURL url = mAccount->getUrl();
00364   QString flags = KMFolderImap::statusToFlags( mMsg->status() );
00365   url.setPath( mFolder->imapPath() + ";SECTION=" + flags );
00366 
00367   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00368 
00369   mMsg->setUID( 0 ); // for the index
00370   QCString cstr(mMsg->asString());
00371   int a = cstr.find("\nX-UID: ");
00372   int b = cstr.find('\n', a);
00373   if (a != -1 && b != -1 && cstr.find("\n\n") > a) cstr.remove(a, b-a);
00374   QCString mData(cstr.length() + cstr.contains('\n'));
00375   unsigned int i = 0;
00376   for( char *ch = cstr.data(); *ch; ch++ ) {
00377     if ( *ch == '\n' ) {
00378       mData.at(i) = '\r';
00379       i++;
00380     }
00381     mData.at(i) = *ch; i++;
00382   }
00383   jd.data = mData;
00384   jd.msgList.append( mMsg );
00385 
00386   mMsg->setTransferInProgress(true);
00387   KIO::SimpleJob *simpleJob = KIO::put(url, 0, false, false, false);
00388   KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00389   mAccount->insertJob(simpleJob, jd);
00390   connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00391            SLOT( slotPutMessageResult(KIO::Job *) ) );
00392   connect( simpleJob, SIGNAL( dataReq(KIO::Job *, QByteArray &) ),
00393            SLOT( slotPutMessageDataReq(KIO::Job *, QByteArray &) ) );
00394   connect( simpleJob, SIGNAL( data(KIO::Job *, const QByteArray &) ),
00395            mFolder, SLOT( slotSimpleData(KIO::Job *, const QByteArray &) ) );
00396   connect( simpleJob, SIGNAL(infoMessage(KIO::Job *, const QString &)),
00397              SLOT(slotPutMessageInfoData(KIO::Job *, const QString &)) );
00398 
00399 }
00400 
00401 //-----------------------------------------------------------------------------
00402 // TODO: port to KIO::StoredTransferJob once it's ok to require kdelibs-3.3
00403 void CachedImapJob::slotPutMessageDataReq(KIO::Job *job, QByteArray &data)
00404 {
00405   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00406   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00407     deleteLater();
00408     return;
00409   }
00410   if ((*it).data.size() - (*it).offset > 0x8000) {
00411     data.duplicate((*it).data.data() + (*it).offset, 0x8000);
00412     (*it).offset += 0x8000;
00413   } else if ((*it).data.size() - (*it).offset > 0) {
00414     data.duplicate((*it).data.data() + (*it).offset,
00415                    (*it).data.size() - (*it).offset);
00416     (*it).offset = (*it).data.size();
00417   } else
00418     data.resize(0);
00419 }
00420 
00421 //----------------------------------------------------------------------------
00422 void CachedImapJob::slotPutMessageInfoData(KIO::Job *job, const QString &data)
00423 {
00424   KMFolderCachedImap * imapFolder = static_cast<KMFolderCachedImap*>(mDestFolder->storage());
00425   KMAcctCachedImap *account = imapFolder->account();
00426   ImapAccountBase::JobIterator it = account->findJob( job );
00427   if ( it == account->jobsEnd() ) return;
00428 
00429   if (data.find("UID") != -1)
00430   {
00431     int uid = (data.right(data.length()-4)).toInt();
00432     kdDebug( 5006 ) << k_funcinfo << "Server told us uid is: " << uid << endl;
00433     mMsg->setUID( uid );
00434   }
00435 }
00436 
00437 
00438 //-----------------------------------------------------------------------------
00439 void CachedImapJob::slotPutMessageResult(KIO::Job *job)
00440 {
00441   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00442   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00443     deleteLater();
00444     return;
00445   }
00446 
00447   if ( job->error() ) {
00448     bool cont = mAccount->handlePutError( job, *it, mFolder->folder() );
00449     if ( !cont ) {
00450       deleteLater();
00451     } else {
00452       mMsg = 0;
00453       slotPutNextMessage();
00454     }
00455     return;
00456   }
00457 
00458   emit messageStored( mMsg );
00459 
00460   // we abuse those fields, the unit is the number of messages, here
00461   ++mSentBytes;
00462   emit progress( mSentBytes, mTotalBytes );
00463 
00464   int i;
00465   if( ( i = mFolder->find(mMsg) ) != -1 ) {
00466      /*
00467       * If we have aquired a uid during upload the server supports the uidnext
00468       * extension and there is no need to redownload this mail, we already have
00469       * it. Otherwise remove it, it will be redownloaded.
00470       */
00471      if ( mMsg->UID() == 0 ) {
00472         mFolder->removeMsg(i);
00473      } else {
00474         // When removing+re-adding, no point in telling the imap resources about it
00475        bool b = kmkernel->iCalIface().isResourceQuiet();
00476        kmkernel->iCalIface().setResourceQuiet( true );
00477 
00478         mFolder->take( i );
00479         mFolder->addMsgKeepUID( mMsg );
00480         mMsg->setTransferInProgress( false );
00481 
00482        kmkernel->iCalIface().setResourceQuiet( b );
00483      }
00484   }
00485   mMsg = NULL;
00486   mAccount->removeJob( it );
00487   slotPutNextMessage();
00488 }
00489 
00490 
00491 void CachedImapJob::slotAddNextSubfolder( KIO::Job * job )
00492 {
00493   if (job) {
00494     KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00495     if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00496       deleteLater();
00497       return;
00498     }
00499 
00500     // make copy of setting, to reset it before potentially destroying 'it'
00501     bool silentUpload = static_cast<KMFolderCachedImap*>((*it).parent->storage())->silentUpload();
00502     static_cast<KMFolderCachedImap*>((*it).parent->storage())->setSilentUpload( false );
00503 
00504     if ( job->error() && !silentUpload ) {
00505       QString myError = "<p><b>" + i18n("Error while uploading folder")
00506         + "</b></p><p>" + i18n("Could not make the folder <b>%1</b> on the server.").arg((*it).items[0])
00507         + "</p><p>" + i18n("This could be because you do not have permission to do this, or because the folder is already present on the server; the error message from the server communication is here:") + "</p>";
00508       mAccount->handleJobError( job, myError );
00509     }
00510 
00511     if( job->error() ) {
00512       deleteLater();
00513       return;
00514     }
00515     mAccount->removeJob( it );
00516   }
00517 
00518   if (mFolderList.isEmpty()) {
00519     // No more folders to add
00520     deleteLater();
00521     return;
00522   }
00523 
00524   KMFolderCachedImap *folder = mFolderList.front();
00525   mFolderList.pop_front();
00526   KURL url = mAccount->getUrl();
00527   url.setPath(mFolder->imapPath() + folder->folder()->name());
00528 
00529   // Associate the jobData with the parent folder, not with the child
00530   // This is necessary in case of an error while creating the subfolder,
00531   // so that folderComplete is called on the parent (and the sync resetted).
00532   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00533   jd.items << folder->label(); // for the err msg
00534   KIO::SimpleJob *simpleJob = KIO::mkdir(url);
00535   KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00536   mAccount->insertJob(simpleJob, jd);
00537   connect( simpleJob, SIGNAL(result(KIO::Job *)),
00538            this, SLOT(slotAddNextSubfolder(KIO::Job *)) );
00539 }
00540 
00541 
00542 void CachedImapJob::slotDeleteNextFolder( KIO::Job *job )
00543 {
00544   if (job) {
00545     KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00546     if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00547       deleteLater();
00548       return;
00549     }
00550 
00551     mAccount->removeDeletedFolder( (*it).path );
00552 
00553     if( job->error() ) {
00554       mAccount->handleJobError( job, i18n( "Error while deleting folder %1 on the server: " ).arg( (*it).path ) + '\n' );
00555       deleteLater();
00556       return;
00557     }
00558     mAccount->removeJob(it);
00559   }
00560 
00561   if( mFoldersOrMessages.isEmpty() ) {
00562     // No more folders to delete
00563     deleteLater();
00564     return;
00565   }
00566 
00567   QString folderPath = mFoldersOrMessages.front(); mFoldersOrMessages.pop_front();
00568   KURL url = mAccount->getUrl();
00569   url.setPath(folderPath);
00570   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00571   jd.path = url.path();
00572   KIO::SimpleJob *simpleJob = KIO::file_delete(url, false);
00573   KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00574   mAccount->insertJob(simpleJob, jd);
00575   connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00576            SLOT( slotDeleteNextFolder(KIO::Job *) ) );
00577 }
00578 
00579 void CachedImapJob::checkUidValidity()
00580 {
00581   KURL url = mAccount->getUrl();
00582   url.setPath( mFolder->imapPath() + ";UID=0:0" );
00583 
00584   ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00585   jd.cancellable = true;
00586 
00587   KIO::SimpleJob *job = KIO::get( url, false, false );
00588   KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00589   mAccount->insertJob( job, jd );
00590   connect( job, SIGNAL(result(KIO::Job *)),
00591            SLOT(slotCheckUidValidityResult(KIO::Job *)) );
00592   connect( job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00593            mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00594 }
00595 
00596 void CachedImapJob::slotCheckUidValidityResult(KIO::Job * job)
00597 {
00598   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00599   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00600     deleteLater();
00601     return;
00602   }
00603 
00604   if( job->error() ) {
00605     mErrorCode = job->error();
00606     mAccount->handleJobError( job, i18n( "Error while reading folder %1 on the server: " ).arg( (*it).parent->label() ) + '\n' );
00607     deleteLater();
00608     return;
00609   }
00610 
00611   // Check the uidValidity
00612   QCString cstr((*it).data.data(), (*it).data.size() + 1);
00613   int a = cstr.find("X-uidValidity: ");
00614   if (a < 0) {
00615     // Something is seriously rotten here!
00616     // TODO: Tell the user that he has a problem
00617     kdDebug(5006) << "No uidvalidity available for folder "
00618                   << mFolder->name() << endl;
00619   }
00620   else {
00621     int b = cstr.find("\r\n", a);
00622     if ( (b - a - 15) >= 0 ) {
00623       QString uidv = cstr.mid(a + 15, b - a - 15);
00624       // kdDebug(5006) << "New uidv = " << uidv << ", old uidv = "
00625       //               << mFolder->uidValidity() << endl;
00626       if( !mFolder->uidValidity().isEmpty() && mFolder->uidValidity() != uidv ) {
00627         // kdDebug(5006) << "Expunging the mailbox " << mFolder->name()
00628         //               << "!" << endl;
00629         mFolder->expunge();
00630         mFolder->setLastUid( 0 );
00631         mFolder->clearUidMap();
00632       }
00633     } else
00634       kdDebug(5006) << "No uidvalidity available for folder "
00635                     << mFolder->name() << endl;
00636   }
00637 
00638   mAccount->removeJob(it);
00639   deleteLater();
00640 }
00641 
00642 
00643 void CachedImapJob::renameFolder( const QString &newName )
00644 {
00645   // Set the source URL
00646   KURL urlSrc = mAccount->getUrl();
00647   urlSrc.setPath( mFolder->imapPath() );
00648 
00649   // Set the destination URL - this is a bit trickier
00650   KURL urlDst = mAccount->getUrl();
00651   QString imapPath( mFolder->imapPath() );
00652   // Destination url = old imappath - oldname + new name
00653   imapPath.truncate( imapPath.length() - mFolder->folder()->name().length() - 1);
00654   imapPath += newName + '/';
00655   urlDst.setPath( imapPath );
00656 
00657   ImapAccountBase::jobData jd( newName, mFolder->folder() );
00658   jd.path = imapPath;
00659 
00660   KIO::SimpleJob *simpleJob = KIO::rename( urlSrc, urlDst, false );
00661   KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob );
00662   mAccount->insertJob( simpleJob, jd );
00663   connect( simpleJob, SIGNAL(result(KIO::Job *)),
00664            SLOT(slotRenameFolderResult(KIO::Job *)) );
00665 }
00666 
00667 static void renameChildFolders( KMFolderDir* dir, const QString& oldPath,
00668                                 const QString& newPath )
00669 {
00670   if( dir ) {
00671     KMFolderNode *node = dir->first();
00672     while( node ) {
00673       if( !node->isDir() ) {
00674         KMFolderCachedImap* imapFolder =
00675           static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
00676         if ( !imapFolder->imapPath().isEmpty() )
00677           // Only rename folders that have been accepted by the server
00678           if( imapFolder->imapPath().find( oldPath ) == 0 ) {
00679             QString p = imapFolder->imapPath();
00680             p = p.mid( oldPath.length() );
00681             p.prepend( newPath );
00682             imapFolder->setImapPath( p );
00683             renameChildFolders( imapFolder->folder()->child(), oldPath, newPath );
00684           }
00685       }
00686       node = dir->next();
00687     }
00688   }
00689 }
00690 
00691 void CachedImapJob::slotRenameFolderResult( KIO::Job *job )
00692 {
00693   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00694   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00695     deleteLater();
00696     return;
00697   }
00698 
00699 
00700   if( job->error() ) {
00701     // Error, revert label change
00702     QMap<QString, KMAcctCachedImap::RenamedFolder>::ConstIterator renit = mAccount->renamedFolders().find( mFolder->imapPath() );
00703     Q_ASSERT( renit != mAccount->renamedFolders().end() );
00704     if ( renit != mAccount->renamedFolders().end() ) {
00705       mFolder->folder()->setLabel( (*renit).mOldLabel );
00706       mAccount->removeRenamedFolder( mFolder->imapPath() );
00707     }
00708     mAccount->handleJobError( job, i18n( "Error while trying to rename folder %1" ).arg( mFolder->label() ) + '\n' );
00709   } else {
00710     // Okay, the folder seems to be renamed on the server,
00711     // now rename it on disk
00712     QString oldName = mFolder->name();
00713     QString oldPath = mFolder->imapPath();
00714     mAccount->removeRenamedFolder( oldPath );
00715     mFolder->setImapPath( (*it).path );
00716     mFolder->FolderStorage::rename( (*it).url );
00717 
00718     if( oldPath.endsWith( "/" ) ) oldPath.truncate( oldPath.length() -1 );
00719     QString newPath = mFolder->imapPath();
00720     if( newPath.endsWith( "/" ) ) newPath.truncate( newPath.length() -1 );
00721     renameChildFolders( mFolder->folder()->child(), oldPath, newPath );
00722     kmkernel->dimapFolderMgr()->contentsChanged();
00723 
00724     mAccount->removeJob(it);
00725   }
00726   deleteLater();
00727 }
00728 
00729 void CachedImapJob::slotListMessagesResult( KIO::Job * job )
00730 {
00731   KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00732   if ( it == mAccount->jobsEnd() ) { // Shouldn't happen
00733     deleteLater();
00734     return;
00735   }
00736 
00737   if (job->error()) {
00738     mErrorCode = job->error();
00739     mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00740   }
00741   else
00742     mAccount->removeJob(it);
00743 
00744   deleteLater();
00745 }
00746 
00747 //-----------------------------------------------------------------------------
00748 void CachedImapJob::setParentFolder( const KMFolderCachedImap* parent )
00749 {
00750   mParentFolder = const_cast<KMFolderCachedImap*>( parent );
00751 }
00752 
00753 }
00754 
00755 #include "cachedimapjob.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Aug 2 09:54:56 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003