00001
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #include "kmacctcachedimap.h"
00037 using KMail::SieveConfig;
00038
00039 #include "kmfoldertree.h"
00040 #include "kmfoldermgr.h"
00041 #include "kmfiltermgr.h"
00042 #include "kmfoldercachedimap.h"
00043 #include "kmmainwin.h"
00044 #include "accountmanager.h"
00045 using KMail::AccountManager;
00046 #include "progressmanager.h"
00047
00048 #include <kio/passdlg.h>
00049 #include <kio/scheduler.h>
00050 #include <kio/slave.h>
00051 #include <kmessagebox.h>
00052 #include <kdebug.h>
00053 #include <kstandarddirs.h>
00054 #include <kapplication.h>
00055 #include <kconfig.h>
00056
00057
00058 KMAcctCachedImap::KMAcctCachedImap( AccountManager* aOwner,
00059 const QString& aAccountName, uint id )
00060 : KMail::ImapAccountBase( aOwner, aAccountName, id ), mFolder( 0 ),
00061 mAnnotationCheckPassed(false)
00062 {
00063
00064 mAutoExpunge = false;
00065 }
00066
00067
00068
00069 KMAcctCachedImap::~KMAcctCachedImap()
00070 {
00071 killAllJobsInternal( true );
00072 }
00073
00074
00075
00076 QString KMAcctCachedImap::type() const
00077 {
00078 return "cachedimap";
00079 }
00080
00081 void KMAcctCachedImap::init() {
00082 ImapAccountBase::init();
00083 }
00084
00085
00086 void KMAcctCachedImap::pseudoAssign( const KMAccount * a ) {
00087 killAllJobs( true );
00088 if (mFolder)
00089 {
00090 mFolder->setContentState(KMFolderCachedImap::imapNoInformation);
00091 mFolder->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00092 }
00093 ImapAccountBase::pseudoAssign( a );
00094 }
00095
00096
00097 void KMAcctCachedImap::setImapFolder(KMFolderCachedImap *aFolder)
00098 {
00099 mFolder = aFolder;
00100 mFolder->setImapPath( "/" );
00101 mFolder->setAccount( this );
00102 }
00103
00104
00105
00106 void KMAcctCachedImap::setAutoExpunge( bool )
00107 {
00108
00109 mAutoExpunge = false;
00110 }
00111
00112
00113 void KMAcctCachedImap::killAllJobs( bool disconnectSlave )
00114 {
00115
00116 QValueList<KMFolderCachedImap*> folderList = killAllJobsInternal( disconnectSlave );
00117 for( QValueList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00118 KMFolderCachedImap *fld = *it;
00119 fld->resetSyncState();
00120 fld->setContentState(KMFolderCachedImap::imapNoInformation);
00121 fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00122 fld->sendFolderComplete(FALSE);
00123 }
00124 }
00125
00126
00127
00128 QValueList<KMFolderCachedImap*> KMAcctCachedImap::killAllJobsInternal( bool disconnectSlave )
00129 {
00130
00131
00132 QValueList<KMFolderCachedImap*> folderList;
00133 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00134 for (; it != mapJobData.end(); ++it) {
00135 if ((*it).parent)
00136 folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00137
00138 if ( !it.key()->error() && mSlave ) {
00139 it.key()->kill();
00140 mSlave = 0;
00141 }
00142 }
00143 mapJobData.clear();
00144
00145
00146 for( QPtrListIterator<CachedImapJob> it( mJobList ); it.current(); ++it )
00147 it.current()->setPassiveDestructor( true );
00148 KMAccount::deleteFolderJobs();
00149
00150 if ( disconnectSlave && mSlave ) {
00151 KIO::Scheduler::disconnectSlave( mSlave );
00152 mSlave = 0;
00153 }
00154 return folderList;
00155 }
00156
00157
00158 void KMAcctCachedImap::cancelMailCheck()
00159 {
00160
00161 QValueList<KMFolderCachedImap*> folderList;
00162 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00163 for (; it != mapJobData.end(); ++it) {
00164 if ( (*it).cancellable && (*it).parent )
00165 folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00166 }
00167
00168 ImapAccountBase::cancelMailCheck();
00169
00170
00171 for( QValueList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00172 KMFolderCachedImap *fld = *it;
00173 fld->resetSyncState();
00174 fld->setContentState(KMFolderCachedImap::imapNoInformation);
00175 fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00176 fld->sendFolderComplete(FALSE);
00177 }
00178 }
00179
00180
00181 void KMAcctCachedImap::killJobsForItem(KMFolderTreeItem * fti)
00182 {
00183 QMap<KIO::Job *, jobData>::Iterator it = mapJobData.begin();
00184 while (it != mapJobData.end())
00185 {
00186 if (it.data().parent == fti->folder())
00187 {
00188 killAllJobs();
00189 break;
00190 }
00191 else ++it;
00192 }
00193 }
00194
00195
00196 void KMAcctCachedImap::slotCheckQueuedFolders()
00197 {
00198 mMailCheckFolders.clear();
00199 mMailCheckFolders.append( mFoldersQueuedForChecking.front() );
00200 mFoldersQueuedForChecking.pop_front();
00201 if ( mFoldersQueuedForChecking.isEmpty() )
00202 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00203 this, SLOT( slotCheckQueuedFolders() ) );
00204
00205 kmkernel->acctMgr()->singleCheckMail(this, true);
00206 mMailCheckFolders.clear();
00207 }
00208
00209 void KMAcctCachedImap::processNewMail( bool )
00210 {
00211 assert( mFolder );
00212
00213 if ( mMailCheckFolders.isEmpty() )
00214 processNewMail( mFolder, true );
00215 else {
00216 KMFolder* f = mMailCheckFolders.front();
00217 mMailCheckFolders.pop_front();
00218 processNewMail( static_cast<KMFolderCachedImap *>( f->storage() ), false );
00219 }
00220 }
00221
00222 void KMAcctCachedImap::processNewMail( KMFolderCachedImap* folder,
00223 bool recurse )
00224 {
00225 assert( folder );
00226
00227 mAutoExpunge = false;
00228 mCountLastUnread = 0;
00229 mUnreadBeforeCheck.clear();
00230
00231 mNoopTimer.stop();
00232
00233
00234 if ( folder == mFolder ) {
00235 QStringList nsToList = namespaces()[PersonalNS];
00236 QStringList otherNSToCheck = namespaces()[OtherUsersNS];
00237 otherNSToCheck += namespaces()[SharedNS];
00238 for ( QStringList::Iterator it = otherNSToCheck.begin();
00239 it != otherNSToCheck.end(); ++it ) {
00240 if ( (*it).isEmpty() ) {
00241
00242
00243 nsToList += *it;
00244 }
00245 }
00246 folder->setNamespacesToList( nsToList );
00247 }
00248
00249 Q_ASSERT( !mMailCheckProgressItem );
00250 mMailCheckProgressItem = KPIM::ProgressManager::createProgressItem(
00251 "MailCheck" + QString::number( id() ),
00252 folder->label(),
00253 QString::null,
00254 true,
00255 useSSL() || useTLS() );
00256 connect( mMailCheckProgressItem, SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
00257 this, SLOT( slotProgressItemCanceled( KPIM::ProgressItem* ) ) );
00258
00259 folder->setAccount(this);
00260 connect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00261 this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00262 folder->serverSync( recurse );
00263 }
00264
00265 void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool )
00266 {
00267 mNoopTimer.start( 60000 );
00268 disconnect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00269 this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00270 mMailCheckProgressItem->setComplete();
00271 mMailCheckProgressItem = 0;
00272
00273 if ( folder == mFolder ) {
00274
00275
00276
00277
00278
00279
00280 #if 0 // this opens a race: delete a folder during a sync (after the sync checked that folder), and it'll be forgotten...
00281 mDeletedFolders.clear();
00282 #endif
00283 mPreviouslyDeletedFolders.clear();
00284 }
00285
00286 KMail::ImapAccountBase::postProcessNewMail();
00287 }
00288
00289 void KMAcctCachedImap::addUnreadMsgCount( const KMFolderCachedImap *folder,
00290 int countUnread )
00291 {
00292 if ( folder->imapPath() != "/INBOX/" ) {
00293
00294
00295 const QString folderId = folder->folder()->idString();
00296 int newInFolder = countUnread;
00297 if ( mUnreadBeforeCheck.find( folderId ) != mUnreadBeforeCheck.end() )
00298 newInFolder -= mUnreadBeforeCheck[folderId];
00299 if ( newInFolder > 0 )
00300 addToNewInFolder( folderId, newInFolder );
00301 }
00302 mCountUnread += countUnread;
00303 }
00304
00305 void KMAcctCachedImap::addLastUnreadMsgCount( const KMFolderCachedImap *folder,
00306 int countLastUnread )
00307 {
00308 mUnreadBeforeCheck[folder->folder()->idString()] = countLastUnread;
00309 mCountLastUnread += countLastUnread;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 void KMAcctCachedImap::readConfig( KConfig & config ) {
00319 ImapAccountBase::readConfig( config );
00320
00321 mPreviouslyDeletedFolders = config.readListEntry( "deleted-folders" );
00322 mDeletedFolders.clear();
00323 const QStringList oldPaths = config.readListEntry( "renamed-folders-paths" );
00324 const QStringList newNames = config.readListEntry( "renamed-folders-names" );
00325 QStringList::const_iterator it = oldPaths.begin();
00326 QStringList::const_iterator nameit = newNames.begin();
00327 for( ; it != oldPaths.end() && nameit != newNames.end(); ++it, ++nameit ) {
00328 addRenamedFolder( *it, QString::null, *nameit );
00329 }
00330 }
00331
00332 void KMAcctCachedImap::writeConfig( KConfig & config ) {
00333 ImapAccountBase::writeConfig( config );
00334 config.writeEntry( "deleted-folders", mDeletedFolders + mPreviouslyDeletedFolders );
00335 config.writeEntry( "renamed-folders-paths", mRenamedFolders.keys() );
00336 const QValueList<RenamedFolder> values = mRenamedFolders.values();
00337 QStringList lstNames;
00338 QValueList<RenamedFolder>::const_iterator it = values.begin();
00339 for ( ; it != values.end() ; ++it )
00340 lstNames.append( (*it).mNewName );
00341 config.writeEntry( "renamed-folders-names", lstNames );
00342 }
00343
00344 void KMAcctCachedImap::invalidateIMAPFolders()
00345 {
00346 invalidateIMAPFolders( mFolder );
00347 }
00348
00349 void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder )
00350 {
00351 if( !folder || !folder->folder() )
00352 return;
00353
00354 folder->setAccount(this);
00355
00356 QStringList strList;
00357 QValueList<QGuardedPtr<KMFolder> > folderList;
00358 kmkernel->dimapFolderMgr()->createFolderList( &strList, &folderList,
00359 folder->folder()->child(), QString::null,
00360 false );
00361 QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00362 mCountLastUnread = 0;
00363 mUnreadBeforeCheck.clear();
00364
00365 for( it = folderList.begin(); it != folderList.end(); ++it ) {
00366 KMFolder *f = *it;
00367 if( f && f->folderType() == KMFolderTypeCachedImap ) {
00368 KMFolderCachedImap *cfolder = static_cast<KMFolderCachedImap*>(f->storage());
00369
00370 cfolder->setUidValidity("INVALID");
00371 cfolder->writeUidCache();
00372 processNewMailSingleFolder( f );
00373 }
00374 }
00375 folder->setUidValidity("INVALID");
00376 folder->writeUidCache();
00377
00378 processNewMailSingleFolder( folder->folder() );
00379 }
00380
00381
00382 void KMAcctCachedImap::addDeletedFolder( KMFolder* folder )
00383 {
00384 if ( folder->folderType() != KMFolderTypeCachedImap )
00385 return;
00386 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>(folder->storage());
00387 addDeletedFolder( storage->imapPath() );
00388 kdDebug(5006) << k_funcinfo << storage->imapPath() << endl;
00389
00390
00391 if( folder && folder->child() ) {
00392 KMFolderNode *node = folder->child()->first();
00393 while( node ) {
00394 if( !node->isDir() ) {
00395 addDeletedFolder( static_cast<KMFolder*>( node ) );
00396 }
00397 node = folder->child()->next();
00398 }
00399 }
00400 }
00401
00402 void KMAcctCachedImap::addDeletedFolder( const QString& imapPath )
00403 {
00404 mDeletedFolders << imapPath;
00405 }
00406
00407 QStringList KMAcctCachedImap::deletedFolderPaths( const QString& subFolderPath ) const
00408 {
00409 QStringList lst;
00410 for ( QStringList::const_iterator it = mDeletedFolders.begin(); it != mDeletedFolders.end(); ++it ) {
00411 if ( (*it).startsWith( subFolderPath ) )
00412
00413 lst.prepend( *it );
00414 }
00415 for ( QStringList::const_iterator it = mPreviouslyDeletedFolders.begin(); it != mPreviouslyDeletedFolders.end(); ++it ) {
00416 if ( (*it).startsWith( subFolderPath ) )
00417 lst.prepend( *it );
00418 }
00419 kdDebug(5006) << "KMAcctCachedImap::deletedFolderPaths for " << subFolderPath << " returning: " << lst << endl;
00420 Q_ASSERT( !lst.isEmpty() );
00421 return lst;
00422 }
00423
00424 bool KMAcctCachedImap::isDeletedFolder( const QString& subFolderPath ) const
00425 {
00426 return mDeletedFolders.find( subFolderPath ) != mDeletedFolders.end();
00427 }
00428
00429 bool KMAcctCachedImap::isPreviouslyDeletedFolder( const QString& subFolderPath ) const
00430 {
00431 return mPreviouslyDeletedFolders.find( subFolderPath ) != mPreviouslyDeletedFolders.end();
00432 }
00433
00434 void KMAcctCachedImap::removeDeletedFolder( const QString& subFolderPath )
00435 {
00436 mDeletedFolders.remove( subFolderPath );
00437 mPreviouslyDeletedFolders.remove( subFolderPath );
00438 }
00439
00440 void KMAcctCachedImap::addRenamedFolder( const QString& subFolderPath, const QString& oldLabel, const QString& newName )
00441 {
00442 mRenamedFolders.insert( subFolderPath, RenamedFolder( oldLabel, newName ) );
00443 }
00444
00445 void KMAcctCachedImap::removeRenamedFolder( const QString& subFolderPath )
00446 {
00447 mRenamedFolders.remove( subFolderPath );
00448 }
00449
00450 void KMAcctCachedImap::slotProgressItemCanceled( ProgressItem* )
00451 {
00452 bool abortConnection = !mSlaveConnected;
00453 killAllJobs( abortConnection );
00454 if ( abortConnection ) {
00455
00456 emit connectionResult( KIO::ERR_USER_CANCELED, QString::null );
00457 }
00458 }
00459
00460 FolderStorage* const KMAcctCachedImap::rootFolder() const
00461 {
00462 return mFolder;
00463 }
00464
00465
00466 QString KMAcctCachedImap::renamedFolder( const QString& imapPath ) const
00467 {
00468 QMap<QString, RenamedFolder>::ConstIterator renit = mRenamedFolders.find( imapPath );
00469 if ( renit != mRenamedFolders.end() )
00470 return (*renit).mNewName;
00471 return QString::null;
00472 }
00473
00474 #include "kmacctcachedimap.moc"