imapjob.cpp
00001 /* -*- mode: C++; c-file-style: "gnu" -*- 00002 * 00003 * This file is part of KMail, the KDE mail client. 00004 * Copyright (c) 2002-2003 Zack Rusin <zack@kde.org> 00005 * 2000-2002 Michael Haeckel <haeckel@kde.org> 00006 * 00007 * KMail is free software; you can redistribute it and/or modify it 00008 * under the terms of the GNU General Public License, version 2, as 00009 * published by the Free Software Foundation. 00010 * 00011 * KMail is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 * 00020 * In addition, as a special exception, the copyright holders give 00021 * permission to link the code of this program with any edition of 00022 * the TQt library by Trolltech AS, Norway (or with modified versions 00023 * of TQt that use the same license as TQt), and distribute linked 00024 * combinations including the two. You must obey the GNU General 00025 * Public License in all respects for all of the code used other than 00026 * TQt. If you modify this file, you may extend this exception to 00027 * your version of the file, but you are not obligated to do so. If 00028 * you do not wish to do so, delete this exception statement from 00029 * your version. 00030 */ 00031 00032 #ifdef HAVE_CONFIG_H 00033 #include <config.h> 00034 #endif 00035 00036 #include "imapjob.h" 00037 #include "kmfolderimap.h" 00038 #include "kmfolder.h" 00039 #include "kmmsgpart.h" 00040 #include "progressmanager.h" 00041 using KPIM::ProgressManager; 00042 #include "util.h" 00043 00044 #include <tqstylesheet.h> 00045 #include <kio/scheduler.h> 00046 #include <kdebug.h> 00047 #include <klocale.h> 00048 #include <mimelib/body.h> 00049 #include <mimelib/bodypart.h> 00050 #include <mimelib/string.h> 00051 00052 00053 namespace KMail { 00054 00055 //----------------------------------------------------------------------------- 00056 ImapJob::ImapJob( KMMessage *msg, JobType jt, KMFolderImap* folder, 00057 TQString partSpecifier, const AttachmentStrategy *as ) 00058 : FolderJob( msg, jt, folder? folder->folder() : 0, partSpecifier ), 00059 mAttachmentStrategy( as ), mParentProgressItem(0) 00060 { 00061 } 00062 00063 //----------------------------------------------------------------------------- 00064 ImapJob::ImapJob( TQPtrList<KMMessage>& msgList, TQString sets, JobType jt, 00065 KMFolderImap* folder ) 00066 : FolderJob( msgList, sets, jt, folder? folder->folder() : 0 ), 00067 mAttachmentStrategy ( 0 ), mParentProgressItem(0) 00068 { 00069 } 00070 00071 void ImapJob::init( JobType jt, TQString sets, KMFolderImap* folder, 00072 TQPtrList<KMMessage>& msgList ) 00073 { 00074 mJob = 0; 00075 00076 assert(jt == tGetMessage || folder); 00077 KMMessage* msg = msgList.first(); 00078 // guard against empty list 00079 if ( !msg ) { 00080 deleteLater(); 00081 return; 00082 } 00083 mType = jt; 00084 mDestFolder = folder? folder->folder() : 0; 00085 // refcount++ 00086 if (folder) { 00087 folder->open("imapjobdest"); 00088 } 00089 KMFolder *msg_parent = msg->parent(); 00090 if (msg_parent) { 00091 msg_parent->open("imapjobsrc"); 00092 } 00093 mSrcFolder = msg_parent; 00094 // If there is a destination folder, this is a copy, move or put to an 00095 // imap folder, use its account for keeping track of the job. Otherwise, 00096 // this is a get job and the src folder is an imap one. Use its account 00097 // then. 00098 KMAcctImap *account = 0; 00099 if (folder) { 00100 account = folder->account(); 00101 } else { 00102 if ( msg_parent && msg_parent->storage() ) 00103 account = static_cast<KMFolderImap*>(msg_parent->storage())->account(); 00104 } 00105 if ( !account || 00106 account->makeConnection() == ImapAccountBase::Error ) { 00107 deleteLater(); 00108 return; 00109 } 00110 account->mJobList.append( this ); 00111 if ( jt == tPutMessage ) 00112 { 00113 // transfers the complete message to the server 00114 TQPtrListIterator<KMMessage> it( msgList ); 00115 KMMessage* curMsg; 00116 while ( ( curMsg = it.current() ) != 0 ) 00117 { 00118 ++it; 00119 if ( mSrcFolder && !curMsg->isMessage() ) 00120 { 00121 int idx = mSrcFolder->find( curMsg ); 00122 curMsg = mSrcFolder->getMsg( idx ); 00123 } 00124 KURL url = account->getUrl(); 00125 TQString flags = KMFolderImap::statusToFlags( curMsg->status(), folder->permanentFlags() ); 00126 url.setPath( folder->imapPath() + ";SECTION=" + flags ); 00127 ImapAccountBase::jobData jd; 00128 jd.parent = 0; jd.offset = 0; jd.done = 0; 00129 jd.total = ( curMsg->msgSizeServer() > 0 ) ? 00130 curMsg->msgSizeServer() : curMsg->msgSize(); 00131 jd.msgList.append( curMsg ); 00132 TQCString cstr( curMsg->asString() ); 00133 int a = cstr.find("\nX-UID: "); 00134 int b = cstr.find('\n', a); 00135 if (a != -1 && b != -1 && cstr.find("\n\n") > a) cstr.remove(a, b-a); 00136 jd.data.resize( cstr.length() + cstr.contains( "\n" ) - cstr.contains( "\r\n" ) ); 00137 unsigned int i = 0; 00138 char prevChar = '\0'; 00139 // according to RFC 2060 we need CRLF 00140 for ( char *ch = cstr.data(); *ch; ch++ ) 00141 { 00142 if ( *ch == '\n' && (prevChar != '\r') ) { 00143 jd.data.at( i ) = '\r'; 00144 i++; 00145 } 00146 jd.data.at( i ) = *ch; 00147 prevChar = *ch; 00148 i++; 00149 } 00150 jd.progressItem = ProgressManager::createProgressItem( 00151 mParentProgressItem, 00152 "ImapJobUploading"+ProgressManager::getUniqueID(), 00153 i18n("Uploading message data"), 00154 TQStyleSheet::escape( curMsg->subject() ), 00155 true, 00156 account->useSSL() || account->useTLS() ); 00157 jd.progressItem->setTotalItems( jd.total ); 00158 connect ( jd.progressItem, TQT_SIGNAL( progressItemCanceled( KPIM::ProgressItem*)), 00159 account, TQT_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) ); 00160 KIO::SimpleJob *job = KIO::put( url, 0, false, false, false ); 00161 KIO::Scheduler::assignJobToSlave( account->slave(), job ); 00162 account->insertJob( job, jd ); 00163 connect( job, TQT_SIGNAL(result(KIO::Job *)), 00164 TQT_SLOT(slotPutMessageResult(KIO::Job *)) ); 00165 connect( job, TQT_SIGNAL(dataReq(KIO::Job *, TQByteArray &)), 00166 TQT_SLOT(slotPutMessageDataReq(KIO::Job *, TQByteArray &)) ); 00167 connect( job, TQT_SIGNAL(infoMessage(KIO::Job *, const TQString &)), 00168 TQT_SLOT(slotPutMessageInfoData(KIO::Job *, const TQString &)) ); 00169 connect( job, TQT_SIGNAL(processedSize(KIO::Job *, KIO::filesize_t)), 00170 TQT_SLOT(slotProcessedSize(KIO::Job *, KIO::filesize_t))); 00171 } 00172 } 00173 else if ( jt == tCopyMessage || jt == tMoveMessage ) 00174 { 00175 KURL url = account->getUrl(); 00176 KURL destUrl = account->getUrl(); 00177 destUrl.setPath(folder->imapPath()); 00178 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(msg_parent->storage()); 00179 url.setPath( imapDestFolder->imapPath() + ";UID=" + sets ); 00180 ImapAccountBase::jobData jd; 00181 jd.parent = 0; jd.offset = 0; 00182 jd.total = 1; jd.done = 0; 00183 jd.msgList = msgList; 00184 00185 TQByteArray packedArgs; 00186 TQDataStream stream( packedArgs, IO_WriteOnly ); 00187 00188 stream << (int) 'C' << url << destUrl; 00189 jd.progressItem = ProgressManager::createProgressItem( 00190 mParentProgressItem, 00191 "ImapJobCopyMove"+ProgressManager::getUniqueID(), 00192 i18n("Server operation"), 00193 i18n("Source folder: %1 - Destination folder: %2") 00194 .arg( TQStyleSheet::escape( msg_parent->prettyURL() ), 00195 TQStyleSheet::escape( mDestFolder->prettyURL() ) ), 00196 true, 00197 account->useSSL() || account->useTLS() ); 00198 jd.progressItem->setTotalItems( jd.total ); 00199 connect ( jd.progressItem, TQT_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)), 00200 account, TQT_SLOT( slotAbortRequested(KPIM::ProgressItem* ) ) ); 00201 KIO::SimpleJob *simpleJob = KIO::special( url, packedArgs, false ); 00202 KIO::Scheduler::assignJobToSlave( account->slave(), simpleJob ); 00203 mJob = simpleJob; 00204 account->insertJob( mJob, jd ); 00205 connect( mJob, TQT_SIGNAL(result(KIO::Job *)), 00206 TQT_SLOT(slotCopyMessageResult(KIO::Job *)) ); 00207 if ( jt == tMoveMessage ) 00208 { 00209 connect( mJob, TQT_SIGNAL(infoMessage(KIO::Job *, const TQString &)), 00210 TQT_SLOT(slotCopyMessageInfoData(KIO::Job *, const TQString &)) ); 00211 } 00212 } 00213 else { 00214 slotGetNextMessage(); 00215 } 00216 } 00217 00218 00219 //----------------------------------------------------------------------------- 00220 ImapJob::~ImapJob() 00221 { 00222 if ( mDestFolder ) 00223 { 00224 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder->storage())->account(); 00225 if ( account ) { 00226 if ( mJob ) { 00227 ImapAccountBase::JobIterator it = account->findJob( mJob ); 00228 if ( it != account->jobsEnd() ) { 00229 if( (*it).progressItem ) { 00230 (*it).progressItem->setComplete(); 00231 (*it).progressItem = 0; 00232 } 00233 if ( !(*it).msgList.isEmpty() ) { 00234 for ( TQPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit ) 00235 mit.current()->setTransferInProgress( false ); 00236 } 00237 } 00238 account->removeJob( mJob ); 00239 } 00240 account->mJobList.remove( this ); 00241 } 00242 mDestFolder->close("imapjobdest"); 00243 } 00244 00245 if ( mSrcFolder ) { 00246 if (!mDestFolder || mDestFolder != mSrcFolder) { 00247 if (! (mSrcFolder->folderType() == KMFolderTypeImap) ) return; 00248 KMAcctImap *account = static_cast<KMFolderImap*>(mSrcFolder->storage())->account(); 00249 if ( account ) { 00250 if ( mJob ) { 00251 ImapAccountBase::JobIterator it = account->findJob( mJob ); 00252 if ( it != account->jobsEnd() ) { 00253 if( (*it).progressItem ) { 00254 (*it).progressItem->setComplete(); 00255 (*it).progressItem = 0; 00256 } 00257 if ( !(*it).msgList.isEmpty() ) { 00258 for ( TQPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit ) 00259 mit.current()->setTransferInProgress( false ); 00260 } 00261 } 00262 account->removeJob( mJob ); // remove the associated kio job 00263 } 00264 account->mJobList.remove( this ); // remove the folderjob 00265 } 00266 } 00267 mSrcFolder->close("imapjobsrc"); 00268 } 00269 } 00270 00271 00272 //----------------------------------------------------------------------------- 00273 void ImapJob::slotGetNextMessage() 00274 { 00275 KMMessage *msg = mMsgList.first(); 00276 KMFolderImap *msgParent = msg ? static_cast<KMFolderImap*>(msg->storage()) : 0; 00277 if ( !msgParent || !msg || msg->UID() == 0 ) 00278 { 00279 // broken message 00280 emit messageRetrieved( 0 ); 00281 deleteLater(); 00282 return; 00283 } 00284 KMAcctImap *account = msgParent->account(); 00285 KURL url = account->getUrl(); 00286 TQString path = msgParent->imapPath() + ";UID=" + TQString::number(msg->UID()); 00287 ImapAccountBase::jobData jd; 00288 jd.parent = 0; jd.offset = 0; 00289 jd.total = 1; jd.done = 0; 00290 jd.msgList.append( msg ); 00291 if ( !mPartSpecifier.isEmpty() ) 00292 { 00293 if ( mPartSpecifier.find ("STRUCTURE", 0, false) != -1 ) { 00294 path += ";SECTION=STRUCTURE"; 00295 } else if ( mPartSpecifier == "HEADER" ) { 00296 path += ";SECTION=HEADER"; 00297 } else { 00298 path += ";SECTION=BODY.PEEK[" + mPartSpecifier + "]"; 00299 DwBodyPart * part = msg->findDwBodyPart( msg->getFirstDwBodyPart(), mPartSpecifier ); 00300 if (part) 00301 jd.total = part->BodySize(); 00302 } 00303 } else { 00304 path += ";SECTION=BODY.PEEK[]"; 00305 if (msg->msgSizeServer() > 0) 00306 jd.total = msg->msgSizeServer(); 00307 } 00308 url.setPath( path ); 00309 // kdDebug(5006) << "ImapJob::slotGetNextMessage - retrieve " << url.path() << endl; 00310 // protect the message, otherwise we'll get crashes afterwards 00311 msg->setTransferInProgress( true ); 00312 jd.progressItem = ProgressManager::createProgressItem( 00313 mParentProgressItem, 00314 "ImapJobDownloading"+ProgressManager::getUniqueID(), 00315 i18n("Downloading message data"), 00316 i18n("Message with subject: ") + 00317 TQStyleSheet::escape( msg->subject() ), 00318 true, 00319 account->useSSL() || account->useTLS() ); 00320 connect ( jd.progressItem, TQT_SIGNAL( progressItemCanceled( KPIM::ProgressItem*)), 00321 account, TQT_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) ); 00322 jd.progressItem->setTotalItems( jd.total ); 00323 00324 KIO::SimpleJob *simpleJob = KIO::get( url, false, false ); 00325 KIO::Scheduler::assignJobToSlave( account->slave(), simpleJob ); 00326 mJob = simpleJob; 00327 account->insertJob( mJob, jd ); 00328 if ( mPartSpecifier.find( "STRUCTURE", 0, false ) != -1 ) 00329 { 00330 connect( mJob, TQT_SIGNAL(result(KIO::Job *)), 00331 this, TQT_SLOT(slotGetBodyStructureResult(KIO::Job *)) ); 00332 } else { 00333 connect( mJob, TQT_SIGNAL(result(KIO::Job *)), 00334 this, TQT_SLOT(slotGetMessageResult(KIO::Job *)) ); 00335 } 00336 connect( mJob, TQT_SIGNAL(data(KIO::Job *, const TQByteArray &)), 00337 msgParent, TQT_SLOT(slotSimpleData(KIO::Job *, const TQByteArray &)) ); 00338 if ( jd.total > 1 ) 00339 { 00340 connect(mJob, TQT_SIGNAL(processedSize(KIO::Job *, KIO::filesize_t)), 00341 this, TQT_SLOT(slotProcessedSize(KIO::Job *, KIO::filesize_t))); 00342 } 00343 } 00344 00345 00346 //----------------------------------------------------------------------------- 00347 void ImapJob::slotGetMessageResult( KIO::Job * job ) 00348 { 00349 KMMessage *msg = mMsgList.first(); 00350 if (!msg || !msg->parent() || !job) { 00351 emit messageRetrieved( 0 ); 00352 deleteLater(); 00353 return; 00354 } 00355 KMFolderImap* parent = static_cast<KMFolderImap*>(msg->storage()); 00356 if (msg->transferInProgress()) 00357 msg->setTransferInProgress( false ); 00358 KMAcctImap *account = parent->account(); 00359 if ( !account ) { 00360 emit messageRetrieved( 0 ); 00361 deleteLater(); 00362 return; 00363 } 00364 ImapAccountBase::JobIterator it = account->findJob( job ); 00365 if ( it == account->jobsEnd() ) return; 00366 00367 bool gotData = true; 00368 if (job->error()) 00369 { 00370 TQString errorStr = i18n( "Error while retrieving messages from the server." ); 00371 if ( (*it).progressItem ) 00372 (*it).progressItem->setStatus( errorStr ); 00373 account->handleJobError( job, errorStr ); 00374 return; 00375 } else { 00376 if ((*it).data.size() > 0) 00377 { 00378 kdDebug(5006) << "ImapJob::slotGetMessageResult - retrieved part " << mPartSpecifier << endl; 00379 if ( mPartSpecifier.isEmpty() || 00380 mPartSpecifier == "HEADER" ) 00381 { 00382 uint size = msg->msgSizeServer(); 00383 if ( size > 0 && mPartSpecifier.isEmpty() ) 00384 (*it).done = size; 00385 ulong uid = msg->UID(); 00386 // must set this first so that msg->fromByteArray sets the attachment status 00387 if ( mPartSpecifier.isEmpty() ) 00388 msg->setComplete( true ); 00389 else 00390 msg->setReadyToShow( false ); 00391 00392 // Convert CR/LF to LF. 00393 size_t dataSize = (*it).data.size(); 00394 dataSize = Util::crlf2lf( (*it).data.data(), dataSize ); // always <= 00395 (*it).data.resize( dataSize ); 00396 00397 // During the construction of the message from the byteArray it does 00398 // not have a uid. Therefore we have to make sure that no connected 00399 // slots are called, since they would operate on uid == 0. 00400 msg->parent()->storage()->blockSignals( true ); 00401 msg->fromByteArray( (*it).data ); 00402 // now let others react 00403 msg->parent()->storage()->blockSignals( false ); 00404 if ( size > 0 && msg->msgSizeServer() == 0 ) { 00405 msg->setMsgSizeServer(size); 00406 } 00407 // reconstruct the UID as it gets overwritten above 00408 msg->setUID(uid); 00409 00410 } else { 00411 // Convert CR/LF to LF. 00412 size_t dataSize = (*it).data.size(); 00413 dataSize = Util::crlf2lf( (*it).data.data(), dataSize ); // always <= 00414 (*it).data.resize( dataSize ); 00415 00416 // Update the body of the retrieved part (the message notifies all observers) 00417 msg->updateBodyPart( mPartSpecifier, (*it).data ); 00418 msg->setReadyToShow( true ); 00419 // Update the attachment state, we have to do this for every part as we actually 00420 // do not know if the message has no attachment or we simply did not load the header 00421 if (msg->attachmentState() != KMMsgHasAttachment) 00422 msg->updateAttachmentState(); 00423 if (msg->invitationState() != KMMsgHasInvitation) 00424 msg->updateInvitationState(); 00425 } 00426 } else { 00427 kdDebug(5006) << "ImapJob::slotGetMessageResult - got no data for " << mPartSpecifier << endl; 00428 gotData = false; 00429 msg->setReadyToShow( true ); 00430 // nevertheless give visual feedback 00431 msg->notify(); 00432 } 00433 } 00434 if (account->slave()) { 00435 account->removeJob(it); 00436 account->mJobList.remove(this); 00437 } 00438 /* This needs to be emitted last, so the slots that are hooked to it 00439 * don't unGetMsg the msg before we have finished. */ 00440 if ( mPartSpecifier.isEmpty() || 00441 mPartSpecifier == "HEADER" ) 00442 { 00443 if ( gotData ) 00444 emit messageRetrieved(msg); 00445 else 00446 { 00447 /* we got an answer but not data 00448 * this means that the msg is not on the server anymore so delete it */ 00449 emit messageRetrieved( 0 ); 00450 parent->ignoreJobsForMessage( msg ); 00451 int idx = parent->find( msg ); 00452 if (idx != -1) parent->removeMsg( idx, true ); 00453 // the removeMsg will unGet the message, which will delete all 00454 // jobs, including this one 00455 return; 00456 } 00457 } else { 00458 emit messageUpdated(msg, mPartSpecifier); 00459 } 00460 deleteLater(); 00461 } 00462 00463 //----------------------------------------------------------------------------- 00464 void ImapJob::slotGetBodyStructureResult( KIO::Job * job ) 00465 { 00466 KMMessage *msg = mMsgList.first(); 00467 if (!msg || !msg->parent() || !job) { 00468 deleteLater(); 00469 return; 00470 } 00471 KMFolderImap* parent = static_cast<KMFolderImap*>(msg->storage()); 00472 if (msg->transferInProgress()) 00473 msg->setTransferInProgress( false ); 00474 KMAcctImap *account = parent->account(); 00475 if ( !account ) { 00476 deleteLater(); 00477 return; 00478 } 00479 ImapAccountBase::JobIterator it = account->findJob( job ); 00480 if ( it == account->jobsEnd() ) return; 00481 00482 00483 if (job->error()) 00484 { 00485 account->handleJobError( job, i18n( "Error while retrieving information on the structure of a message." ) ); 00486 return; 00487 } else { 00488 if ((*it).data.size() > 0) 00489 { 00490 TQDataStream stream( (*it).data, IO_ReadOnly ); 00491 account->handleBodyStructure(stream, msg, mAttachmentStrategy); 00492 } 00493 } 00494 if (account->slave()) { 00495 account->removeJob(it); 00496 account->mJobList.remove(this); 00497 } 00498 deleteLater(); 00499 } 00500 00501 //----------------------------------------------------------------------------- 00502 void ImapJob::slotPutMessageDataReq( KIO::Job *job, TQByteArray &data ) 00503 { 00504 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder->storage())->account(); 00505 if ( !account ) 00506 { 00507 emit finished(); 00508 deleteLater(); 00509 return; 00510 } 00511 ImapAccountBase::JobIterator it = account->findJob( job ); 00512 if ( it == account->jobsEnd() ) return; 00513 00514 if ((*it).data.size() - (*it).offset > 0x8000) 00515 { 00516 data.duplicate((*it).data.data() + (*it).offset, 0x8000); 00517 (*it).offset += 0x8000; 00518 } 00519 else if ((*it).data.size() - (*it).offset > 0) 00520 { 00521 data.duplicate((*it).data.data() + (*it).offset, (*it).data.size() - (*it).offset); 00522 (*it).offset = (*it).data.size(); 00523 } else data.resize(0); 00524 } 00525 00526 00527 //----------------------------------------------------------------------------- 00528 void ImapJob::slotPutMessageResult( KIO::Job *job ) 00529 { 00530 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder->storage())->account(); 00531 if ( !account ) 00532 { 00533 emit finished(); 00534 deleteLater(); 00535 return; 00536 } 00537 ImapAccountBase::JobIterator it = account->findJob( job ); 00538 if ( it == account->jobsEnd() ) return; 00539 bool deleteMe = false; 00540 if (job->error()) 00541 { 00542 if ( (*it).progressItem ) 00543 (*it).progressItem->setStatus( i18n("Uploading message data failed.") ); 00544 account->handlePutError( job, *it, mDestFolder ); 00545 return; 00546 } else { 00547 if ( (*it).progressItem ) 00548 (*it).progressItem->setStatus( i18n("Uploading message data completed.") ); 00549 if ( mParentProgressItem ) 00550 { 00551 mParentProgressItem->incCompletedItems(); 00552 mParentProgressItem->updateProgress(); 00553 } 00554 KMMessage *msg = (*it).msgList.first(); 00555 emit messageStored( msg ); 00556 if ( msg == mMsgList.getLast() ) 00557 { 00558 emit messageCopied( mMsgList ); 00559 if (account->slave()) { 00560 account->mJobList.remove( this ); 00561 } 00562 deleteMe = true; 00563 } 00564 } 00565 if (account->slave()) { 00566 account->removeJob( it ); // also clears progressitem 00567 } 00568 if ( deleteMe ) 00569 deleteLater(); 00570 } 00571 00572 //----------------------------------------------------------------------------- 00573 void ImapJob::slotCopyMessageInfoData(KIO::Job * job, const TQString & data) 00574 { 00575 KMFolderImap * imapFolder = static_cast<KMFolderImap*>(mDestFolder->storage()); 00576 KMAcctImap *account = imapFolder->account(); 00577 if ( !account ) 00578 { 00579 emit finished(); 00580 deleteLater(); 00581 return; 00582 } 00583 ImapAccountBase::JobIterator it = account->findJob( job ); 00584 if ( it == account->jobsEnd() ) return; 00585 00586 if (data.find("UID") != -1) 00587 { 00588 // split 00589 TQString oldUid = data.section(' ', 1, 1); 00590 TQString newUid = data.section(' ', 2, 2); 00591 00592 // get lists of uids 00593 TQValueList<ulong> olduids = KMFolderImap::splitSets(oldUid); 00594 TQValueList<ulong> newuids = KMFolderImap::splitSets(newUid); 00595 00596 int index = -1; 00597 KMMessage * msg; 00598 for ( msg = (*it).msgList.first(); msg; msg = (*it).msgList.next() ) 00599 { 00600 ulong uid = msg->UID(); 00601 index = olduids.findIndex(uid); 00602 if (index > -1) 00603 { 00604 // found, get the new uid 00605 imapFolder->saveMsgMetaData( msg, newuids[index] ); 00606 } 00607 } 00608 } 00609 } 00610 00611 //---------------------------------------------------------------------------- 00612 void ImapJob::slotPutMessageInfoData(KIO::Job *job, const TQString &data) 00613 { 00614 KMFolderImap * imapFolder = static_cast<KMFolderImap*>(mDestFolder->storage()); 00615 KMAcctImap *account = imapFolder->account(); 00616 if ( !account ) 00617 { 00618 emit finished(); 00619 deleteLater(); 00620 return; 00621 } 00622 ImapAccountBase::JobIterator it = account->findJob( job ); 00623 if ( it == account->jobsEnd() ) return; 00624 00625 if ( data.find("UID") != -1 ) 00626 { 00627 ulong uid = ( data.right(data.length()-4) ).toInt(); 00628 if ( !(*it).msgList.isEmpty() ) 00629 { 00630 imapFolder->saveMsgMetaData( (*it).msgList.first(), uid ); 00631 } 00632 } 00633 } 00634 00635 00636 //----------------------------------------------------------------------------- 00637 void ImapJob::slotCopyMessageResult( KIO::Job *job ) 00638 { 00639 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder->storage())->account(); 00640 if ( !account ) 00641 { 00642 emit finished(); 00643 deleteLater(); 00644 return; 00645 } 00646 ImapAccountBase::JobIterator it = account->findJob( job ); 00647 if ( it == account->jobsEnd() ) return; 00648 00649 if (job->error()) 00650 { 00651 mErrorCode = job->error(); 00652 TQString errStr = i18n("Error while copying messages."); 00653 if ( (*it).progressItem ) 00654 (*it).progressItem->setStatus( errStr ); 00655 if ( account->handleJobError( job, errStr ) ) 00656 deleteLater(); 00657 return; 00658 } else { 00659 if ( !(*it).msgList.isEmpty() ) 00660 { 00661 emit messageCopied((*it).msgList); 00662 } else if (mMsgList.first()) { 00663 emit messageCopied(mMsgList.first()); 00664 } 00665 } 00666 if (account->slave()) { 00667 account->removeJob(it); 00668 account->mJobList.remove(this); 00669 } 00670 deleteLater(); 00671 } 00672 00673 //----------------------------------------------------------------------------- 00674 void ImapJob::execute() 00675 { 00676 init( mType, mSets, mDestFolder? 00677 dynamic_cast<KMFolderImap*>( mDestFolder->storage() ):0, mMsgList ); 00678 } 00679 00680 //----------------------------------------------------------------------------- 00681 void ImapJob::setParentFolder( const KMFolderImap* parent ) 00682 { 00683 mParentFolder = const_cast<KMFolderImap*>( parent ); 00684 } 00685 00686 //----------------------------------------------------------------------------- 00687 void ImapJob::slotProcessedSize(KIO::Job * job, KIO::filesize_t processed) 00688 { 00689 KMMessage *msg = mMsgList.first(); 00690 if (!msg || !job) { 00691 return; 00692 } 00693 KMFolderImap* parent = 0; 00694 if ( msg->parent() && msg->parent()->folderType() == KMFolderTypeImap ) 00695 parent = static_cast<KMFolderImap*>(msg->parent()->storage()); 00696 else if (mDestFolder) // put 00697 parent = static_cast<KMFolderImap*>(mDestFolder->storage()); 00698 if (!parent) return; 00699 KMAcctImap *account = parent->account(); 00700 if ( !account ) return; 00701 ImapAccountBase::JobIterator it = account->findJob( job ); 00702 if ( it == account->jobsEnd() ) return; 00703 (*it).done = processed; 00704 if ( (*it).progressItem ) { 00705 (*it).progressItem->setCompletedItems( processed ); 00706 (*it).progressItem->updateProgress(); 00707 } 00708 emit progress( (*it).done, (*it).total ); 00709 } 00710 00711 }//namespace KMail 00712 00713 #include "imapjob.moc"