00001
00032
#ifdef HAVE_CONFIG_H
00033
#include <config.h>
00034
#endif
00035
00036
#include <errno.h>
00037
00038
#include "kmkernel.h"
00039
#include "kmfoldercachedimap.h"
00040
#include "undostack.h"
00041
#include "kmfoldermgr.h"
00042
#include "kmmessage.h"
00043
#include "kmacctcachedimap.h"
00044
#include "kmacctmgr.h"
00045
#include "kmailicalifaceimpl.h"
00046
#include "kmfolder.h"
00047
#include "kmdict.h"
00048
#include "acljobs.h"
00049
#include "broadcaststatus.h"
00050
using KPIM::BroadcastStatus;
00051
#include "progressmanager.h"
00052
00053
using KMail::CachedImapJob;
00054
using KMail::ImapAccountBase;
00055
#include "listjob.h"
00056
using KMail::ListJob;
00057
00058
#include <kapplication.h>
00059
#include <kmessagebox.h>
00060
#include <klocale.h>
00061
#include <kdebug.h>
00062
#include <kconfig.h>
00063
#include <kio/global.h>
00064
#include <kio/scheduler.h>
00065
#include <qbuffer.h>
00066
#include <qfile.h>
00067
#include <qlabel.h>
00068
#include <qlayout.h>
00069
#include <qvaluelist.h>
00070
00071
#define UIDCACHE_VERSION 1
00072
00073
00074 DImapTroubleShootDialog::DImapTroubleShootDialog(
QWidget* parent,
00075
const char* name )
00076 : KDialogBase( Plain, i18n( "Troubleshooting IMAP Cache" ),
00077 Cancel | User1 | User2, Cancel, parent, name, true ),
00078 rc( Cancel )
00079 {
00080
QFrame* page = plainPage();
00081
QVBoxLayout *topLayout =
new QVBoxLayout( page, 0 );
00082
QString txt = i18n(
"<p><b>Troubleshooting the IMAP cache.</b></p>"
00083
"<p>If you have problems with synchronizing an IMAP "
00084
"folder, you should first try rebuilding the index "
00085
"file. This will take some time to rebuild, but will "
00086
"not cause any problems.</p><p>If that is not enough, "
00087
"you can try refreshing the IMAP cache. If you do this, "
00088
"you will loose all your local changes for this folder "
00089
"and all it's subfolders.</p>" );
00090 topLayout->addWidget(
new QLabel( txt, page ) );
00091 enableButtonSeparator(
true );
00092
00093 setButtonText( User1, i18n(
"Refresh &Cache" ) );
00094 setButtonText( User2, i18n(
"Rebuild &Index" ) );
00095
00096 connect(
this, SIGNAL( user1Clicked () ),
this, SLOT( slotRebuildCache() ) );
00097 connect(
this, SIGNAL( user2Clicked () ),
this, SLOT( slotRebuildIndex() ) );
00098 }
00099
00100
int DImapTroubleShootDialog::run()
00101 {
00102 DImapTroubleShootDialog d;
00103 d.exec();
00104
return d.rc;
00105 }
00106
00107
void DImapTroubleShootDialog::slotRebuildCache()
00108 {
00109 rc = User1;
00110 done( User1 );
00111 }
00112
00113
void DImapTroubleShootDialog::slotRebuildIndex()
00114 {
00115 rc = User2;
00116 done( User2 );
00117 }
00118
00119
00120 KMFolderCachedImap::KMFolderCachedImap(
KMFolder* folder,
const char* aName )
00121 : KMFolderMaildir( folder, aName ),
00122 mSyncState( SYNC_STATE_INITIAL ), mContentState( imapNoInformation ),
00123 mSubfolderState( imapNoInformation ), mIsSelected( false ),
00124 mCheckFlags( true ), mAccount( NULL ), uidMapDirty( true ),
00125 uidWriteTimer( -1 ), mLastUid( 0 ), mTentativeHighestUid( 0 ),
00126 mUserRights( 0 ), mFolderRemoved( false ),
00127 mRecurse( true ),
00128 mContentsTypeChanged( false ), mStatusChangedLocally( false )
00129 {
00130 setUidValidity(
"");
00131 readUidCache();
00132
00133 mProgress = 0;
00134 }
00135
00136 KMFolderCachedImap::~KMFolderCachedImap()
00137 {
00138
if( !mFolderRemoved ) {
00139
00140 KConfig* config = KMKernel::config();
00141 KConfigGroupSaver saver( config,
"Folder-" + folder()->
idString() );
00142 config->writeEntry(
"ImapPath", mImapPath );
00143 config->writeEntry(
"NoContent", mNoContent );
00144 config->writeEntry(
"ReadOnly", mReadOnly );
00145 config->writeEntry(
"StatusChangedLocally", mStatusChangedLocally );
00146
00147 writeUidCache();
00148 }
00149
00150
if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed( folder() );
00151 }
00152
00153
void KMFolderCachedImap::initializeFrom( KMFolderCachedImap* parent )
00154 {
00155 setAccount( parent->account() );
00156
00157
00158 mAccount->removeDeletedFolder( imapPath() );
00159 setUserRights( parent->userRights() );
00160 }
00161
00162
void KMFolderCachedImap::readConfig()
00163 {
00164 KConfig* config = KMKernel::config();
00165 KConfigGroupSaver saver( config,
"Folder-" + folder()->
idString() );
00166
if( mImapPath.isEmpty() ) mImapPath = config->readEntry(
"ImapPath" );
00167
if(
QString( name() ).upper() ==
"INBOX" && mImapPath ==
"/INBOX/" )
00168 {
00169 folder()->setLabel( i18n(
"inbox" ) );
00170
00171 folder()->setSystemFolder(
true );
00172 }
00173 mNoContent = config->readBoolEntry(
"NoContent",
false );
00174 mReadOnly = config->readBoolEntry(
"ReadOnly",
false );
00175
00176 KMFolderMaildir::readConfig();
00177 mContentsTypeChanged =
false;
00178 mStatusChangedLocally =
00179 config->readBoolEntry(
"StatusChangedLocally",
false );
00180 }
00181
00182
void KMFolderCachedImap::remove()
00183 {
00184 mFolderRemoved =
true;
00185
00186
QString part1 = folder()->path() +
"/." + dotEscape(name());
00187
QString uidCacheFile = part1 +
".uidcache";
00188
00189
00190
if( QFile::exists(uidCacheFile) )
00191 unlink( QFile::encodeName( uidCacheFile ) );
00192 KIO::del( KURL::fromPathOrURL( part1 +
".directory" ) );
00193
00194
FolderStorage::remove();
00195 }
00196
00197
QString KMFolderCachedImap::uidCacheLocation()
const
00198
{
00199
QString sLocation(folder()->path());
00200
if (!sLocation.isEmpty()) sLocation +=
'/';
00201
return sLocation +
'.' + dotEscape(
fileName()) +
".uidcache";
00202 }
00203
00204
int KMFolderCachedImap::readUidCache()
00205 {
00206
QFile uidcache( uidCacheLocation() );
00207
if( uidcache.open( IO_ReadOnly ) ) {
00208
char buf[1024];
00209
int len = uidcache.readLine( buf,
sizeof(buf) );
00210
if( len > 0 ) {
00211
int cacheVersion;
00212 sscanf( buf,
"# KMail-UidCache V%d\n", &cacheVersion );
00213
if( cacheVersion == UIDCACHE_VERSION ) {
00214 len = uidcache.readLine( buf,
sizeof(buf) );
00215
if( len > 0 ) {
00216 setUidValidity( QString::fromLocal8Bit( buf).stripWhiteSpace() );
00217 len = uidcache.readLine( buf,
sizeof(buf) );
00218
if( len > 0 ) {
00219
00220 setLastUid( QString::fromLocal8Bit( buf).stripWhiteSpace().toULong() );
00221
return 0;
00222 }
00223 }
00224 }
00225 }
00226 }
00227
return -1;
00228 }
00229
00230
int KMFolderCachedImap::writeUidCache()
00231 {
00232
if( uidValidity().isEmpty() || uidValidity() ==
"INVALID" ) {
00233
00234
if( QFile::exists( uidCacheLocation() ) )
00235 unlink( QFile::encodeName( uidCacheLocation() ) );
00236
return 0;
00237 }
00238
00239
QFile uidcache( uidCacheLocation() );
00240
if( uidcache.open( IO_WriteOnly ) ) {
00241
QTextStream str( &uidcache );
00242 str <<
"# KMail-UidCache V" << UIDCACHE_VERSION << endl;
00243 str << uidValidity() << endl;
00244 str << lastUid() << endl;
00245 uidcache.flush();
00246 fsync( uidcache.handle() );
00247 uidcache.close();
00248
return 0;
00249 }
else {
00250
return errno;
00251 }
00252 }
00253
00254
void KMFolderCachedImap::reloadUidMap()
00255 {
00256 uidMap.clear();
00257
open();
00258
for(
int i = 0; i <
count(); ++i ) {
00259 KMMsgBase *msg =
getMsgBase( i );
00260
if( !msg )
continue;
00261 ulong uid = msg->UID();
00262 uidMap.insert( uid, i );
00263 }
00264
close();
00265 uidMapDirty =
false;
00266 }
00267
00268
00269 KMMessage* KMFolderCachedImap::take(
int idx)
00270 {
00271 uidMapDirty =
true;
00272
return KMFolderMaildir::take(idx);
00273 }
00274
00275
00276
int KMFolderCachedImap::addMsgInternal( KMMessage* msg,
bool newMail,
00277
int* index_return )
00278 {
00279
00280 ulong uid = msg->UID();
00281
if( uid != 0 ) {
00282 uidMapDirty =
true;
00283 }
00284
00285
00286
int rc = KMFolderMaildir::addMsg(msg, index_return);
00287
00288
if( newMail && imapPath() ==
"/INBOX/" )
00289
00290 mAccount->processNewMsg( msg );
00291
00292
return rc;
00293 }
00294
00295
00296
int KMFolderCachedImap::addMsg(KMMessage* msg,
int* index_return)
00297 {
00298
00299 msg->removeHeaderField(
"X-UID" );
00300 msg->setUID( 0 );
00301
00302
00303
return addMsgInternal( msg,
false, index_return );
00304 }
00305
00306
00307
00308
void KMFolderCachedImap::removeMsg(
int idx,
bool imapQuiet)
00309 {
00310 uidMapDirty =
true;
00311
00312 KMFolderMaildir::removeMsg(idx,imapQuiet);
00313 }
00314
00315
bool KMFolderCachedImap::canRemoveFolder()
const {
00316
00317
if( folder() && folder()->child() && folder()->child()->count() > 0 )
00318
return false;
00319
00320
#if 0
00321
00322
return KMFolderMaildir::canRemoveFolder();
00323
#endif
00324
return true;
00325 }
00326
00327
00328
int KMFolderCachedImap::rename(
const QString& aName,
00329
KMFolderDir* )
00330 {
00331
if ( aName == name() )
00332
00333
return 0;
00334
00335
if( account() == 0 || imapPath().isEmpty() ) {
00336
QString err = i18n(
"You must synchronize with the server before renaming IMAP folders.");
00337 KMessageBox::error( 0, err );
00338
return -1;
00339 }
00340
00341
00342
00343 mAccount->addRenamedFolder( imapPath(), folder()->
label(), aName );
00344 folder()->setLabel( aName );
00345
00346
return 0;
00347 }
00348
00349
KMFolder* KMFolderCachedImap::trashFolder()
const
00350
{
00351
QString trashStr = account()->trash();
00352
return kmkernel->dimapFolderMgr()->findIdString( trashStr );
00353 }
00354
00355
void KMFolderCachedImap::setLastUid( ulong uid )
00356 {
00357 mLastUid = uid;
00358
if( uidWriteTimer == -1 )
00359
00360 uidWriteTimer = startTimer( 60000 );
00361 }
00362
00363
void KMFolderCachedImap::timerEvent(
QTimerEvent* )
00364 {
00365 killTimer( uidWriteTimer );
00366 uidWriteTimer = -1;
00367 writeUidCache();
00368 }
00369
00370 ulong KMFolderCachedImap::lastUid()
00371 {
00372
return mLastUid;
00373 }
00374
00375 KMMsgBase* KMFolderCachedImap::findByUID( ulong uid )
00376 {
00377
bool mapReloaded =
false;
00378
if( uidMapDirty ) {
00379 reloadUidMap();
00380 mapReloaded =
true;
00381 }
00382
00383
QMap<ulong,int>::Iterator it = uidMap.find( uid );
00384
if( it != uidMap.end() ) {
00385 KMMsgBase *msg =
getMsgBase( *it );
00386
if( msg && msg->UID() == uid )
00387
return msg;
00388 }
00389
00390
if( mapReloaded )
00391
00392
return 0;
00393
00394 reloadUidMap();
00395 it = uidMap.find( uid );
00396
if( it != uidMap.end() )
00397
00398
return getMsg( *it );
00399
00400
return 0;
00401 }
00402
00403
00404
00405 KMAcctCachedImap *KMFolderCachedImap::account()
const
00406
{
00407
if( (KMAcctCachedImap *)mAccount == 0 ) {
00408
00409 mAccount = static_cast<KMAcctCachedImap *>( kmkernel->acctMgr()->findByName( name() ) );
00410 }
00411
00412
return mAccount;
00413 }
00414
00415
void KMFolderCachedImap::slotTroubleshoot()
00416 {
00417
const int rc = DImapTroubleShootDialog::run();
00418
00419
if( rc == KDialogBase::User1 ) {
00420
00421
if( !account() ) {
00422 KMessageBox::sorry( 0, i18n(
"No account setup for this folder.\n"
00423
"Please try running a sync before this.") );
00424
return;
00425 }
00426
QString str = i18n(
"Are you sure you want to refresh the IMAP cache of "
00427
"the folder %1 and all it's subfolders?\nThis will "
00428
"remove all changes you have done locally to your "
00429
"folders").arg(
label() );
00430
QString s1 = i18n(
"Refresh IMAP Cache");
00431
QString s2 = i18n(
"&Refresh");
00432
if( KMessageBox::warningContinueCancel( 0, str, s1, s2 ) ==
00433 KMessageBox::Continue )
00434 account()->invalidateIMAPFolders(
this );
00435 }
else if( rc == KDialogBase::User2 ) {
00436
00437 createIndexFromContents();
00438 KMessageBox::information( 0, i18n(
"The index of this folder has been "
00439
"recreated." ) );
00440 }
00441 }
00442
00443
void KMFolderCachedImap::serverSync(
bool recurse )
00444 {
00445
if( mSyncState != SYNC_STATE_INITIAL ) {
00446
if( KMessageBox::warningYesNo( 0, i18n(
"Folder %1 is not in initial sync state (state was %2). Do you want to reset it to initial sync state and sync anyway?" ).arg( imapPath() ).arg( mSyncState ) ) == KMessageBox::Yes ) {
00447 mSyncState = SYNC_STATE_INITIAL;
00448 }
else return;
00449 }
00450
00451 mRecurse = recurse;
00452 assert( account() );
00453
00454 mAccount->mailCheckProgressItem()->reset();
00455 mAccount->mailCheckProgressItem()->setTotalItems( 100 );
00456 mProgress = 0;
00457
00458
#if 0
00459
if( mHoldSyncs ) {
00460
00461 account()->mailCheckProgressItem()->setProgress( 100 );
00462 mProgress = 100;
00463 newState( mProgress, i18n(
"Synchronization skipped"));
00464 mSyncState = SYNC_STATE_INITIAL;
00465 emit folderComplete(
this,
true );
00466
return;
00467 }
00468
#endif
00469
mTentativeHighestUid = 0;
00470
00471 serverSyncInternal();
00472 }
00473
00474
QString KMFolderCachedImap::state2String(
int state )
const
00475
{
00476
switch( state ) {
00477
case SYNC_STATE_INITIAL:
return "SYNC_STATE_INITIAL";
00478
case SYNC_STATE_PUT_MESSAGES:
return "SYNC_STATE_PUT_MESSAGES";
00479
case SYNC_STATE_UPLOAD_FLAGS:
return "SYNC_STATE_UPLOAD_FLAGS";
00480
case SYNC_STATE_CREATE_SUBFOLDERS:
return "SYNC_STATE_CREATE_SUBFOLDERS";
00481
case SYNC_STATE_LIST_SUBFOLDERS:
return "SYNC_STATE_LIST_SUBFOLDERS";
00482
case SYNC_STATE_LIST_SUBFOLDERS2:
return "SYNC_STATE_LIST_SUBFOLDERS2";
00483
case SYNC_STATE_DELETE_SUBFOLDERS:
return "SYNC_STATE_DELETE_SUBFOLDERS";
00484
case SYNC_STATE_LIST_MESSAGES:
return "SYNC_STATE_LIST_MESSAGES";
00485
case SYNC_STATE_DELETE_MESSAGES:
return "SYNC_STATE_DELETE_MESSAGES";
00486
case SYNC_STATE_GET_MESSAGES:
return "SYNC_STATE_GET_MESSAGES";
00487
case SYNC_STATE_EXPUNGE_MESSAGES:
return "SYNC_STATE_EXPUNGE_MESSAGES";
00488
case SYNC_STATE_HANDLE_INBOX:
return "SYNC_STATE_HANDLE_INBOX";
00489
case SYNC_STATE_GET_USERRIGHTS:
return "SYNC_STATE_GET_USERRIGHTS";
00490
case SYNC_STATE_GET_ACLS:
return "SYNC_STATE_GET_ACLS";
00491
case SYNC_STATE_SET_ACLS:
return "SYNC_STATE_SET_ACLS";
00492
case SYNC_STATE_FIND_SUBFOLDERS:
return "SYNC_STATE_FIND_SUBFOLDERS";
00493
case SYNC_STATE_SYNC_SUBFOLDERS:
return "SYNC_STATE_SYNC_SUBFOLDERS";
00494
case SYNC_STATE_CHECK_UIDVALIDITY:
return "SYNC_STATE_CHECK_UIDVALIDITY";
00495
case SYNC_STATE_RENAME_FOLDER:
return "SYNC_STATE_RENAME_FOLDER";
00496
default:
return "Unknown state";
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
void KMFolderCachedImap::serverSyncInternal()
00529 {
00530
00531
00532
00533
if( kmkernel->mailCheckAborted() ) {
00534 resetSyncState();
00535 emit folderComplete(
this,
false );
00536
return;
00537 }
00538
00539
00540
switch( mSyncState ) {
00541
case SYNC_STATE_INITIAL:
00542 {
00543 mProgress = 0;
00544 newState( mProgress, i18n(
"Synchronizing"));
00545
00546
open();
00547
if ( !
noContent() )
00548 mAccount->addLastUnreadMsgCount(
this,
countUnread() );
00549
00550
00551 ImapAccountBase::ConnectionState cs = mAccount->makeConnection();
00552
if ( cs == ImapAccountBase::Error ) {
00553
00554
00555
00556 newState( mProgress, i18n(
"Error connecting to server %1" ).arg( mAccount->host() ) );
00557
close();
00558 emit folderComplete(
this, FALSE);
00559
break;
00560 }
else if ( cs == ImapAccountBase::Connecting ) {
00561
00562 newState( mProgress, i18n(
"Connecting to %1").arg( mAccount->host() ) );
00563
00564 connect( mAccount, SIGNAL( connectionResult(
int,
const QString&) ),
00565
this, SLOT( slotConnectionResult(
int,
const QString&) ) );
00566
break;
00567 }
else {
00568
00569
00570 mSyncState = SYNC_STATE_GET_USERRIGHTS;
00571
00572 }
00573 }
00574
00575
case SYNC_STATE_GET_USERRIGHTS:
00576 mSyncState = SYNC_STATE_RENAME_FOLDER;
00577
00578
if( !
noContent() && mAccount->hasACLSupport() ) {
00579
00580 newState( mProgress, i18n(
"Checking permissions"));
00581 connect( mAccount, SIGNAL( receivedUserRights(
KMFolder* ) ),
00582
this, SLOT( slotReceivedUserRights(
KMFolder* ) ) );
00583 mAccount->getUserRights( folder(), imapPath() );
00584
break;
00585 }
00586
00587
case SYNC_STATE_RENAME_FOLDER:
00588 {
00589 mSyncState = SYNC_STATE_CHECK_UIDVALIDITY;
00590
00591
QString newName = mAccount->renamedFolder( imapPath() );
00592
if ( !newName.isEmpty() ) {
00593 newState( mProgress, i18n(
"Renaming folder") );
00594 CachedImapJob *job =
new CachedImapJob( newName, CachedImapJob::tRenameFolder,
this );
00595 connect( job, SIGNAL( result(KMail::FolderJob *) ),
this, SLOT( slotIncreaseProgress() ) );
00596 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00597 job->start();
00598
break;
00599 }
00600 }
00601
00602
case SYNC_STATE_CHECK_UIDVALIDITY:
00603 mSyncState = SYNC_STATE_CREATE_SUBFOLDERS;
00604
if( !
noContent() ) {
00605 checkUidValidity();
00606
break;
00607 }
00608
00609
00610
case SYNC_STATE_CREATE_SUBFOLDERS:
00611 mSyncState = SYNC_STATE_PUT_MESSAGES;
00612 createNewFolders();
00613
break;
00614
00615
case SYNC_STATE_PUT_MESSAGES:
00616 mSyncState = SYNC_STATE_UPLOAD_FLAGS;
00617
if( !
noContent() ) {
00618 uploadNewMessages();
00619
break;
00620 }
00621
00622
case SYNC_STATE_UPLOAD_FLAGS:
00623 mSyncState = SYNC_STATE_LIST_SUBFOLDERS;
00624
if( !
noContent() ) {
00625
00626
if( uidMapDirty )
00627 reloadUidMap();
00628
00629
00630
if ( mUserRights <= 0 || ( mUserRights & KMail::ACLJobs::WriteFlags ) ) {
00631
if ( mStatusChangedLocally ) {
00632 uploadFlags();
00633
break;
00634 }
else {
00635 kdDebug(5006) <<
"Skipping flags upload, folder unchanged: " <<
label() << endl;
00636 }
00637 }
00638 }
00639
00640
case SYNC_STATE_LIST_SUBFOLDERS:
00641 mSyncState = SYNC_STATE_LIST_SUBFOLDERS2;
00642 newState( mProgress, i18n(
"Retrieving folderlist"));
00643
if( !listDirectory() ) {
00644 mSyncState = SYNC_STATE_INITIAL;
00645 KMessageBox::error(0, i18n(
"Error while retrieving the folderlist"));
00646 }
00647
break;
00648
00649
case SYNC_STATE_LIST_SUBFOLDERS2:
00650 mSyncState = SYNC_STATE_DELETE_SUBFOLDERS;
00651 mProgress += 10;
00652 newState( mProgress, i18n(
"Retrieving subfolders"));
00653 listDirectory2();
00654
break;
00655
00656
case SYNC_STATE_DELETE_SUBFOLDERS:
00657 mSyncState = SYNC_STATE_LIST_MESSAGES;
00658
if( !foldersForDeletionOnServer.isEmpty() ) {
00659 newState( mProgress, i18n(
"Deleting folders from server"));
00660 CachedImapJob* job =
new CachedImapJob( foldersForDeletionOnServer,
00661 CachedImapJob::tDeleteFolders,
this );
00662 connect( job, SIGNAL( result(KMail::FolderJob *) ),
this, SLOT( slotIncreaseProgress() ) );
00663 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00664 job->start();
00665
break;
00666 }
00667
00668
00669
00670
00671
case SYNC_STATE_LIST_MESSAGES:
00672 mSyncState = SYNC_STATE_DELETE_MESSAGES;
00673
if( !
noContent() ) {
00674 newState( mProgress, i18n(
"Retrieving message list"));
00675 listMessages();
00676
break;
00677 }
00678
00679
00680
case SYNC_STATE_DELETE_MESSAGES:
00681 mSyncState = SYNC_STATE_EXPUNGE_MESSAGES;
00682
if( !
noContent() ) {
00683
if( deleteMessages() ) {
00684
00685 }
else {
00686
00687 newState( mProgress, i18n(
"No messages to delete..."));
00688 mSyncState = SYNC_STATE_GET_MESSAGES;
00689 serverSyncInternal();
00690 }
00691
break;
00692 }
00693
00694
00695
case SYNC_STATE_EXPUNGE_MESSAGES:
00696 mSyncState = SYNC_STATE_GET_MESSAGES;
00697
if( !
noContent() ) {
00698 newState( mProgress, i18n(
"Expunging deleted messages"));
00699 CachedImapJob *job =
new CachedImapJob( QString::null,
00700 CachedImapJob::tExpungeFolder,
this );
00701 connect( job, SIGNAL( result(KMail::FolderJob *) ),
this, SLOT( slotIncreaseProgress() ) );
00702 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00703 job->start();
00704
break;
00705 }
00706
00707
00708
case SYNC_STATE_GET_MESSAGES:
00709 mSyncState = SYNC_STATE_HANDLE_INBOX;
00710
if( !
noContent() ) {
00711
if( !mMsgsForDownload.isEmpty() ) {
00712 newState( mProgress, i18n(
"Retrieving new messages"));
00713 CachedImapJob *job =
new CachedImapJob( mMsgsForDownload,
00714 CachedImapJob::tGetMessage,
00715
this );
00716 connect( job, SIGNAL( progress(
unsigned long,
unsigned long) ),
00717
this, SLOT( slotProgress(
unsigned long,
unsigned long) ) );
00718 connect( job, SIGNAL( finished() ),
this, SLOT( slotUpdateLastUid() ) );
00719 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00720 job->start();
00721 mMsgsForDownload.clear();
00722
break;
00723 }
else {
00724 newState( mProgress, i18n(
"No new messages from server"));
00725
00726
00727
00728
00729
00730 slotUpdateLastUid();
00731
if( mLastUid == 0 && uidWriteTimer == -1 )
00732
00733 writeUidCache();
00734 }
00735 }
00736
00737
00738
00739
case SYNC_STATE_HANDLE_INBOX:
00740
00741 mProgress = 95;
00742
00743
00744 mSyncState = SYNC_STATE_SET_ACLS;
00745
00746
case SYNC_STATE_SET_ACLS:
00747 mSyncState = SYNC_STATE_GET_ACLS;
00748
00749
if( !
noContent() && mAccount->hasACLSupport() ) {
00750
bool hasChangedACLs =
false;
00751 ACLList::ConstIterator it = mACLList.begin();
00752
for ( ; it != mACLList.end() && !hasChangedACLs; ++it ) {
00753 hasChangedACLs = (*it).changed;
00754 }
00755
if ( hasChangedACLs ) {
00756 newState( mProgress, i18n(
"Setting permissions"));
00757 KURL url = mAccount->getUrl();
00758 url.setPath( imapPath() );
00759 KIO::Job* job =
KMail::ACLJobs::multiSetACL( mAccount->slave(), url, mACLList );
00760 ImapAccountBase::jobData jd( url.url(), folder() );
00761 mAccount->insertJob(job, jd);
00762
00763 connect(job, SIGNAL(result(KIO::Job *)),
00764 SLOT(slotMultiSetACLResult(KIO::Job *)));
00765 connect(job, SIGNAL(aclChanged(
const QString&,
int )),
00766 SLOT(slotACLChanged(
const QString&,
int )) );
00767
break;
00768 }
00769 }
00770
00771
case SYNC_STATE_GET_ACLS:
00772
00773 mSyncState = SYNC_STATE_FIND_SUBFOLDERS;
00774
00775
if( !
noContent() && mAccount->hasACLSupport() ) {
00776 newState( mProgress, i18n(
"Retrieving permissions" ) );
00777 mAccount->getACL( folder(), mImapPath );
00778 connect( mAccount, SIGNAL(receivedACL(
KMFolder*, KIO::Job*,
const KMail::ACLList& )),
00779
this, SLOT(slotReceivedACL(
KMFolder*, KIO::Job*,
const KMail::ACLList& )) );
00780
break;
00781 }
00782
00783
case SYNC_STATE_FIND_SUBFOLDERS:
00784 {
00785 mProgress = 98;
00786 newState( mProgress, i18n(
"Updating cache file"));
00787
00788 mSyncState = SYNC_STATE_SYNC_SUBFOLDERS;
00789 mSubfoldersForSync.clear();
00790 mCurrentSubfolder = 0;
00791
if( folder() && folder()->child() ) {
00792 KMFolderNode *node = folder()->child()->first();
00793
while( node ) {
00794
if( !node->isDir() ) {
00795 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
00796
00797
if ( !storage->imapPath().isEmpty()
00798
00799 && !foldersForDeletionOnServer.contains( storage->imapPath() ) )
00800 mSubfoldersForSync << storage;
00801 }
00802 node = folder()->child()->next();
00803 }
00804 }
00805 }
00806
00807
00808 mProgress = 100;
00809 newState( mProgress, i18n(
"Synchronization done"));
00810
00811
if ( !mRecurse )
00812 mSubfoldersForSync.clear();
00813
00814
00815
case SYNC_STATE_SYNC_SUBFOLDERS:
00816 {
00817
if( mCurrentSubfolder ) {
00818 disconnect( mCurrentSubfolder, SIGNAL( folderComplete(KMFolderCachedImap*,
bool) ),
00819
this, SLOT( slotSubFolderComplete(KMFolderCachedImap*,
bool) ) );
00820 mCurrentSubfolder = 0;
00821 }
00822
00823
if( mSubfoldersForSync.isEmpty() ) {
00824 mSyncState = SYNC_STATE_INITIAL;
00825 mAccount->addUnreadMsgCount(
this,
countUnread() );
00826
close();
00827 emit folderComplete(
this, TRUE );
00828 }
else {
00829 mCurrentSubfolder = mSubfoldersForSync.front();
00830 mSubfoldersForSync.pop_front();
00831 connect( mCurrentSubfolder, SIGNAL( folderComplete(KMFolderCachedImap*,
bool) ),
00832
this, SLOT( slotSubFolderComplete(KMFolderCachedImap*,
bool) ) );
00833
00834
00835 assert( !mCurrentSubfolder->imapPath().isEmpty() );
00836 mCurrentSubfolder->setAccount( account() );
00837 mCurrentSubfolder->serverSync( mRecurse );
00838 }
00839 }
00840
break;
00841
00842
default:
00843 kdDebug(5006) <<
"KMFolderCachedImap::serverSyncInternal() WARNING: no such state "
00844 << mSyncState << endl;
00845 }
00846 }
00847
00848
00849
00850
00851
void KMFolderCachedImap::slotConnectionResult(
int errorCode,
const QString& errorMsg )
00852 {
00853 disconnect( mAccount, SIGNAL( connectionResult(
int,
const QString&) ),
00854
this, SLOT( slotConnectionResult(
int,
const QString&) ) );
00855
if ( !errorCode ) {
00856
00857 mSyncState = SYNC_STATE_GET_USERRIGHTS;
00858 mProgress += 5;
00859 serverSyncInternal();
00860 }
else {
00861
00862 newState( mProgress, KIO::buildErrorString( errorCode, errorMsg ));
00863 emit folderComplete(
this, FALSE);
00864 }
00865 }
00866
00867
00868
QValueList<unsigned long> KMFolderCachedImap::findNewMessages()
00869 {
00870
QValueList<unsigned long> result;
00871
for(
int i = 0; i <
count(); ++i ) {
00872 KMMsgBase *msg =
getMsgBase( i );
00873
if( !msg )
continue;
00874
if ( msg->UID() == 0 )
00875 result.append( msg->getMsgSerNum() );
00876 }
00877
return result;
00878 }
00879
00880
00881
void KMFolderCachedImap::uploadNewMessages()
00882 {
00883
QValueList<unsigned long> newMsgs = findNewMessages();
00884
if( !newMsgs.isEmpty() ) {
00885
00886 newState( mProgress, i18n(
"Uploading messages to server"));
00887 CachedImapJob *job =
new CachedImapJob( newMsgs, CachedImapJob::tPutMessage,
this );
00888 connect( job, SIGNAL( progress(
unsigned long,
unsigned long) ),
00889
this, SLOT( slotPutProgress(
unsigned long,
unsigned long) ) );
00890 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00891 job->start();
00892 }
else {
00893 newState( mProgress, i18n(
"No messages to upload to server"));
00894
00895 serverSyncInternal();
00896 }
00897 }
00898
00899
00900
void KMFolderCachedImap::slotPutProgress(
unsigned long done,
unsigned long total )
00901 {
00902
00903
int progressSpan = 10;
00904 newState( mProgress + (progressSpan * done) / total, QString::null );
00905
if ( done == total )
00906 mProgress += progressSpan;
00907 }
00908
00909
00910
void KMFolderCachedImap::uploadFlags()
00911 {
00912
if ( !uidMap.isEmpty() ) {
00913 mStatusFlagsJobs = 0;
00914 newState( mProgress, i18n(
"Uploading status of messages to server"));
00915
00916
00917
QMap< QString, QStringList > groups;
00918
00919
for(
int i = 0; i <
count(); ++i ) {
00920 KMMsgBase* msg =
getMsgBase( i );
00921
if( !msg || msg->UID() == 0 )
00922
00923
continue;
00924
00925
QString flags = KMFolderImap::statusToFlags(msg->status());
00926
00927
QString uid;
00928 uid.setNum( msg->UID() );
00929 groups[flags].append(uid);
00930 }
00931
QMapIterator< QString, QStringList > dit;
00932
for( dit = groups.begin(); dit != groups.end(); ++dit ) {
00933
QCString flags = dit.key().latin1();
00934
QStringList sets = KMFolderImap::makeSets( (*dit),
true );
00935 mStatusFlagsJobs += sets.count();
00936
00937
for( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
00938
QString imappath = imapPath() +
";UID=" + ( *slit );
00939 mAccount->setImapStatus(folder(), imappath, flags);
00940 }
00941 }
00942
00943
00944
if ( mStatusFlagsJobs ) {
00945 connect( mAccount, SIGNAL( imapStatusChanged(
KMFolder*,
const QString&,
bool) ),
00946
this, SLOT( slotImapStatusChanged(
KMFolder*,
const QString&,
bool) ) );
00947
return;
00948 }
00949 }
00950 newState( mProgress, i18n(
"No messages to upload to server"));
00951 serverSyncInternal();
00952 }
00953
00954
void KMFolderCachedImap::slotImapStatusChanged(
KMFolder* folder,
const QString&,
bool cont)
00955 {
00956
if ( folder->
storage() ==
this ) {
00957 --mStatusFlagsJobs;
00958
if ( mStatusFlagsJobs == 0 || !cont )
00959 disconnect( mAccount, SIGNAL( imapStatusChanged(
KMFolder*,
const QString&,
bool) ),
00960
this, SLOT( slotImapStatusChanged(
KMFolder*,
const QString&,
bool) ) );
00961
if ( mStatusFlagsJobs == 0 && cont ) {
00962 mProgress += 5;
00963 serverSyncInternal();
00964 }
00965 }
00966 }
00967
00968
00969
void KMFolderCachedImap::setStatus(
QValueList<int>& ids, KMMsgStatus status,
bool toggle)
00970 {
00971 KMFolderMaildir::setStatus(ids, status, toggle);
00972
00973 mStatusChangedLocally =
true;
00974 }
00975
00976
00977
void KMFolderCachedImap::createNewFolders()
00978 {
00979
QValueList<KMFolderCachedImap*> newFolders = findNewFolders();
00980
00981
if( !newFolders.isEmpty() ) {
00982 newState( mProgress, i18n(
"Creating subfolders on server"));
00983 CachedImapJob *job =
new CachedImapJob( newFolders, CachedImapJob::tAddSubfolders,
this );
00984 connect( job, SIGNAL( result(KMail::FolderJob *) ),
this, SLOT( slotIncreaseProgress() ) );
00985 connect( job, SIGNAL( finished() ),
this, SLOT( serverSyncInternal() ) );
00986 job->start();
00987 }
else {
00988 serverSyncInternal();
00989 }
00990 }
00991
00992
QValueList<KMFolderCachedImap*> KMFolderCachedImap::findNewFolders()
00993 {
00994
QValueList<KMFolderCachedImap*> newFolders;
00995
if( folder() && folder()->
child() ) {
00996 KMFolderNode *node = folder()->
child()->first();
00997
while( node ) {
00998
if( !node->isDir() ) {
00999
if( static_cast<KMFolder*>(node)->folderType() != KMFolderTypeCachedImap ) {
01000 kdError(5006) <<
"KMFolderCachedImap::findNewFolders(): ARGH!!! "
01001 << node->name() <<
" is not an IMAP folder\n";
01002 node = folder()->child()->next();
01003 assert(0);
01004 }
01005 KMFolderCachedImap* folder = static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
01006
if( folder->imapPath().isEmpty() ) newFolders << folder;
01007 }
01008 node = folder()->child()->next();
01009 }
01010 }
01011
return newFolders;
01012 }
01013
01014
bool KMFolderCachedImap::deleteMessages()
01015 {
01016
01017
QPtrList<KMMessage> msgsForDeletion;
01018
01019
01020
01021
01022
01023
QMap<ulong,int>::const_iterator it = uidMap.constBegin();
01024
for( ; it != uidMap.end(); it++ ) {
01025 ulong uid ( it.key() );
01026
if( uid!=0 && !uidsOnServer.find( uid ) )
01027 msgsForDeletion.append(
getMsg( *it ) );
01028 }
01029
01030
if( !msgsForDeletion.isEmpty() ) {
01031
removeMsg( msgsForDeletion );
01032 }
01033
01034
01035
if( !uidsForDeletionOnServer.isEmpty() ) {
01036 newState( mProgress, i18n(
"Deleting removed messages from server"));
01037
QStringList sets = KMFolderImap::makeSets( uidsForDeletionOnServer,
true );
01038 uidsForDeletionOnServer.clear();
01039 kdDebug(5006) <<
"Deleting " << sets.count() <<
" sets of messages from server folder " << imapPath() << endl;
01040 CachedImapJob *job =
new CachedImapJob( sets, CachedImapJob::tDeleteMessage,
this );
01041 connect( job, SIGNAL( result(KMail::FolderJob *) ),
01042
this, SLOT( slotDeleteMessagesResult(KMail::FolderJob *) ) );
01043 job->start();
01044
return true;
01045 }
else {
01046
return false;
01047 }
01048 }
01049
01050
void KMFolderCachedImap::slotDeleteMessagesResult( KMail::FolderJob* job )
01051 {
01052
if ( job->error() ) {
01053
01054 mSyncState = SYNC_STATE_GET_MESSAGES;
01055 }
01056 mProgress += 10;
01057 serverSyncInternal();
01058 }
01059
01060
void KMFolderCachedImap::checkUidValidity() {
01061
01062
01063
if( imapPath().isEmpty() || imapPath() ==
"/" )
01064
01065 serverSyncInternal();
01066
else {
01067 newState( mProgress, i18n(
"Checking folder validity"));
01068 CachedImapJob *job =
new CachedImapJob( FolderJob::tCheckUidValidity,
this );
01069 connect( job, SIGNAL( result( KMail::FolderJob* ) ),
01070
this, SLOT( slotCheckUidValidityResult( KMail::FolderJob* ) ) );
01071 job->start();
01072 }
01073 }
01074
01075
void KMFolderCachedImap::slotCheckUidValidityResult( KMail::FolderJob* job )
01076 {
01077
if ( job->error() ) {
01078
01079
01080 mSyncState = SYNC_STATE_HANDLE_INBOX;
01081 }
01082 mProgress += 5;
01083 serverSyncInternal();
01084 }
01085
01086
01087
01088
void KMFolderCachedImap::listMessages() {
01089
if( imapPath() ==
"/" ) {
01090
01091 serverSyncInternal();
01092
return;
01093 }
01094
01095
if( !mAccount->slave() ) {
01096 resetSyncState();
01097 emit folderComplete(
this,
false );
01098
return;
01099 }
01100 uidsOnServer.clear();
01101 uidsOnServer.resize( count() * 2 );
01102 uidsForDeletionOnServer.clear();
01103 mMsgsForDownload.clear();
01104 mUidsForDownload.clear();
01105
01106 CachedImapJob* job =
new CachedImapJob( FolderJob::tListMessages,
this );
01107 connect( job, SIGNAL( result(KMail::FolderJob *) ),
01108
this, SLOT( slotGetLastMessagesResult(KMail::FolderJob *) ) );
01109 job->start();
01110 }
01111
01112
void KMFolderCachedImap::slotGetLastMessagesResult(KMail::FolderJob *job)
01113 {
01114 getMessagesResult(job,
true);
01115 }
01116
01117
01118
void KMFolderCachedImap::slotGetMessagesData(KIO::Job * job,
const QByteArray & data)
01119 {
01120 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
01121
if ( it == mAccount->jobsEnd() ) {
01122 kdDebug(5006) <<
"could not find job!?!?!" << endl;
01123 serverSyncInternal();
01124
return;
01125 }
01126 (*it).cdata +=
QCString(data, data.size() + 1);
01127
int pos = (*it).cdata.find(
"\r\n--IMAPDIGEST");
01128
if (pos > 0) {
01129
int a = (*it).cdata.find(
"\r\nX-uidValidity:");
01130
if (a != -1) {
01131
int b = (*it).cdata.find(
"\r\n", a + 17);
01132 setUidValidity((*it).cdata.mid(a + 17, b - a - 17));
01133 }
01134 a = (*it).cdata.find(
"\r\nX-Access:");
01135
if (a != -1) {
01136
int b = (*it).cdata.find(
"\r\n", a + 12);
01137
QString access = (*it).cdata.mid(a + 12, b - a - 12);
01138 mReadOnly = access ==
"Read only";
01139 }
01140 (*it).cdata.remove(0, pos);
01141 }
01142 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
01143
01144
if ( uidsOnServer.size() == 0 )
01145 uidsOnServer.resize( KMail::nextPrime( 2000 ) );
01146
int flags;
01147
const int v = 42;
01148
while (pos >= 0) {
01149 KMMessage msg;
01150 msg.fromString((*it).cdata.mid(16, pos - 16));
01151 flags = msg.headerField(
"X-Flags").toInt();
01152
bool deleted = ( flags & 8 );
01153 ulong uid = msg.UID();
01154
if ( !deleted ) {
01155
if( uid != 0 ) {
01156
if ( uidsOnServer.count() == uidsOnServer.size() ) {
01157 uidsOnServer.resize( KMail::nextPrime( uidsOnServer.size() * 2 ) );
01158 kdDebug( 5006 ) <<
"Resizing to: " << uidsOnServer.size() << endl;
01159 }
01160 uidsOnServer.insert( uid, &v );
01161 }
01162
if ( uid <= lastUid() ) {
01163
01164
01165
01166
01167
01168
01169
01170
01171 KMMsgBase *existingMessage = findByUID(uid);
01172
01173
01174
01175
if( !existingMessage ) {
01176
01177 uidsForDeletionOnServer << uid;
01178 }
else {
01179
if (!mReadOnly) {
01180
01181 KMFolderImap::flagsToStatus( existingMessage, flags );
01182 }
01183 }
01184
01185 }
else {
01186
01187
01188
if ( !uidMap.contains( uid ) ) {
01189 ulong size = msg.headerField(
"X-Length").toULong();
01190 mMsgsForDownload <<
KMail::CachedImapJob::MsgForDownload(uid, flags, size);
01191
if( imapPath() ==
"/INBOX/" )
01192 mUidsForDownload << uid;
01193 }
01194
01195
if ( uid > mTentativeHighestUid )
01196 mTentativeHighestUid = uid;
01197 }
01198 }
01199 (*it).cdata.remove(0, pos);
01200 (*it).done++;
01201 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
01202 }
01203 }
01204
01205
void KMFolderCachedImap::getMessagesResult( KMail::FolderJob *job,
bool lastSet )
01206 {
01207 mProgress += 10;
01208
if( job->error() ) {
01209 mContentState = imapNoInformation;
01210 }
else {
01211
if( lastSet ) {
01212 mContentState = imapFinished;
01213 mStatusChangedLocally =
false;
01214 }
01215 }
01216 serverSyncInternal();
01217 }
01218
01219
void KMFolderCachedImap::slotProgress(
unsigned long done,
unsigned long total)
01220 {
01221
int progressSpan = 100 - 5 - mProgress;
01222
01223
01224
01225 newState( mProgress + (progressSpan * done) / total, QString::null );
01226 }
01227
01228
01229
void KMFolderCachedImap::setAccount(KMAcctCachedImap *aAccount)
01230 {
01231 assert( aAccount->isA(
"KMAcctCachedImap") );
01232 mAccount = aAccount;
01233
if( imapPath()==
"/" ) aAccount->setFolder( folder() );
01234
01235
01236
QString newName = mAccount->renamedFolder( imapPath() );
01237
if ( !newName.isEmpty() )
01238 folder()->
setLabel( newName );
01239
01240
if( !folder() || !folder()->
child() || !folder()->
child()->count() )
return;
01241
for( KMFolderNode* node = folder()->
child()->first(); node;
01242 node = folder()->child()->next() )
01243
if (!node->isDir())
01244 static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage())->setAccount(aAccount);
01245 }
01246
01247
01248
01249
01250
bool KMFolderCachedImap::listDirectory(
bool secondStep)
01251 {
01252 mSubfolderState = imapInProgress;
01253
if( !mAccount->slave() ) {
01254 resetSyncState();
01255 emit folderComplete(
this,
false );
01256
return false;
01257 }
01258
01259
if (
this == mAccount->rootFolder() )
01260 mAccount->setHasInbox(
false );
01261
01262
01263 ImapAccountBase::ListType
type = ImapAccountBase::List;
01264
if ( mAccount->onlySubscribedFolders() )
01265 type = ImapAccountBase::ListSubscribed;
01266
ListJob* job =
new ListJob(
this, mAccount, type, secondStep,
01267
false, mAccount->hasInbox() );
01268 connect( job, SIGNAL(receivedFolders(
const QStringList&,
const QStringList&,
01269
const QStringList&,
const QStringList&,
const ImapAccountBase::jobData&)),
01270
this, SLOT(slotListResult(
const QStringList&,
const QStringList&,
01271
const QStringList&,
const QStringList&,
const ImapAccountBase::jobData&)));
01272 job->start();
01273
01274
return true;
01275 }
01276
01277
void KMFolderCachedImap::slotListResult(
const QStringList& folderNames,
01278
const QStringList& folderPaths,
01279
const QStringList& folderMimeTypes,
01280
const QStringList& folderAttributes,
01281
const ImapAccountBase::jobData& jobData )
01282 {
01283
01284 mSubfolderNames = folderNames;
01285 mSubfolderPaths = folderPaths;
01286 mSubfolderMimeTypes = folderMimeTypes;
01287 mSubfolderAttributes = folderAttributes;
01288
01289 mSubfolderState = imapFinished;
01290
bool it_inboxOnly = jobData.inboxOnly;
01291
01292 mCreateInbox = jobData.createInbox;
01293
01294
if (it_inboxOnly) {
01295
01296 listDirectory(TRUE);
01297
return;
01298 }
01299
01300
if ( folder()->
isSystemFolder() && mImapPath ==
"/INBOX/"
01301 && mAccount->prefix() ==
"/INBOX/" )
01302 {
01303
01304 mCreateInbox =
false;
01305 mSubfolderNames.clear();
01306 }
01307 folder()->
createChildFolder();
01308
01309 KMFolderNode *node = folder()->
child()->first();
01310
QPtrList<KMFolder> toRemove;
01311
while (node) {
01312
if (!node->isDir() ) {
01313 KMFolderCachedImap *f = static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
01314
if ( mSubfolderNames.findIndex(node->name()) == -1 &&
01315 (node->name().upper() !=
"INBOX" || !mCreateInbox) )
01316 {
01317
01318
if( !f->imapPath().isEmpty() ) {
01319
01320
01321 toRemove.append( f->folder() );
01322 kdDebug(5006) << node->name() <<
" isn't on the server. It has an imapPath -> delete it locally" << endl;
01323 }
else {
01324 kdDebug(5006) << node->name() <<
" isn't on the server, but has no imapPath. ERROR - why didn't createNewFolders create it?" << endl;
01325 }
01326 }
else {
01327
01328 }
01329 }
else {
01330
01331 }
01332 node = folder()->child()->next();
01333 }
01334
01335
for (
KMFolder* doomed=toRemove.first(); doomed; doomed = toRemove.next() )
01336 kmkernel->dimapFolderMgr()->remove( doomed );
01337
01338 mProgress += 5;
01339 serverSyncInternal();
01340 }
01341
01342
01343
void KMFolderCachedImap::listDirectory2() {
01344 foldersForDeletionOnServer.clear();
01345
QString path = folder()->path();
01346 KMFolderCachedImap *f = 0;
01347 kmkernel->dimapFolderMgr()->quiet(
true);
01348
01349
if (mCreateInbox)
01350 {
01351 KMFolderNode *node;
01352
01353
for (node = folder()->child()->first(); node; node = folder()->child()->next())
01354
if (!node->isDir() && node->name() ==
"INBOX")
break;
01355
if (node)
01356 f = static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
01357
else {
01358
KMFolder* newFolder = folder()->child()->createFolder(
"INBOX",
true, KMFolderTypeCachedImap);
01359
if (newFolder)
01360 f = static_cast<KMFolderCachedImap*>(newFolder->
storage());
01361 }
01362 f->setAccount(mAccount);
01363 f->setImapPath(
"/INBOX/");
01364 f->folder()->setLabel(i18n(
"inbox"));
01365
if (!node) {
01366 f->close();
01367 kmkernel->dimapFolderMgr()->contentsChanged();
01368 }
01369
01370 mAccount->setHasInbox(
true );
01371 }
01372
01373
01374
for (uint i = 0; i < mSubfolderNames.count(); i++) {
01375
01376
if (mSubfolderNames[i].upper() ==
"INBOX" &&
01377 mSubfolderPaths[i] ==
"/INBOX/" &&
01378 mAccount->hasInbox())
01379
continue;
01380
01381
01382 KMFolderNode *node;
01383
for (node = folder()->child()->first(); node;
01384 node = folder()->child()->next())
01385
if (!node->isDir() && node->name() == mSubfolderNames[i])
break;
01386
01387
if (!node) {
01388
01389
01390
QString subfolderPath = mSubfolderPaths[i];
01391
01392
01393
01394
bool locallyDeleted = mAccount->isDeletedFolder( subfolderPath );
01395
01396
01397
01398
if ( !locallyDeleted && mAccount->isPreviouslyDeletedFolder( subfolderPath ) ) {
01399 locallyDeleted = KMessageBox::warningYesNo(
01400 0, i18n(
"<qt><p>It seems that the folder <b>%1</b> was deleted. Do you want to delete it from the server?</p></qt>" ).arg( mSubfolderNames[i] ) ) == KMessageBox::Yes;
01401 }
01402
01403
if ( locallyDeleted ) {
01404 kdDebug(5006) << subfolderPath <<
" was deleted locally => delete on server." << endl;
01405 foldersForDeletionOnServer << subfolderPath;
01406 }
else {
01407 kdDebug(5006) << subfolderPath <<
" is a new folder on the server => create local cache" << endl;
01408
KMFolder* newFolder = folder()->child()->createFolder(mSubfolderNames[i],
false, KMFolderTypeCachedImap);
01409
if (newFolder)
01410 f = static_cast<KMFolderCachedImap*>(newFolder->
storage());
01411
if (f) {
01412 f->close();
01413 f->setAccount(mAccount);
01414 kmkernel->dimapFolderMgr()->contentsChanged();
01415 }
else {
01416 kdDebug(5006) <<
"can't create folder " << mSubfolderNames[i] <<endl;
01417 }
01418 }
01419 }
else {
01420
if( static_cast<KMFolder*>(node)->folderType() == KMFolderTypeCachedImap )
01421 f = static_cast<KMFolderCachedImap*>(static_cast<KMFolder*>(node)->storage());
01422 }
01423
01424
if( f ) {
01425
01426
01427
01428 f->setAccount(mAccount);
01429 f->setNoContent(mSubfolderMimeTypes[i] ==
"inode/directory");
01430 f->setNoChildren(mSubfolderMimeTypes[i] ==
"message/digest");
01431 f->setImapPath(mSubfolderPaths[i]);
01432 }
01433 }
01434 kmkernel->dimapFolderMgr()->quiet(
false);
01435 emit listComplete(
this);
01436 serverSyncInternal();
01437 }
01438
01439
void KMFolderCachedImap::slotSubFolderComplete(KMFolderCachedImap* sub,
bool success)
01440 {
01441 Q_UNUSED(sub);
01442
01443
if ( success ) {
01444 serverSyncInternal();
01445 }
01446
else
01447 {
01448
01449
if ( mCurrentSubfolder ) {
01450 Q_ASSERT( sub == mCurrentSubfolder );
01451 disconnect( mCurrentSubfolder, SIGNAL( folderComplete(KMFolderCachedImap*,
bool) ),
01452
this, SLOT( slotSubFolderComplete(KMFolderCachedImap*,
bool) ) );
01453 mCurrentSubfolder = 0;
01454 }
01455
01456 mSubfoldersForSync.clear();
01457 mSyncState = SYNC_STATE_INITIAL;
01458
close();
01459 emit folderComplete(
this,
false );
01460 }
01461 }
01462
01463
void KMFolderCachedImap::slotSimpleData(KIO::Job * job,
const QByteArray & data)
01464 {
01465 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
01466
if (it == mAccount->jobsEnd())
return;
01467
QBuffer buff((*it).data);
01468 buff.open(IO_WriteOnly | IO_Append);
01469 buff.writeBlock(data.data(), data.size());
01470 buff.close();
01471 }
01472
01473
01474 FolderJob*
01475 KMFolderCachedImap::doCreateJob( KMMessage *msg, FolderJob::JobType jt,
KMFolder *folder,
01476
QString,
const AttachmentStrategy* )
const
01477
{
01478
QPtrList<KMMessage> msgList;
01479 msgList.append( msg );
01480 CachedImapJob *job =
new CachedImapJob( msgList, jt, folder? static_cast<KMFolderCachedImap*>( folder->
storage() ):0 );
01481 job->setParentFolder(
this );
01482
return job;
01483 }
01484
01485 FolderJob*
01486 KMFolderCachedImap::doCreateJob(
QPtrList<KMMessage>& msgList,
const QString& sets,
01487 FolderJob::JobType jt,
KMFolder *folder )
const
01488
{
01489
01490 Q_UNUSED( sets );
01491 CachedImapJob *job =
new CachedImapJob( msgList, jt, folder? static_cast<KMFolderCachedImap*>( folder->
storage() ):0 );
01492 job->setParentFolder(
this );
01493
return job;
01494 }
01495
01496
void
01497 KMFolderCachedImap::setUserRights(
unsigned int userRights )
01498 {
01499 mUserRights = userRights;
01500 }
01501
01502
void
01503 KMFolderCachedImap::slotReceivedUserRights(
KMFolder* folder )
01504 {
01505
if ( folder->
storage() ==
this ) {
01506 disconnect( mAccount, SIGNAL( receivedUserRights(
KMFolder* ) ),
01507
this, SLOT( slotReceivedUserRights(
KMFolder* ) ) );
01508
if ( mUserRights == 0 )
01509 mUserRights = -1;
01510
else
01511 mReadOnly = ( mUserRights & KMail::ACLJobs::Insert ) == 0;
01512 mProgress += 5;
01513 serverSyncInternal();
01514 }
01515 }
01516
01517
void
01518 KMFolderCachedImap::slotReceivedACL(
KMFolder* folder, KIO::Job*,
const KMail::ACLList& aclList )
01519 {
01520
if ( folder->
storage() ==
this ) {
01521 disconnect( mAccount, SIGNAL(receivedACL(
KMFolder*, KIO::Job*,
const KMail::ACLList& )),
01522
this, SLOT(slotReceivedACL(
KMFolder*, KIO::Job*,
const KMail::ACLList& )) );
01523 mACLList = aclList;
01524 serverSyncInternal();
01525 }
01526 }
01527
01528
void
01529 KMFolderCachedImap::setACLList(
const ACLList& arr )
01530 {
01531 mACLList = arr;
01532 }
01533
01534
void
01535 KMFolderCachedImap::slotMultiSetACLResult(KIO::Job *job)
01536 {
01537 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
01538
if ( it == mAccount->jobsEnd() )
return;
01539
if ( (*it).parent != folder() )
return;
01540
01541
if ( job->error() )
01542
01543
01544 job->showErrorDialog();
01545
01546
if (mAccount->slave()) mAccount->removeJob(job);
01547 serverSyncInternal();
01548 }
01549
01550
void
01551 KMFolderCachedImap::slotACLChanged(
const QString& userId,
int permissions )
01552 {
01553
01554
01555
for( ACLList::Iterator it = mACLList.begin(); it != mACLList.end(); ++it ) {
01556
if ( (*it).userId == userId && (*it).permissions == permissions ) {
01557
if ( permissions == -1 )
01558 mACLList.erase( it );
01559
else
01560 (*it).changed =
false;
01561
return;
01562 }
01563 }
01564 }
01565
01566
01567
void KMFolderCachedImap::resetSyncState()
01568 {
01569 mSubfoldersForSync.clear();
01570 mSyncState = SYNC_STATE_INITIAL;
01571
close();
01572
01573 ProgressItem *progressItem = mAccount->mailCheckProgressItem();
01574
QString str = i18n(
"Aborted");
01575
if (progressItem)
01576 progressItem->setStatus( str );
01577 emit
statusMsg( str );
01578 }
01579
01580
void KMFolderCachedImap::slotIncreaseProgress()
01581 {
01582 mProgress += 5;
01583 }
01584
01585
void KMFolderCachedImap::newState(
int progress,
const QString& syncStatus )
01586 {
01587
01588 ProgressItem *progressItem = mAccount->mailCheckProgressItem();
01589
if( progressItem )
01590 progressItem->setCompletedItems( progress );
01591
if ( !syncStatus.isEmpty() ) {
01592
QString str;
01593
01594
if ( mAccount->imapFolder() ==
this )
01595 str = syncStatus;
01596
else
01597 str =
QString(
"%1: %2" ).arg(
label() ).arg( syncStatus );
01598
if( progressItem )
01599 progressItem->setStatus( str );
01600 emit
statusMsg( str );
01601 }
01602
if( progressItem )
01603 progressItem->updateProgress();
01604 }
01605
01606
void KMFolderCachedImap::setSubfolderState( imapState state )
01607 {
01608 mSubfolderState = state;
01609
if ( state == imapNoInformation && folder()->
child() )
01610 {
01611
01612 KMFolderNode* node;
01613
QPtrListIterator<KMFolderNode> it( *folder()->
child() );
01614
for ( ; (node = it.current()); )
01615 {
01616 ++it;
01617
if (node->isDir())
continue;
01618
KMFolder *folder = static_cast<KMFolder*>(node);
01619 static_cast<KMFolderCachedImap*>(folder->
storage())->setSubfolderState( state );
01620 }
01621 }
01622 }
01623
01624
void KMFolderCachedImap::setImapPath(
const QString &path)
01625 {
01626 mImapPath = path;
01627 }
01628
01629
void KMFolderCachedImap::setContentsType( KMail::FolderContentsType type )
01630 {
01631
if ( type != mContentsType ) {
01632
FolderStorage::setContentsType( type );
01633 mContentsTypeChanged =
true;
01634 }
01635 }
01636
01637
void KMFolderCachedImap::slotUpdateLastUid()
01638 {
01639
if( mTentativeHighestUid != 0 )
01640 setLastUid( mTentativeHighestUid );
01641 mTentativeHighestUid = 0;
01642 }
01643
01644
#include "kmfoldercachedimap.moc"