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