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