00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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 #include "scalix.h"
00048 #include "util.h"
00049
00050 #include <kio/scheduler.h>
00051 #include <kio/job.h>
00052
00053 #include <klocale.h>
00054 #include <kdebug.h>
00055
00056
00057 namespace KMail {
00058
00059
00060 CachedImapJob::CachedImapJob( const QValueList<MsgForDownload>& msgs,
00061 JobType type, KMFolderCachedImap* folder )
00062 : FolderJob( type ), mFolder( folder ), mMsgsForDownload( msgs ),
00063 mTotalBytes(0), mMsg(0), mParentFolder( 0 )
00064 {
00065 QValueList<MsgForDownload>::ConstIterator it = msgs.begin();
00066 for ( ; it != msgs.end() ; ++it )
00067 mTotalBytes += (*it).size;
00068 }
00069
00070
00071 CachedImapJob::CachedImapJob( const QPtrList<KMMessage>& msgs, JobType type,
00072 KMFolderCachedImap* folder )
00073 : FolderJob( msgs, QString::null, type, folder?folder->folder():0 ), mFolder( folder ),
00074 mTotalBytes( msgs.count() ),
00075 mMsg( 0 ), mParentFolder( 0 )
00076 {
00077 }
00078
00079 CachedImapJob::CachedImapJob( const QValueList<unsigned long>& msgs,
00080 JobType type, KMFolderCachedImap* folder )
00081 : FolderJob( QPtrList<KMMessage>(), QString::null, type, folder?folder->folder():0 ),
00082 mFolder( folder ), mSerNumMsgList( msgs ), mTotalBytes( msgs.count() ), mMsg( 0 ),
00083 mParentFolder ( 0 )
00084 {
00085 }
00086
00087
00088 CachedImapJob::CachedImapJob( const QValueList<KMFolderCachedImap*>& fList,
00089 JobType type, KMFolderCachedImap* folder )
00090 : FolderJob( type ), mFolder( folder ), mFolderList( fList ), mMsg( 0 ),
00091 mParentFolder ( 0 )
00092 {
00093 }
00094
00095
00096 CachedImapJob::CachedImapJob( const QString& string1, JobType type,
00097 KMFolderCachedImap* folder )
00098 : FolderJob( type ), mFolder(folder), mMsg( 0 ), mString( string1 ),
00099 mParentFolder ( 0 )
00100 {
00101 assert( folder );
00102 assert( type != tDeleteMessage );
00103 }
00104
00105
00106 CachedImapJob::CachedImapJob( const QStringList& foldersOrMsgs, JobType type,
00107 KMFolderCachedImap* folder )
00108 : FolderJob( type ), mFolder( folder ), mFoldersOrMessages( foldersOrMsgs ),
00109 mMsg( 0 ), mParentFolder( 0 )
00110 {
00111 assert( folder );
00112 }
00113
00114
00115 CachedImapJob::CachedImapJob( JobType type, KMFolderCachedImap* folder )
00116 : FolderJob( type ), mFolder( folder ), mMsg( 0 ), mParentFolder ( 0 )
00117 {
00118 assert( folder );
00119 }
00120
00121 CachedImapJob::~CachedImapJob()
00122 {
00123 mAccount->mJobList.remove(this);
00124 }
00125
00126 void CachedImapJob::execute()
00127 {
00128 mSentBytes = 0;
00129
00130 if( !mFolder ) {
00131 if( !mMsgList.isEmpty() ) {
00132 mFolder = static_cast<KMFolderCachedImap*>(mMsgList.first()->storage());
00133 }
00134 }
00135 assert( mFolder );
00136 mAccount = mFolder->account();
00137 assert( mAccount != 0 );
00138 if( mAccount->makeConnection() != ImapAccountBase::Connected ) {
00139
00140 kdDebug(5006) << "mAccount->makeConnection() failed" << endl;
00141 mPassiveDestructor = true;
00142 delete this;
00143 return;
00144 } else
00145 mPassiveDestructor = false;
00146
00147
00148 mAccount->mJobList.append(this);
00149
00156 if ( mAccount->groupwareType() == KMAcctCachedImap::GroupwareScalix ) {
00157 if ( !mAccount->sentCustomLoginCommand() ) {
00158 QByteArray packedArgs;
00159 QDataStream stream( packedArgs, IO_WriteOnly );
00160
00161 const QString command = QString( "X-SCALIX-ID " );
00162 const QString argument = QString( "(\"name\" \"Evolution\" \"version\" \"2.10.0\")" );
00163
00164 stream << (int) 'X' << 'N' << command << argument;
00165
00166 const KURL url = mAccount->getUrl();
00167
00168 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00169 jd.items << mFolder->label();
00170 KIO::SimpleJob *simpleJob = KIO::special( url.url(), packedArgs, false );
00171 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00172 mAccount->insertJob(simpleJob, jd);
00173
00174 mAccount->setSentCustomLoginCommand( true );
00175 }
00176 }
00177
00178 switch( mType ) {
00179 case tGetMessage: slotGetNextMessage(); break;
00180 case tPutMessage: slotPutNextMessage(); break;
00181 case tDeleteMessage: slotDeleteNextMessages(); break;
00182 case tExpungeFolder: expungeFolder(); break;
00183 case tAddSubfolders: slotAddNextSubfolder(); break;
00184 case tDeleteFolders: slotDeleteNextFolder(); break;
00185 case tCheckUidValidity: checkUidValidity(); break;
00186 case tRenameFolder: renameFolder(mString); break;
00187 case tListMessages: listMessages(); break;
00188 default:
00189 assert( 0 );
00190 }
00191 }
00192
00193 void CachedImapJob::listMessages()
00194 {
00195 KURL url = mAccount->getUrl();
00196 url.setPath( mFolder->imapPath() + ";UID=1:*;SECTION=FLAGS RFC822.SIZE");
00197
00198 KIO::SimpleJob *job = KIO::get(url, false, false);
00199 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00200 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00201 jd.cancellable = true;
00202 mAccount->insertJob( job, jd );
00203 connect( job, SIGNAL( result(KIO::Job *) ),
00204 this, SLOT( slotListMessagesResult( KIO::Job* ) ) );
00205
00206 connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00207 mFolder, SLOT( slotGetMessagesData( KIO::Job* , const QByteArray& ) ) );
00208 }
00209
00210 void CachedImapJob::slotDeleteNextMessages( KIO::Job* job )
00211 {
00212 if (job) {
00213 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00214 if ( it == mAccount->jobsEnd() ) {
00215 delete this;
00216 return;
00217 }
00218
00219 if( job->error() ) {
00220 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00221 delete this;
00222 return;
00223 }
00224 mAccount->removeJob(it);
00225 }
00226
00227 if( mFoldersOrMessages.isEmpty() ) {
00228
00229 delete this;
00230 return;
00231 }
00232
00233 QString uids = mFoldersOrMessages.front(); mFoldersOrMessages.pop_front();
00234
00235 KURL url = mAccount->getUrl();
00236 url.setPath( mFolder->imapPath() +
00237 QString::fromLatin1(";UID=%1").arg(uids) );
00238
00239 KIO::SimpleJob *simpleJob = KIO::file_delete( url, false );
00240 KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob );
00241 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00242 mAccount->insertJob( simpleJob, jd );
00243 connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00244 this, SLOT( slotDeleteNextMessages(KIO::Job *) ) );
00245 }
00246
00247 void CachedImapJob::expungeFolder()
00248 {
00249 KURL url = mAccount->getUrl();
00250
00251 url.setPath( mFolder->imapPath() + QString::fromLatin1(";UID=*") );
00252
00253 KIO::SimpleJob *job = KIO::file_delete( url, false );
00254 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00255 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00256 mAccount->insertJob( job, jd );
00257 connect( job, SIGNAL( result(KIO::Job *) ),
00258 this, SLOT( slotExpungeResult(KIO::Job *) ) );
00259 }
00260
00261 void CachedImapJob::slotExpungeResult( KIO::Job * job )
00262 {
00263 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00264 if ( it == mAccount->jobsEnd() ) {
00265 delete this;
00266 return;
00267 }
00268
00269 if (job->error()) {
00270 mErrorCode = job->error();
00271 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00272 }
00273 else
00274 mAccount->removeJob(it);
00275
00276 delete this;
00277 }
00278
00279 void CachedImapJob::slotGetNextMessage(KIO::Job * job)
00280 {
00281 if (job) {
00282 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00283 if ( it == mAccount->jobsEnd() ) {
00284 delete this;
00285 return;
00286 }
00287
00288 if (job->error()) {
00289 mErrorCode = job->error();
00290 mAccount->handleJobError( job, i18n( "Error while retrieving message on the server: " ) + '\n' );
00291 delete this;
00292 return;
00293 }
00294
00295 ulong size = 0;
00296 if ((*it).data.size() > 0) {
00297 ulong uid = mMsg->UID();
00298 size = mMsg->msgSizeServer();
00299
00300
00301 size_t dataSize = (*it).data.size();
00302 dataSize = Util::crlf2lf( (*it).data.data(), dataSize );
00303 (*it).data.resize( dataSize );
00304
00305 mMsg->setComplete( true );
00306 mMsg->fromByteArray( (*it).data );
00307 mMsg->setUID(uid);
00308 mMsg->setMsgSizeServer(size);
00309 mMsg->setTransferInProgress( false );
00310 int index = -1;
00311 mFolder->open( "KMFolderCachedImap::slotGetNextMessage" );
00312 mFolder->addMsgInternal( mMsg, true, &index );
00313
00314 if ( kmkernel->iCalIface().isResourceFolder( mFolder->folder() ) ) {
00315 mFolder->setStatus( index, KMMsgStatusRead, false );
00316 }
00317 mFolder->close( "KMFolderCachedImap::slotGetNextMessage" );
00318
00319 emit messageRetrieved( mMsg );
00320 if ( index >= 0 ) mFolder->unGetMsg( index );
00321 } else {
00322 emit messageRetrieved( 0 );
00323 }
00324 mMsg = 0;
00325
00326 mSentBytes += size;
00327 emit progress( mSentBytes, mTotalBytes );
00328 mAccount->removeJob(it);
00329 } else
00330 mFolder->quiet( true );
00331
00332 if( mMsgsForDownload.isEmpty() ) {
00333 mFolder->quiet( false );
00334 delete this;
00335 return;
00336 }
00337
00338 MsgForDownload mfd = mMsgsForDownload.front(); mMsgsForDownload.pop_front();
00339
00340 mMsg = new KMMessage;
00341 mMsg->setUID(mfd.uid);
00342 mMsg->setMsgSizeServer(mfd.size);
00343 if( mfd.flags > 0 )
00344 KMFolderImap::flagsToStatus(mMsg, mfd.flags, true, GlobalSettings::allowLocalFlags() ? mFolder->permanentFlags() : INT_MAX);
00345 KURL url = mAccount->getUrl();
00346 url.setPath(mFolder->imapPath() + QString(";UID=%1;SECTION=BODY.PEEK[]").arg(mfd.uid));
00347
00348 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00349 jd.cancellable = true;
00350 mMsg->setTransferInProgress(true);
00351 KIO::SimpleJob *simpleJob = KIO::get(url, false, false);
00352 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00353 mAccount->insertJob(simpleJob, jd);
00354 connect(simpleJob, SIGNAL(processedSize(KIO::Job *, KIO::filesize_t)),
00355 this, SLOT(slotProcessedSize(KIO::Job *, KIO::filesize_t)));
00356 connect(simpleJob, SIGNAL(result(KIO::Job *)),
00357 this, SLOT(slotGetNextMessage(KIO::Job *)));
00358 connect(simpleJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00359 mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00360 }
00361
00362 void CachedImapJob::slotProcessedSize(KIO::Job *, KIO::filesize_t processed)
00363 {
00364 emit progress( mSentBytes + processed, mTotalBytes );
00365 }
00366
00367 void CachedImapJob::slotPutNextMessage()
00368 {
00369 mMsg = 0;
00370
00371
00372 if( !mMsgList.isEmpty() ) {
00373 mMsg = mMsgList.first();
00374 mMsgList.removeFirst();
00375 }
00376
00377
00378 while( mMsg == 0 && !mSerNumMsgList.isEmpty() ) {
00379 unsigned long serNum = mSerNumMsgList.first();
00380 mSerNumMsgList.pop_front();
00381
00382
00383 int i = 0;
00384 KMFolder* aFolder = 0;
00385 KMMsgDict::instance()->getLocation( serNum, &aFolder, &i );
00386 if( mFolder->folder() != aFolder )
00387
00388 continue;
00389 mMsg = mFolder->getMsg( i );
00390 }
00391
00392 if( !mMsg ) {
00393
00394 delete this;
00395 return;
00396 }
00397
00398 KURL url = mAccount->getUrl();
00399 QString flags = KMFolderImap::statusToFlags( mMsg->status(), mFolder->permanentFlags() );
00400 url.setPath( mFolder->imapPath() + ";SECTION=" + flags );
00401
00402 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00403
00404 mMsg->setUID( 0 );
00405 QCString cstr(mMsg->asString());
00406 int a = cstr.find("\nX-UID: ");
00407 int b = cstr.find('\n', a);
00408 if (a != -1 && b != -1 && cstr.find("\n\n") > a) cstr.remove(a, b-a);
00409 QCString mData(cstr.length() + cstr.contains('\n'));
00410 unsigned int i = 0;
00411 for( char *ch = cstr.data(); *ch; ch++ ) {
00412 if ( *ch == '\n' ) {
00413 mData.at(i) = '\r';
00414 i++;
00415 }
00416 mData.at(i) = *ch; i++;
00417 }
00418 jd.data = mData;
00419 jd.msgList.append( mMsg );
00420
00421 mMsg->setTransferInProgress(true);
00422 KIO::SimpleJob *simpleJob = KIO::put(url, 0, false, false, false);
00423 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00424 mAccount->insertJob(simpleJob, jd);
00425 connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00426 SLOT( slotPutMessageResult(KIO::Job *) ) );
00427 connect( simpleJob, SIGNAL( dataReq(KIO::Job *, QByteArray &) ),
00428 SLOT( slotPutMessageDataReq(KIO::Job *, QByteArray &) ) );
00429 connect( simpleJob, SIGNAL( data(KIO::Job *, const QByteArray &) ),
00430 mFolder, SLOT( slotSimpleData(KIO::Job *, const QByteArray &) ) );
00431 connect( simpleJob, SIGNAL(infoMessage(KIO::Job *, const QString &)),
00432 SLOT(slotPutMessageInfoData(KIO::Job *, const QString &)) );
00433
00434 }
00435
00436
00437
00438 void CachedImapJob::slotPutMessageDataReq(KIO::Job *job, QByteArray &data)
00439 {
00440 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00441 if ( it == mAccount->jobsEnd() ) {
00442 delete this;
00443 return;
00444 }
00445 if ((*it).data.size() - (*it).offset > 0x8000) {
00446 data.duplicate((*it).data.data() + (*it).offset, 0x8000);
00447 (*it).offset += 0x8000;
00448 } else if ((*it).data.size() - (*it).offset > 0) {
00449 data.duplicate((*it).data.data() + (*it).offset,
00450 (*it).data.size() - (*it).offset);
00451 (*it).offset = (*it).data.size();
00452 } else
00453 data.resize(0);
00454 }
00455
00456
00457 void CachedImapJob::slotPutMessageInfoData( KIO::Job *job, const QString &data )
00458 {
00459 KMFolderCachedImap *imapFolder = static_cast<KMFolderCachedImap*>( mDestFolder->storage() );
00460 if ( imapFolder ) {
00461 KMAcctCachedImap *account = imapFolder->account();
00462 ImapAccountBase::JobIterator it = account->findJob( job );
00463 if ( it == account->jobsEnd() ) {
00464 return;
00465 }
00466
00467 if ( data.find( "UID" ) != -1 && mMsg ) {
00468 int uid = ( data.right( data.length() - 4 ) ).toInt();
00469 kdDebug( 5006 ) << k_funcinfo << "Server told us uid is: " << uid << endl;
00470 mMsg->setUID( uid );
00471 }
00472 }
00473 }
00474
00475
00476
00477 void CachedImapJob::slotPutMessageResult(KIO::Job *job)
00478 {
00479 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00480 if ( it == mAccount->jobsEnd() ) {
00481 delete this;
00482 return;
00483 }
00484
00485 if ( job->error() ) {
00486 bool cont = mAccount->handlePutError( job, *it, mFolder->folder() );
00487 if ( !cont ) {
00488 delete this;
00489 } else {
00490 mMsg = 0;
00491 slotPutNextMessage();
00492 }
00493 return;
00494 }
00495
00496 emit messageStored( mMsg );
00497
00498
00499 ++mSentBytes;
00500 emit progress( mSentBytes, mTotalBytes );
00501
00502 int i;
00503 if( ( i = mFolder->find(mMsg) ) != -1 ) {
00504
00505
00506
00507
00508
00509 if ( mMsg->UID() == 0 ) {
00510 mFolder->removeMsg(i);
00511 } else {
00512
00513 bool b = kmkernel->iCalIface().isResourceQuiet();
00514 kmkernel->iCalIface().setResourceQuiet( true );
00515
00516 mFolder->takeTemporarily( i );
00517 mFolder->addMsgKeepUID( mMsg );
00518 mMsg->setTransferInProgress( false );
00519
00520 kmkernel->iCalIface().setResourceQuiet( b );
00521 }
00522 }
00523 mMsg = NULL;
00524 mAccount->removeJob( it );
00525 slotPutNextMessage();
00526 }
00527
00528
00529 void CachedImapJob::slotAddNextSubfolder( KIO::Job * job )
00530 {
00531 if (job) {
00532 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00533 if ( it == mAccount->jobsEnd() ) {
00534 delete this;
00535 return;
00536 }
00537
00538
00539 bool silentUpload = static_cast<KMFolderCachedImap*>((*it).parent->storage())->silentUpload();
00540 static_cast<KMFolderCachedImap*>((*it).parent->storage())->setSilentUpload( false );
00541
00542 if ( job->error() && !silentUpload ) {
00543 QString myError = "<p><b>" + i18n("Error while uploading folder")
00544 + "</b></p><p>" + i18n("Could not make the folder <b>%1</b> on the server.").arg((*it).items[0])
00545 + "</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>";
00546 mAccount->handleJobError( job, myError );
00547 }
00548
00549 if( job->error() ) {
00550 delete this;
00551 return;
00552 } else {
00553 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>( (*it).current->storage() );
00554 KMFolderCachedImap* parentStorage = static_cast<KMFolderCachedImap*>( (*it).parent->storage() );
00555 Q_ASSERT( storage );
00556 Q_ASSERT( parentStorage );
00557 if ( storage->imapPath().isEmpty() ) {
00558 QString path = mAccount->createImapPath( parentStorage->imapPath(), storage->folder()->name() );
00559 if ( !storage->imapPathForCreation().isEmpty() )
00560 path = storage->imapPathForCreation();
00561 storage->setImapPath( path );
00562 storage->writeConfig();
00563 }
00564 }
00565 mAccount->removeJob( it );
00566 }
00567
00568 if (mFolderList.isEmpty()) {
00569
00570 delete this;
00571 return;
00572 }
00573
00574 KMFolderCachedImap *folder = mFolderList.front();
00575 mFolderList.pop_front();
00576 KURL url = mAccount->getUrl();
00577 QString path = mAccount->createImapPath( mFolder->imapPath(),
00578 folder->folder()->name() );
00579 if ( !folder->imapPathForCreation().isEmpty() ) {
00580
00581 path = folder->imapPathForCreation();
00582 }
00583 url.setPath( path );
00584
00585 if ( mAccount->groupwareType() != KMAcctCachedImap::GroupwareScalix ) {
00586
00587
00588
00589 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00590 jd.items << folder->label();
00591 jd.current = folder->folder();
00592 KIO::SimpleJob *simpleJob = KIO::mkdir(url);
00593 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00594 mAccount->insertJob(simpleJob, jd);
00595 connect( simpleJob, SIGNAL(result(KIO::Job *)),
00596 this, SLOT(slotAddNextSubfolder(KIO::Job *)) );
00597 } else {
00598 QByteArray packedArgs;
00599 QDataStream stream( packedArgs, IO_WriteOnly );
00600
00601 const QString command = QString( "X-CREATE-SPECIAL" );
00602 const QString argument = QString( "%1 %2" ).arg( Scalix::Utils::contentsTypeToScalixId( folder->contentsType() ) )
00603 .arg( path );
00604
00605 stream << (int) 'X' << 'N' << command << argument;
00606
00607 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00608 jd.items << folder->label();
00609 jd.current = folder->folder();
00610 KIO::SimpleJob *simpleJob = KIO::special( url.url(), packedArgs, false );
00611 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00612 mAccount->insertJob(simpleJob, jd);
00613 connect( simpleJob, SIGNAL(result(KIO::Job *)),
00614 this, SLOT(slotAddNextSubfolder(KIO::Job *)) );
00615 }
00616 }
00617
00618
00619 void CachedImapJob::slotDeleteNextFolder( KIO::Job *job )
00620 {
00621 if (job) {
00622 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00623 if ( it == mAccount->jobsEnd() ) {
00624 delete this;
00625 return;
00626 }
00627
00628 mAccount->removeDeletedFolder( (*it).path );
00629
00630 if( job->error() ) {
00631 mAccount->handleJobError( job, i18n( "Error while deleting folder %1 on the server: " ).arg( (*it).path ) + '\n' );
00632 delete this;
00633 return;
00634 }
00635 mAccount->removeJob(it);
00636 }
00637
00638 if( mFoldersOrMessages.isEmpty() ) {
00639
00640 delete this;
00641 return;
00642 }
00643
00644 QString folderPath = mFoldersOrMessages.front();
00645 mFoldersOrMessages.pop_front();
00646 KURL url = mAccount->getUrl();
00647 url.setPath(folderPath);
00648 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00649 jd.path = url.path();
00650 KIO::SimpleJob *simpleJob = KIO::file_delete(url, false);
00651 KIO::Scheduler::assignJobToSlave(mAccount->slave(), simpleJob);
00652 mAccount->insertJob(simpleJob, jd);
00653 connect( simpleJob, SIGNAL( result(KIO::Job *) ),
00654 SLOT( slotDeleteNextFolder(KIO::Job *) ) );
00655 }
00656
00657 void CachedImapJob::checkUidValidity()
00658 {
00659 KURL url = mAccount->getUrl();
00660 url.setPath( mFolder->imapPath() + ";UID=0:0" );
00661
00662 ImapAccountBase::jobData jd( url.url(), mFolder->folder() );
00663 jd.cancellable = true;
00664
00665 KIO::SimpleJob *job = KIO::get( url, false, false );
00666 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00667 mAccount->insertJob( job, jd );
00668 connect( job, SIGNAL(result(KIO::Job *)),
00669 SLOT(slotCheckUidValidityResult(KIO::Job *)) );
00670 connect( job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00671 mFolder, SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00672 }
00673
00674 void CachedImapJob::slotCheckUidValidityResult(KIO::Job * job)
00675 {
00676 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00677 if ( it == mAccount->jobsEnd() ) {
00678 delete this;
00679 return;
00680 }
00681
00682 if( job->error() ) {
00683 mErrorCode = job->error();
00684 mAccount->handleJobError( job, i18n( "Error while reading folder %1 on the server: " ).arg( (*it).parent->label() ) + '\n' );
00685 delete this;
00686 return;
00687 }
00688
00689
00690 QCString cstr((*it).data.data(), (*it).data.size() + 1);
00691 int a = cstr.find("X-uidValidity: ");
00692 if (a < 0) {
00693
00694
00695 kdDebug(5006) << "No uidvalidity available for folder "
00696 << mFolder->name() << endl;
00697 }
00698 else {
00699 int b = cstr.find("\r\n", a);
00700 if ( (b - a - 15) >= 0 ) {
00701 QString uidv = cstr.mid(a + 15, b - a - 15);
00702
00703
00704 if( !mFolder->uidValidity().isEmpty() && mFolder->uidValidity() != uidv ) {
00705
00706
00707 mFolder->expunge();
00708 mFolder->setLastUid( 0 );
00709 mFolder->clearUidMap();
00710 }
00711 } else
00712 kdDebug(5006) << "No uidvalidity available for folder "
00713 << mFolder->name() << endl;
00714 }
00715
00716 a = cstr.find( "X-PermanentFlags: " );
00717 if ( a < 0 ) {
00718 kdDebug(5006) << "no PERMANENTFLAGS response? assumming custom flags are not available" << endl;
00719 } else {
00720 int b = cstr.find( "\r\n", a );
00721 if ( (b - a - 18) >= 0 ) {
00722 int flags = cstr.mid( a + 18, b - a - 18 ).toInt();
00723 emit permanentFlags( flags );
00724 } else {
00725 kdDebug(5006) << "PERMANENTFLAGS response broken, assumming custom flags are not available" << endl;
00726 }
00727 }
00728
00729 mAccount->removeJob(it);
00730 delete this;
00731 }
00732
00733
00734 void CachedImapJob::renameFolder( const QString &newName )
00735 {
00736 mNewName = newName;
00737
00738
00739 KURL urlSrc = mAccount->getUrl();
00740 mOldImapPath = mFolder->imapPath();
00741 urlSrc.setPath( mOldImapPath );
00742
00743
00744 KURL urlDst = mAccount->getUrl();
00745 mNewImapPath = mFolder->imapPath();
00746
00747 mNewImapPath.truncate( mNewImapPath.length() - mFolder->folder()->name().length() - 1);
00748 mNewImapPath += newName + '/';
00749 urlDst.setPath( mNewImapPath );
00750
00751 ImapAccountBase::jobData jd( newName, mFolder->folder() );
00752 jd.path = mNewImapPath;
00753
00754 KIO::SimpleJob *simpleJob = KIO::rename( urlSrc, urlDst, false );
00755 KIO::Scheduler::assignJobToSlave( mAccount->slave(), simpleJob );
00756 mAccount->insertJob( simpleJob, jd );
00757 connect( simpleJob, SIGNAL(result(KIO::Job *)),
00758 SLOT(slotRenameFolderResult(KIO::Job *)) );
00759 }
00760
00761 static void renameChildFolders( KMFolderDir* dir, const QString& oldPath,
00762 const QString& newPath )
00763 {
00764 if( dir ) {
00765 KMFolderNode *node = dir->first();
00766 while( node ) {
00767 if( !node->isDir() ) {
00768 KMFolderCachedImap* imapFolder =
00769 static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
00770 if ( !imapFolder->imapPath().isEmpty() )
00771
00772 if( imapFolder->imapPath().find( oldPath ) == 0 ) {
00773 QString p = imapFolder->imapPath();
00774 p = p.mid( oldPath.length() );
00775 p.prepend( newPath );
00776 imapFolder->setImapPath( p );
00777 renameChildFolders( imapFolder->folder()->child(), oldPath, newPath );
00778 }
00779 }
00780 node = dir->next();
00781 }
00782 }
00783 }
00784
00785 void CachedImapJob::revertLabelChange()
00786 {
00787 QMap<QString, KMAcctCachedImap::RenamedFolder>::ConstIterator renit = mAccount->renamedFolders().find( mFolder->imapPath() );
00788 Q_ASSERT( renit != mAccount->renamedFolders().end() );
00789 if ( renit != mAccount->renamedFolders().end() ) {
00790 mFolder->folder()->setLabel( (*renit).mOldLabel );
00791 mAccount->removeRenamedFolder( mFolder->imapPath() );
00792 kmkernel->dimapFolderMgr()->contentsChanged();
00793 }
00794 }
00795
00796 void CachedImapJob::renameOnDisk()
00797 {
00798 QString oldName = mFolder->name();
00799 QString oldPath = mFolder->imapPath();
00800 mAccount->removeRenamedFolder( oldPath );
00801 mFolder->setImapPath( mNewImapPath );
00802 mFolder->FolderStorage::rename( mNewName );
00803
00804 if( oldPath.endsWith( "/" ) ) oldPath.truncate( oldPath.length() -1 );
00805 QString newPath = mFolder->imapPath();
00806 if( newPath.endsWith( "/" ) ) newPath.truncate( newPath.length() -1 );
00807 renameChildFolders( mFolder->folder()->child(), oldPath, newPath );
00808 kmkernel->dimapFolderMgr()->contentsChanged();
00809 }
00810
00811 void CachedImapJob::slotSubscribtionChange1Failed( const QString &errorMessage )
00812 {
00813 KMessageBox::sorry( 0, i18n( "Error while trying to subscribe to the renamed folder %1.\n"
00814 "Renaming itself was successful, but the renamed folder might disappear "
00815 "from the folder list after the next sync since it is unsubscribed on the server.\n"
00816 "You can try to manually subscribe to the folder yourself.\n\n"
00817 "%2" )
00818 .arg( mFolder->label() ).arg( errorMessage ) );
00819 delete this;
00820 }
00821
00822 void CachedImapJob::slotSubscribtionChange2Failed( const QString &errorMessage )
00823 {
00824 kdWarning(5006) << k_funcinfo << errorMessage << endl;
00825
00826 delete this;
00827 }
00828
00829 void CachedImapJob::slotSubscribtionChange1Done( const QString&, bool )
00830 {
00831 disconnect( mAccount, SIGNAL( subscriptionChanged( const QString&, bool ) ),
00832 this, SLOT( slotSubscribtionChange1Done( const QString&, bool ) ) );
00833 connect( mAccount, SIGNAL( subscriptionChanged( const QString&, bool ) ),
00834 this, SLOT( slotSubscribtionChange2Done( const QString&, bool ) ) );
00835 disconnect( mAccount, SIGNAL( subscriptionChangeFailed( const QString& ) ),
00836 this, SLOT( slotSubscribtionChange1Failed( const QString& ) ) );
00837 connect( mAccount, SIGNAL( subscriptionChangeFailed( const QString& ) ),
00838 this, SLOT( slotSubscribtionChange2Failed( const QString& ) ) );
00839
00840 mAccount->changeSubscription( false, mOldImapPath, true );
00841 }
00842
00843 void CachedImapJob::slotSubscribtionChange2Done( const QString&, bool )
00844 {
00845
00846 delete this;
00847 }
00848
00849 void CachedImapJob::slotRenameFolderResult( KIO::Job *job )
00850 {
00851 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00852 if ( it == mAccount->jobsEnd() ) {
00853 delete this;
00854 return;
00855 }
00856
00857 if( job->error() ) {
00858 revertLabelChange();
00859 const QString errorMessage = i18n( "Error while trying to rename folder %1" ).arg( mFolder->label() );
00860 mAccount->handleJobError( job, errorMessage );
00861 delete this;
00862 } else {
00863
00864 mAccount->removeJob( it );
00865 renameOnDisk();
00866
00867
00868
00869
00870 connect( mAccount, SIGNAL( subscriptionChangeFailed( const QString& ) ),
00871 this, SLOT( slotSubscribtionChange1Failed( const QString& ) ) );
00872 connect( mAccount, SIGNAL( subscriptionChanged( const QString&, bool ) ),
00873 this, SLOT( slotSubscribtionChange1Done( const QString&, bool ) ) );
00874 mAccount->changeSubscription( true, mNewImapPath, true );
00875 }
00876 }
00877
00878 void CachedImapJob::slotListMessagesResult( KIO::Job * job )
00879 {
00880 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
00881 if ( it == mAccount->jobsEnd() ) {
00882 delete this;
00883 return;
00884 }
00885
00886 if (job->error()) {
00887 mErrorCode = job->error();
00888 mAccount->handleJobError( job, i18n( "Error while deleting messages on the server: " ) + '\n' );
00889 }
00890 else
00891 mAccount->removeJob(it);
00892
00893 delete this;
00894 }
00895
00896
00897 void CachedImapJob::setParentFolder( const KMFolderCachedImap* parent )
00898 {
00899 mParentFolder = const_cast<KMFolderCachedImap*>( parent );
00900 }
00901
00902 }
00903
00904 #include "cachedimapjob.moc"