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