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 "kmacctcachedimap.h" 00044 #include "kmmsgdict.h" 00045 #include "maildirjob.h" 00046 00047 #include <kio/scheduler.h> 00048 #include <kio/job.h> 00049 00050 #include <kmessagebox.h> 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 delete this; 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 delete this; 00186 return; 00187 } 00188 00189 if( job->error() ) { 00190 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' ); 00191 delete this; 00192 return; 00193 } 00194 mAccount->removeJob(it); 00195 } 00196 00197 if( mFoldersOrMessages.isEmpty() ) { 00198 // No more messages to delete 00199 delete this; 00200 return; 00201 } 00202 00203 QString uids = mFoldersOrMessages.front(); mFoldersOrMessages.pop_front(); 00204 00205 KURL url = mAccount->getUrl(); 00206 url.setPath( mFolder->imapPath() + 00207 QString::fromLatin1(";UID=%1").arg(uids) ); 00208 00209 KIO::SimpleJob *simpleJob = KIO::file_delete( url, false ); 00210 KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob ); 00211 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00212 mAccount->insertJob( simpleJob, jd ); 00213 connect( simpleJob, SIGNAL( result(KIO::Job *) ), 00214 this, SLOT( slotDeleteNextMessages(KIO::Job *) ) ); 00215 } 00216 00217 void CachedImapJob::expungeFolder() 00218 { 00219 KURL url = mAccount->getUrl(); 00220 // Special URL that means EXPUNGE 00221 url.setPath( mFolder->imapPath() + QString::fromLatin1(";UID=*") ); 00222 00223 KIO::SimpleJob *job = KIO::file_delete( url, false ); 00224 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job ); 00225 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00226 mAccount->insertJob( job, jd ); 00227 connect( job, SIGNAL( result(KIO::Job *) ), 00228 this, SLOT( slotExpungeResult(KIO::Job *) ) ); 00229 } 00230 00231 void CachedImapJob::slotExpungeResult( KIO::Job * job ) 00232 { 00233 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00234 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00235 delete this; 00236 return; 00237 } 00238 00239 if (job->error()) { 00240 mErrorCode = job->error(); 00241 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' ); 00242 } 00243 else 00244 mAccount->removeJob(it); 00245 00246 delete this; 00247 } 00248 00249 void CachedImapJob::slotGetNextMessage(KIO::Job * job) 00250 { 00251 if (job) { 00252 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00253 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00254 delete this; 00255 return; 00256 } 00257 00258 if (job->error()) { 00259 mErrorCode = job->error(); 00260 mAccount->handleJobError( job, i18n( "Error while retrieving message on the server: " ) + '\n' ); 00261 delete this; 00262 return; 00263 } 00264 00265 ulong size = 0; 00266 if ((*it).data.size() > 0) { 00267 ulong uid = mMsg->UID(); 00268 size = mMsg->msgSizeServer(); 00269 00270 // Convert CR/LF to LF. 00271 size_t dataSize = (*it).data.size(); 00272 dataSize = FolderStorage::crlf2lf( (*it).data.data(), dataSize ); // always <= 00273 (*it).data.resize( dataSize ); 00274 00275 mMsg->setComplete( true ); 00276 mMsg->fromByteArray( (*it).data ); 00277 mMsg->setUID(uid); 00278 mMsg->setMsgSizeServer(size); 00279 mMsg->setTransferInProgress( false ); 00280 int index = 0; 00281 mFolder->addMsgInternal( mMsg, true, &index ); 00282 emit messageRetrieved( mMsg ); 00283 if ( index > 0 ) mFolder->unGetMsg( index ); 00284 } else { 00285 emit messageRetrieved( 0 ); 00286 } 00287 mMsg = 0; 00288 00289 mSentBytes += size; 00290 emit progress( mSentBytes, mTotalBytes ); 00291 mAccount->removeJob(it); 00292 } 00293 00294 if( mMsgsForDownload.isEmpty() ) { 00295 delete this; 00296 return; 00297 } 00298 00299 MsgForDownload mfd = mMsgsForDownload.front(); mMsgsForDownload.pop_front(); 00300 00301 mMsg = new KMMessage; 00302 mMsg->setUID(mfd.uid); 00303 mMsg->setMsgSizeServer(mfd.size); 00304 if( mfd.flags > 0 ) 00305 KMFolderImap::flagsToStatus(mMsg, mfd.flags); 00306 KURL url = mAccount->getUrl(); 00307 url.setPath(mFolder->imapPath() + QString(";UID=%1;SECTION=BODY.PEEK[]").arg(mfd.uid)); 00308 00309 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00310 jd.cancellable = true; 00311 mMsg->setTransferInProgress(true); 00312 KIO::SimpleJob *simpleJob = KIO::get(url, false, false); 00313 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob); 00314 mAccount->insertJob(simpleJob, jd); 00315 connect(simpleJob, SIGNAL(processedSize(KIO::Job *, KIO::filesize_t)), 00316 this, SLOT(slotProcessedSize(KIO::Job *, KIO::filesize_t))); 00317 connect(simpleJob, SIGNAL(result(KIO::Job *)), 00318 this, SLOT(slotGetNextMessage(KIO::Job *))); 00319 connect(simpleJob, SIGNAL(data(KIO::Job *, const QByteArray &)), 00320 mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &))); 00321 } 00322 00323 void CachedImapJob::slotProcessedSize(KIO::Job *, KIO::filesize_t processed) 00324 { 00325 emit progress( mSentBytes + processed, mTotalBytes ); 00326 } 00327 00328 void CachedImapJob::slotPutNextMessage() 00329 { 00330 mMsg = 0; 00331 00332 // First try the message list 00333 if( !mMsgList.isEmpty() ) { 00334 mMsg = mMsgList.first(); 00335 mMsgList.removeFirst(); 00336 } 00337 00338 // Now try the serial number list 00339 while( mMsg == 0 && !mSerNumMsgList.isEmpty() ) { 00340 unsigned long serNum = mSerNumMsgList.first(); 00341 mSerNumMsgList.pop_front(); 00342 00343 // Find the message with this serial number 00344 int i = 0; 00345 KMFolder* aFolder = 0; 00346 kmkernel->msgDict()->getLocation( serNum, &aFolder, &i ); 00347 if( mFolder->folder() != aFolder ) 00348 // This message was moved or something 00349 continue; 00350 mMsg = mFolder->getMsg( i ); 00351 } 00352 00353 if( !mMsg ) { 00354 // No message found for upload 00355 delete this; 00356 return; 00357 } 00358 00359 KURL url = mAccount->getUrl(); 00360 QString flags = KMFolderImap::statusToFlags( mMsg->status() ); 00361 url.setPath( mFolder->imapPath() + ";SECTION=" + flags ); 00362 00363 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00364 00365 mMsg->setUID( 0 ); // for the index 00366 QCString cstr(mMsg->asString()); 00367 int a = cstr.find("\nX-UID: "); 00368 int b = cstr.find('\n', a); 00369 if (a != -1 && b != -1 && cstr.find("\n\n") > a) cstr.remove(a, b-a); 00370 QCString mData(cstr.length() + cstr.contains('\n')); 00371 unsigned int i = 0; 00372 for( char *ch = cstr.data(); *ch; ch++ ) { 00373 if ( *ch == '\n' ) { 00374 mData.at(i) = '\r'; 00375 i++; 00376 } 00377 mData.at(i) = *ch; i++; 00378 } 00379 jd.data = mData; 00380 jd.msgList.append( mMsg ); 00381 00382 mMsg->setTransferInProgress(true); 00383 KIO::SimpleJob *simpleJob = KIO::put(url, 0, false, false, false); 00384 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob); 00385 mAccount->insertJob(simpleJob, jd); 00386 connect( simpleJob, SIGNAL( result(KIO::Job *) ), 00387 SLOT( slotPutMessageResult(KIO::Job *) ) ); 00388 connect( simpleJob, SIGNAL( dataReq(KIO::Job *, QByteArray &) ), 00389 SLOT( slotPutMessageDataReq(KIO::Job *, QByteArray &) ) ); 00390 connect( simpleJob, SIGNAL( data(KIO::Job *, const QByteArray &) ), 00391 mFolder, SLOT( slotSimpleData(KIO::Job *, const QByteArray &) ) ); 00392 connect( simpleJob, SIGNAL(infoMessage(KIO::Job *, const QString &)), 00393 SLOT(slotPutMessageInfoData(KIO::Job *, const QString &)) ); 00394 00395 } 00396 00397 //----------------------------------------------------------------------------- 00398 // TODO: port to KIO::StoredTransferJob once it's ok to require kdelibs-3.3 00399 void CachedImapJob::slotPutMessageDataReq(KIO::Job *job, QByteArray &data) 00400 { 00401 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00402 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00403 delete this; 00404 return; 00405 } 00406 if ((*it).data.size() - (*it).offset > 0x8000) { 00407 data.duplicate((*it).data.data() + (*it).offset, 0x8000); 00408 (*it).offset += 0x8000; 00409 } else if ((*it).data.size() - (*it).offset > 0) { 00410 data.duplicate((*it).data.data() + (*it).offset, 00411 (*it).data.size() - (*it).offset); 00412 (*it).offset = (*it).data.size(); 00413 } else 00414 data.resize(0); 00415 } 00416 00417 //---------------------------------------------------------------------------- 00418 void CachedImapJob::slotPutMessageInfoData(KIO::Job *job, const QString &data) 00419 { 00420 KMFolderCachedImap * imapFolder = static_cast<KMFolderCachedImap*>(mDestFolder->storage()); 00421 KMAcctCachedImap *account = imapFolder->account(); 00422 ImapAccountBase::JobIterator it = account->findJob( job ); 00423 if ( it == account->jobsEnd() ) return; 00424 00425 if (data.find("UID") != -1) 00426 { 00427 int uid = (data.right(data.length()-4)).toInt(); 00428 kdDebug( 5006 ) << k_funcinfo << "Server told us uid is: " << uid << endl; 00429 mMsg->setUID( uid ); 00430 } 00431 } 00432 00433 00434 //----------------------------------------------------------------------------- 00435 void CachedImapJob::slotPutMessageResult(KIO::Job *job) 00436 { 00437 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00438 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00439 delete this; 00440 return; 00441 } 00442 00443 if ( job->error() ) { 00444 bool cont = mAccount->handlePutError( job, *it, mFolder->folder() ); 00445 if ( !cont ) { 00446 delete this; 00447 } else { 00448 mMsg = 0; 00449 slotPutNextMessage(); 00450 } 00451 return; 00452 } 00453 00454 emit messageStored( mMsg ); 00455 00456 // we abuse those fields, the unit is the number of messages, here 00457 ++mSentBytes; 00458 emit progress( mSentBytes, mTotalBytes ); 00459 00460 int i; 00461 if( ( i = mFolder->find(mMsg) ) != -1 ) { 00462 /* 00463 * If we have aquired a uid during upload the server supports the uidnext 00464 * extension and there is no need to redownload this mail, we already have 00465 * it. Otherwise remove it, it will be redownloaded. 00466 */ 00467 if ( mMsg->UID() == 0 ) { 00468 mFolder->removeMsg(i); 00469 } else { 00470 mFolder->take( i ); 00471 mFolder->addMsgKeepUID( mMsg ); 00472 mMsg->setTransferInProgress( false ); 00473 } 00474 } 00475 mMsg = NULL; 00476 mAccount->removeJob( it ); 00477 slotPutNextMessage(); 00478 } 00479 00480 00481 void CachedImapJob::slotAddNextSubfolder( KIO::Job * job ) 00482 { 00483 if (job) { 00484 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00485 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00486 delete this; 00487 return; 00488 } 00489 00490 // make copy of setting, to reset it before potentially destroying 'it' 00491 bool silentUpload = static_cast<KMFolderCachedImap*>((*it).parent->storage())->silentUpload(); 00492 static_cast<KMFolderCachedImap*>((*it).parent->storage())->setSilentUpload( false ); 00493 00494 if ( job->error() && !silentUpload ) { 00495 QString myError = "<p><b>" + i18n("Error while uploading folder") 00496 + "</b></p><p>" + i18n("Could not make the folder <b>%1</b> on the server.").arg((*it).items[0]) 00497 + "</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>"; 00498 mAccount->handleJobError( job, myError ); 00499 } 00500 00501 if( job->error() ) { 00502 delete this; 00503 return; 00504 } 00505 mAccount->removeJob( it ); 00506 } 00507 00508 if (mFolderList.isEmpty()) { 00509 // No more folders to add 00510 delete this; 00511 return; 00512 } 00513 00514 KMFolderCachedImap *folder = mFolderList.front(); 00515 mFolderList.pop_front(); 00516 KURL url = mAccount->getUrl(); 00517 url.setPath(mFolder->imapPath() + folder->name()); 00518 00519 // Associate the jobData with the parent folder, not with the child 00520 // This is necessary in case of an error while creating the subfolder, 00521 // so that folderComplete is called on the parent (and the sync resetted). 00522 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00523 jd.items << folder->label(); // for the err msg 00524 KIO::SimpleJob *simpleJob = KIO::mkdir(url); 00525 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob); 00526 mAccount->insertJob(simpleJob, jd); 00527 connect( simpleJob, SIGNAL(result(KIO::Job *)), 00528 this, SLOT(slotAddNextSubfolder(KIO::Job *)) ); 00529 } 00530 00531 00532 void CachedImapJob::slotDeleteNextFolder( KIO::Job *job ) 00533 { 00534 if (job) { 00535 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00536 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00537 delete this; 00538 return; 00539 } 00540 00541 if( job->error() ) { 00542 mAccount->handleJobError( job, i18n( "Error while deleting folder %1 on the server: " ).arg( (*it).path ) + '\n' ); 00543 delete this; 00544 return; 00545 } 00546 mAccount->removeJob(it); 00547 } 00548 00549 if( mFoldersOrMessages.isEmpty() ) { 00550 // No more folders to delete 00551 delete this; 00552 return; 00553 } 00554 00555 QString folderPath = mFoldersOrMessages.front(); mFoldersOrMessages.pop_front(); 00556 KURL url = mAccount->getUrl(); 00557 url.setPath(folderPath); 00558 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00559 jd.path = url.path(); 00560 KIO::SimpleJob *simpleJob = KIO::file_delete(url, false); 00561 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob); 00562 mAccount->insertJob(simpleJob, jd); 00563 connect( simpleJob, SIGNAL( result(KIO::Job *) ), 00564 SLOT( slotDeleteNextFolder(KIO::Job *) ) ); 00565 } 00566 00567 void CachedImapJob::checkUidValidity() 00568 { 00569 KURL url = mAccount->getUrl(); 00570 url.setPath( mFolder->imapPath() + ";UID=0:0" ); 00571 00572 ImapAccountBase::jobData jd( url.url(), mFolder->folder() ); 00573 jd.cancellable = true; 00574 00575 KIO::SimpleJob *job = KIO::get( url, false, false ); 00576 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job ); 00577 mAccount->insertJob( job, jd ); 00578 connect( job, SIGNAL(result(KIO::Job *)), 00579 SLOT(slotCheckUidValidityResult(KIO::Job *)) ); 00580 connect( job, SIGNAL(data(KIO::Job *, const QByteArray &)), 00581 mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &))); 00582 } 00583 00584 void CachedImapJob::slotCheckUidValidityResult(KIO::Job * job) 00585 { 00586 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00587 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00588 delete this; 00589 return; 00590 } 00591 00592 if( job->error() ) { 00593 mErrorCode = job->error(); 00594 mAccount->handleJobError( job, i18n( "Error while reading folder %1 on the server: " ).arg( (*it).parent->label() ) + '\n' ); 00595 delete this; 00596 return; 00597 } 00598 00599 // Check the uidValidity 00600 QCString cstr((*it).data.data(), (*it).data.size() + 1); 00601 int a = cstr.find("X-uidValidity: "); 00602 if (a < 0) { 00603 // Something is seriously rotten here! 00604 // TODO: Tell the user that he has a problem 00605 kdDebug(5006) << "No uidvalidity available for folder " 00606 << mFolder->name() << endl; 00607 } 00608 else { 00609 int b = cstr.find("\r\n", a); 00610 if ( (b - a - 15) >= 0 ) { 00611 QString uidv = cstr.mid(a + 15, b - a - 15); 00612 // kdDebug(5006) << "New uidv = " << uidv << ", old uidv = " 00613 // << mFolder->uidValidity() << endl; 00614 if( !mFolder->uidValidity().isEmpty() && mFolder->uidValidity() != uidv ) { 00615 // kdDebug(5006) << "Expunging the mailbox " << mFolder->name() 00616 // << "!" << endl; 00617 mFolder->expunge(); 00618 mFolder->setLastUid( 0 ); 00619 mFolder->clearUidMap(); 00620 } 00621 } else 00622 kdDebug(5006) << "No uidvalidity available for folder " 00623 << mFolder->name() << endl; 00624 } 00625 00626 mAccount->removeJob(it); 00627 delete this; 00628 } 00629 00630 00631 void CachedImapJob::renameFolder( const QString &newName ) 00632 { 00633 // Set the source URL 00634 KURL urlSrc = mAccount->getUrl(); 00635 urlSrc.setPath( mFolder->imapPath() ); 00636 00637 // Set the destination URL - this is a bit trickier 00638 KURL urlDst = mAccount->getUrl(); 00639 QString imapPath( mFolder->imapPath() ); 00640 // Destination url = old imappath - oldname + new name 00641 imapPath.truncate( imapPath.length() - mFolder->folder()->name().length() - 1); 00642 imapPath += newName + '/'; 00643 urlDst.setPath( imapPath ); 00644 00645 ImapAccountBase::jobData jd( newName, mFolder->folder() ); 00646 jd.path = imapPath; 00647 00648 KIO::SimpleJob *simpleJob = KIO::rename( urlSrc, urlDst, false ); 00649 KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob ); 00650 mAccount->insertJob( simpleJob, jd ); 00651 connect( simpleJob, SIGNAL(result(KIO::Job *)), 00652 SLOT(slotRenameFolderResult(KIO::Job *)) ); 00653 } 00654 00655 static void renameChildFolders( KMFolderDir* dir, const QString& oldPath, 00656 const QString& newPath ) 00657 { 00658 if( dir ) { 00659 KMFolderNode *node = dir->first(); 00660 while( node ) { 00661 if( !node->isDir() ) { 00662 KMFolderCachedImap* imapFolder = 00663 static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage()); 00664 if ( !imapFolder->imapPath().isEmpty() ) 00665 // Only rename folders that have been accepted by the server 00666 if( imapFolder->imapPath().find( oldPath ) == 0 ) { 00667 QString p = imapFolder->imapPath(); 00668 p = p.mid( oldPath.length() ); 00669 p.prepend( newPath ); 00670 imapFolder->setImapPath( p ); 00671 renameChildFolders( imapFolder->folder()->child(), oldPath, newPath ); 00672 } 00673 } 00674 node = dir->next(); 00675 } 00676 } 00677 } 00678 00679 void CachedImapJob::slotRenameFolderResult( KIO::Job *job ) 00680 { 00681 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00682 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00683 delete this; 00684 return; 00685 } 00686 00687 00688 if( job->error() ) { 00689 // Error, revert label change 00690 QMap<QString, KMAcctCachedImap::RenamedFolder>::ConstIterator renit = mAccount->renamedFolders().find( mFolder->imapPath() ); 00691 Q_ASSERT( renit != mAccount->renamedFolders().end() ); 00692 if ( renit != mAccount->renamedFolders().end() ) { 00693 mFolder->folder()->setLabel( (*renit).mOldLabel ); 00694 mAccount->removeRenamedFolder( mFolder->imapPath() ); 00695 } 00696 mAccount->handleJobError( job, i18n( "Error while trying to rename folder %1" ).arg( mFolder->label() ) + '\n' ); 00697 } else { 00698 // Okay, the folder seems to be renamed on the server, 00699 // now rename it on disk 00700 QString oldName = mFolder->name(); 00701 QString oldPath = mFolder->imapPath(); 00702 mAccount->removeRenamedFolder( oldPath ); 00703 mFolder->setImapPath( (*it).path ); 00704 mFolder->FolderStorage::rename( (*it).url ); 00705 00706 if( oldPath.endsWith( "/" ) ) oldPath.truncate( oldPath.length() -1 ); 00707 QString newPath = mFolder->imapPath(); 00708 if( newPath.endsWith( "/" ) ) newPath.truncate( newPath.length() -1 ); 00709 renameChildFolders( mFolder->folder()->child(), oldPath, newPath ); 00710 kmkernel->dimapFolderMgr()->contentsChanged(); 00711 00712 mAccount->removeJob(it); 00713 } 00714 delete this; 00715 } 00716 00717 void CachedImapJob::slotListMessagesResult( KIO::Job * job ) 00718 { 00719 KMAcctCachedImap::JobIterator it = mAccount->findJob(job); 00720 if ( it == mAccount->jobsEnd() ) { // Shouldn't happen 00721 delete this; 00722 return; 00723 } 00724 00725 if (job->error()) { 00726 mErrorCode = job->error(); 00727 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' ); 00728 } 00729 else 00730 mAccount->removeJob(it); 00731 00732 delete this; 00733 } 00734 00735 //----------------------------------------------------------------------------- 00736 void CachedImapJob::setParentFolder( const KMFolderCachedImap* parent ) 00737 { 00738 mParentFolder = const_cast<KMFolderCachedImap*>( parent ); 00739 } 00740 00741 } 00742 00743 #include "cachedimapjob.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:43 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003