00001
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "imapaccountbase.h"
00029 using KMail::SieveConfig;
00030
00031 #include "accountmanager.h"
00032 using KMail::AccountManager;
00033 #include "kmfolder.h"
00034 #include "broadcaststatus.h"
00035 using KPIM::BroadcastStatus;
00036 #include "kmmainwin.h"
00037 #include "kmfolderimap.h"
00038 #include "kmmainwidget.h"
00039 #include "kmmainwin.h"
00040 #include "kmmsgpart.h"
00041 #include "acljobs.h"
00042 #include "kmfoldercachedimap.h"
00043 #include "bodyvisitor.h"
00044 using KMail::BodyVisitor;
00045 #include "imapjob.h"
00046 using KMail::ImapJob;
00047 #include "protocols.h"
00048 #include "progressmanager.h"
00049 using KPIM::ProgressManager;
00050 #include "kmfoldermgr.h"
00051 #include "listjob.h"
00052
00053 #include <kapplication.h>
00054 #include <kdebug.h>
00055 #include <kconfig.h>
00056 #include <klocale.h>
00057 #include <kmessagebox.h>
00058 using KIO::MetaData;
00059 #include <kio/passdlg.h>
00060 using KIO::PasswordDialog;
00061 #include <kio/scheduler.h>
00062 #include <kio/slave.h>
00063 #include <mimelib/bodypart.h>
00064 #include <mimelib/body.h>
00065 #include <mimelib/headers.h>
00066 #include <mimelib/message.h>
00067
00068
00069 #include <qregexp.h>
00070 #include <qstylesheet.h>
00071
00072 namespace KMail {
00073
00074 static const unsigned short int imapDefaultPort = 143;
00075
00076
00077
00078
00079
00080
00081
00082 ImapAccountBase::ImapAccountBase( AccountManager * parent, const QString & name, uint id )
00083 : NetworkAccount( parent, name, id ),
00084 mIdleTimer( 0, "mIdleTimer" ),
00085 mNoopTimer( 0, "mNoopTimer" ),
00086 mTotal( 0 ),
00087 mCountUnread( 0 ),
00088 mCountLastUnread( 0 ),
00089 mAutoExpunge( true ),
00090 mHiddenFolders( false ),
00091 mOnlySubscribedFolders( false ),
00092 mOnlyLocallySubscribedFolders( false ),
00093 mLoadOnDemand( true ),
00094 mListOnlyOpenFolders( false ),
00095 mProgressEnabled( false ),
00096 mErrorDialogIsActive( false ),
00097 mPasswordDialogIsActive( false ),
00098 mACLSupport( true ),
00099 mAnnotationSupport( true ),
00100 mQuotaSupport( true ),
00101 mSlaveConnected( false ),
00102 mSlaveConnectionError( false ),
00103 mCheckingSingleFolder( false ),
00104 mListDirProgressItem( 0 )
00105 {
00106 mPort = imapDefaultPort;
00107 mBodyPartList.setAutoDelete(true);
00108 KIO::Scheduler::connect(SIGNAL(slaveError(KIO::Slave *, int, const QString &)),
00109 this, SLOT(slotSchedulerSlaveError(KIO::Slave *, int, const QString &)));
00110 KIO::Scheduler::connect(SIGNAL(slaveConnected(KIO::Slave *)),
00111 this, SLOT(slotSchedulerSlaveConnected(KIO::Slave *)));
00112 connect(&mNoopTimer, SIGNAL(timeout()), SLOT(slotNoopTimeout()));
00113 connect(&mIdleTimer, SIGNAL(timeout()), SLOT(slotIdleTimeout()));
00114 }
00115
00116 ImapAccountBase::~ImapAccountBase() {
00117 kdWarning( mSlave, 5006 )
00118 << "slave should have been destroyed by subclass!" << endl;
00119 }
00120
00121 void ImapAccountBase::init() {
00122 mAutoExpunge = true;
00123 mHiddenFolders = false;
00124 mOnlySubscribedFolders = false;
00125 mOnlyLocallySubscribedFolders = false;
00126 mLoadOnDemand = true;
00127 mListOnlyOpenFolders = false;
00128 mProgressEnabled = false;
00129 }
00130
00131 void ImapAccountBase::pseudoAssign( const KMAccount * a ) {
00132 NetworkAccount::pseudoAssign( a );
00133
00134 const ImapAccountBase * i = dynamic_cast<const ImapAccountBase*>( a );
00135 if ( !i ) return;
00136
00137 setAutoExpunge( i->autoExpunge() );
00138 setHiddenFolders( i->hiddenFolders() );
00139 setOnlySubscribedFolders( i->onlySubscribedFolders() );
00140 setOnlyLocallySubscribedFolders( i->onlyLocallySubscribedFolders() );
00141 setLoadOnDemand( i->loadOnDemand() );
00142 setListOnlyOpenFolders( i->listOnlyOpenFolders() );
00143 setNamespaces( i->namespaces() );
00144 setNamespaceToDelimiter( i->namespaceToDelimiter() );
00145 localBlacklistFromStringList( i->locallyBlacklistedFolders() );
00146 }
00147
00148 unsigned short int ImapAccountBase::defaultPort() const {
00149 return imapDefaultPort;
00150 }
00151
00152 QString ImapAccountBase::protocol() const {
00153 return useSSL() ? IMAP_SSL_PROTOCOL : IMAP_PROTOCOL;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162 void ImapAccountBase::setAutoExpunge( bool expunge ) {
00163 mAutoExpunge = expunge;
00164 }
00165
00166 void ImapAccountBase::setHiddenFolders( bool show ) {
00167 mHiddenFolders = show;
00168 }
00169
00170 void ImapAccountBase::setOnlySubscribedFolders( bool show ) {
00171 mOnlySubscribedFolders = show;
00172 }
00173
00174 void ImapAccountBase::setOnlyLocallySubscribedFolders( bool show ) {
00175 mOnlyLocallySubscribedFolders = show;
00176 }
00177
00178 void ImapAccountBase::setLoadOnDemand( bool load ) {
00179 mLoadOnDemand = load;
00180 }
00181
00182 void ImapAccountBase::setListOnlyOpenFolders( bool only ) {
00183 mListOnlyOpenFolders = only;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 void ImapAccountBase::readConfig( KConfig & config ) {
00193 NetworkAccount::readConfig( config );
00194
00195 setAutoExpunge( config.readBoolEntry( "auto-expunge", false ) );
00196 setHiddenFolders( config.readBoolEntry( "hidden-folders", false ) );
00197 setOnlySubscribedFolders( config.readBoolEntry( "subscribed-folders", false ) );
00198 setOnlyLocallySubscribedFolders( config.readBoolEntry( "locally-subscribed-folders", false ) );
00199 setLoadOnDemand( config.readBoolEntry( "loadondemand", false ) );
00200 setListOnlyOpenFolders( config.readBoolEntry( "listOnlyOpenFolders", false ) );
00201 mCapabilities = config.readListEntry( "capabilities", QStringList() );
00202
00203 nsMap map;
00204 QStringList list = config.readListEntry( QString::number( PersonalNS ) );
00205 if ( !list.isEmpty() )
00206 map[PersonalNS] = list.gres( "\"", "" );
00207 list = config.readListEntry( QString::number( OtherUsersNS ) );
00208 if ( !list.isEmpty() )
00209 map[OtherUsersNS] = list.gres( "\"", "" );
00210 list = config.readListEntry( QString::number( SharedNS ) );
00211 if ( !list.isEmpty() )
00212 map[SharedNS] = list.gres( "\"", "" );
00213 setNamespaces( map );
00214
00215 namespaceDelim entries = config.entryMap( config.group() );
00216 namespaceDelim namespaceToDelimiter;
00217 for ( namespaceDelim::ConstIterator it = entries.begin();
00218 it != entries.end(); ++it ) {
00219 if ( it.key().startsWith( "Namespace:" ) ) {
00220 QString key = it.key().right( it.key().length() - 10 );
00221 namespaceToDelimiter[key] = it.data();
00222 }
00223 }
00224 setNamespaceToDelimiter( namespaceToDelimiter );
00225 mOldPrefix = config.readEntry( "prefix" );
00226 if ( !mOldPrefix.isEmpty() ) {
00227 makeConnection();
00228 }
00229 localBlacklistFromStringList( config.readListEntry( "locallyUnsubscribedFolders" ) );
00230 }
00231
00232 void ImapAccountBase::writeConfig( KConfig & config ) {
00233 NetworkAccount::writeConfig( config );
00234
00235 config.writeEntry( "auto-expunge", autoExpunge() );
00236 config.writeEntry( "hidden-folders", hiddenFolders() );
00237 config.writeEntry( "subscribed-folders", onlySubscribedFolders() );
00238 config.writeEntry( "locally-subscribed-folders", onlyLocallySubscribedFolders() );
00239 config.writeEntry( "loadondemand", loadOnDemand() );
00240 config.writeEntry( "listOnlyOpenFolders", listOnlyOpenFolders() );
00241 config.writeEntry( "capabilities", mCapabilities );
00242 QString data;
00243 for ( nsMap::Iterator it = mNamespaces.begin(); it != mNamespaces.end(); ++it ) {
00244 if ( !it.data().isEmpty() ) {
00245 data = "\"" + it.data().join("\",\"") + "\"";
00246 config.writeEntry( QString::number( it.key() ), data );
00247 }
00248 }
00249 QString key;
00250 for ( namespaceDelim::ConstIterator it = mNamespaceToDelimiter.begin();
00251 it != mNamespaceToDelimiter.end(); ++it ) {
00252 key = "Namespace:" + it.key();
00253 config.writeEntry( key, it.data() );
00254 }
00255 config.writeEntry( "locallyUnsubscribedFolders", locallyBlacklistedFolders() );
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 MetaData ImapAccountBase::slaveConfig() const {
00265 MetaData m = NetworkAccount::slaveConfig();
00266
00267 m.insert( "auth", auth() );
00268 if ( autoExpunge() )
00269 m.insert( "expunge", "auto" );
00270
00271 return m;
00272 }
00273
00274 ImapAccountBase::ConnectionState ImapAccountBase::makeConnection()
00275 {
00276 if ( mSlave && mSlaveConnected ) {
00277 return Connected;
00278 }
00279 if ( mPasswordDialogIsActive ) return Connecting;
00280
00281 if( mAskAgain || ( ( passwd().isEmpty() || login().isEmpty() ) &&
00282 auth() != "GSSAPI" ) ) {
00283
00284 Q_ASSERT( !mSlave );
00285 QString log = login();
00286 QString pass = passwd();
00287
00288
00289
00290
00291 KConfigGroup passwords( KGlobal::config(), "Passwords" );
00292 passwords.writeEntry( "Keep", storePasswd() );
00293 QString msg = i18n("You need to supply a username and a password to "
00294 "access this mailbox.");
00295 mPasswordDialogIsActive = true;
00296
00297 PasswordDialog dlg( msg, log, true , true, KMKernel::self()->mainWin() );
00298 dlg.setPlainCaption( i18n("Authorization Dialog") );
00299 dlg.addCommentLine( i18n("Account:"), name() );
00300 int ret = dlg.exec();
00301 if (ret != QDialog::Accepted ) {
00302 mPasswordDialogIsActive = false;
00303 mAskAgain = false;
00304 emit connectionResult( KIO::ERR_USER_CANCELED, QString::null );
00305 return Error;
00306 }
00307 mPasswordDialogIsActive = false;
00308
00309
00310 setPasswd( dlg.password(), dlg.keepPassword() );
00311 setLogin( dlg.username() );
00312 mAskAgain = false;
00313 }
00314
00315 if ( mSlave && !mSlaveConnected ) return Connecting;
00316
00317 mSlaveConnected = false;
00318 mSlave = KIO::Scheduler::getConnectedSlave( getUrl(), slaveConfig() );
00319 if ( !mSlave ) {
00320 KMessageBox::error(0, i18n("Could not start process for %1.")
00321 .arg( getUrl().protocol() ) );
00322 return Error;
00323 }
00324 if ( mSlave->isConnected() ) {
00325 slotSchedulerSlaveConnected( mSlave );
00326 return Connected;
00327 }
00328
00329 return Connecting;
00330 }
00331
00332 bool ImapAccountBase::handleJobError( KIO::Job *job, const QString& context, bool abortSync )
00333 {
00334 JobIterator it = findJob( job );
00335 if ( it != jobsEnd() && (*it).progressItem )
00336 {
00337 (*it).progressItem->setComplete();
00338 (*it).progressItem = 0;
00339 }
00340 return handleError( job->error(), job->errorText(), job, context, abortSync );
00341 }
00342
00343
00344 void ImapAccountBase::postProcessNewMail( bool showStatusMsg ) {
00345 setCheckingMail(false);
00346 int newMails = 0;
00347 if ( mCountUnread > 0 && mCountUnread > mCountLastUnread ) {
00348 newMails = mCountUnread - mCountLastUnread;
00349 mCountLastUnread = mCountUnread;
00350 mCountUnread = 0;
00351 checkDone( true, CheckOK );
00352 } else {
00353 mCountUnread = 0;
00354 checkDone( false, CheckOK );
00355 }
00356 if ( showStatusMsg )
00357 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00358 name(), newMails);
00359 }
00360
00361
00362 void ImapAccountBase::changeSubscription( bool subscribe, const QString& imapPath, bool quiet )
00363 {
00364
00365 KURL url = getUrl();
00366 url.setPath(imapPath);
00367
00368 QByteArray packedArgs;
00369 QDataStream stream( packedArgs, IO_WriteOnly);
00370
00371 if (subscribe)
00372 stream << (int) 'u' << url;
00373 else
00374 stream << (int) 'U' << url;
00375
00376
00377 if ( makeConnection() != Connected )
00378 return;
00379 KIO::SimpleJob *job = KIO::special(url, packedArgs, false);
00380 KIO::Scheduler::assignJobToSlave(mSlave, job);
00381 jobData jd( url.url(), NULL );
00382
00383 if (subscribe) jd.onlySubscribed = true;
00384 else jd.onlySubscribed = false;
00385 jd.quiet = quiet;
00386 insertJob(job, jd);
00387
00388 connect(job, SIGNAL(result(KIO::Job *)),
00389 SLOT(slotSubscriptionResult(KIO::Job *)));
00390 }
00391
00392
00393 void ImapAccountBase::slotSubscriptionResult( KIO::Job * job )
00394 {
00395
00396 JobIterator it = findJob( job );
00397 if ( it == jobsEnd() ) return;
00398 bool onlySubscribed = (*it).onlySubscribed;
00399 QString path = static_cast<KIO::SimpleJob*>(job)->url().path();
00400 if (job->error())
00401 {
00402 if ( !(*it).quiet )
00403 handleJobError( job, i18n( "Error while trying to subscribe to %1:" ).arg( path ) + '\n' );
00404 emit subscriptionChangeFailed( job->errorString() );
00405
00406 }
00407 else
00408 {
00409 emit subscriptionChanged( path, onlySubscribed );
00410 if (mSlave) removeJob(job);
00411 }
00412 }
00413
00414
00415
00416 void ImapAccountBase::getUserRights( KMFolder* parent, const QString& imapPath )
00417 {
00418
00419
00420
00421
00422 if ( imapPath == "/INBOX/" ) {
00423 if ( parent->folderType() == KMFolderTypeImap )
00424 static_cast<KMFolderImap*>( parent->storage() )->setUserRights( ACLJobs::All );
00425 else if ( parent->folderType() == KMFolderTypeCachedImap )
00426 static_cast<KMFolderCachedImap*>( parent->storage() )->setUserRights( ACLJobs::All );
00427 emit receivedUserRights( parent );
00428 return;
00429 }
00430
00431 KURL url = getUrl();
00432 url.setPath(imapPath);
00433
00434 ACLJobs::GetUserRightsJob* job = ACLJobs::getUserRights( mSlave, url );
00435
00436 jobData jd( url.url(), parent );
00437 jd.cancellable = true;
00438 insertJob(job, jd);
00439
00440 connect(job, SIGNAL(result(KIO::Job *)),
00441 SLOT(slotGetUserRightsResult(KIO::Job *)));
00442 }
00443
00444 void ImapAccountBase::slotGetUserRightsResult( KIO::Job* _job )
00445 {
00446 ACLJobs::GetUserRightsJob* job = static_cast<ACLJobs::GetUserRightsJob *>( _job );
00447 JobIterator it = findJob( job );
00448 if ( it == jobsEnd() ) return;
00449
00450 KMFolder* folder = (*it).parent;
00451 if ( job->error() ) {
00452 if ( job->error() == KIO::ERR_UNSUPPORTED_ACTION )
00453 mACLSupport = false;
00454 else
00455 kdWarning(5006) << "slotGetUserRightsResult: " << job->errorString() << endl;
00456 } else {
00457 #ifndef NDEBUG
00458
00459 #endif
00460
00461 if ( folder->folderType() == KMFolderTypeImap )
00462 static_cast<KMFolderImap*>( folder->storage() )->setUserRights( job->permissions() );
00463 else if ( folder->folderType() == KMFolderTypeCachedImap )
00464 static_cast<KMFolderCachedImap*>( folder->storage() )->setUserRights( job->permissions() );
00465 }
00466 if (mSlave) removeJob(job);
00467 emit receivedUserRights( folder );
00468 }
00469
00470
00471 void ImapAccountBase::getACL( KMFolder* parent, const QString& imapPath )
00472 {
00473 KURL url = getUrl();
00474 url.setPath(imapPath);
00475
00476 ACLJobs::GetACLJob* job = ACLJobs::getACL( mSlave, url );
00477 jobData jd( url.url(), parent );
00478 jd.cancellable = true;
00479 insertJob(job, jd);
00480
00481 connect(job, SIGNAL(result(KIO::Job *)),
00482 SLOT(slotGetACLResult(KIO::Job *)));
00483 }
00484
00485 void ImapAccountBase::slotGetACLResult( KIO::Job* _job )
00486 {
00487 ACLJobs::GetACLJob* job = static_cast<ACLJobs::GetACLJob *>( _job );
00488 JobIterator it = findJob( job );
00489 if ( it == jobsEnd() ) return;
00490
00491 KMFolder* folder = (*it).parent;
00492 emit receivedACL( folder, job, job->entries() );
00493 if (mSlave) removeJob(job);
00494 }
00495
00496
00497
00498 void ImapAccountBase::getStorageQuotaInfo( KMFolder* parent, const QString& imapPath )
00499 {
00500 if ( !mSlave ) return;
00501 KURL url = getUrl();
00502 url.setPath(imapPath);
00503
00504 QuotaJobs::GetStorageQuotaJob* job = QuotaJobs::getStorageQuota( mSlave, url );
00505 jobData jd( url.url(), parent );
00506 jd.cancellable = true;
00507 insertJob(job, jd);
00508
00509 connect(job, SIGNAL(result(KIO::Job *)),
00510 SLOT(slotGetStorageQuotaInfoResult(KIO::Job *)));
00511 }
00512
00513 void ImapAccountBase::slotGetStorageQuotaInfoResult( KIO::Job* _job )
00514 {
00515 QuotaJobs::GetStorageQuotaJob* job = static_cast<QuotaJobs::GetStorageQuotaJob *>( _job );
00516 JobIterator it = findJob( job );
00517 if ( it == jobsEnd() ) return;
00518 if ( job->error() && job->error() == KIO::ERR_UNSUPPORTED_ACTION )
00519 setHasNoQuotaSupport();
00520
00521 KMFolder* folder = (*it).parent;
00522 emit receivedStorageQuotaInfo( folder, job, job->storageQuotaInfo() );
00523 if (mSlave) removeJob(job);
00524 }
00525
00526 void ImapAccountBase::slotNoopTimeout()
00527 {
00528 if ( mSlave ) {
00529 QByteArray packedArgs;
00530 QDataStream stream( packedArgs, IO_WriteOnly );
00531
00532 stream << ( int ) 'N';
00533
00534 KIO::SimpleJob *job = KIO::special( getUrl(), packedArgs, false );
00535 KIO::Scheduler::assignJobToSlave(mSlave, job);
00536 connect( job, SIGNAL(result( KIO::Job * ) ),
00537 this, SLOT( slotSimpleResult( KIO::Job * ) ) );
00538 } else {
00539
00540
00541 mNoopTimer.stop();
00542 }
00543 }
00544
00545 void ImapAccountBase::slotIdleTimeout()
00546 {
00547 if ( mSlave ) {
00548 KIO::Scheduler::disconnectSlave(mSlave);
00549 mSlave = 0;
00550 mSlaveConnected = false;
00551
00552
00553 mIdleTimer.stop();
00554 }
00555 }
00556
00557 void ImapAccountBase::slotAbortRequested( KPIM::ProgressItem* item )
00558 {
00559 if ( item )
00560 item->setComplete();
00561 killAllJobs();
00562 }
00563
00564
00565
00566 void ImapAccountBase::slotSchedulerSlaveError(KIO::Slave *aSlave, int errorCode,
00567 const QString &errorMsg)
00568 {
00569 if (aSlave != mSlave) return;
00570 handleError( errorCode, errorMsg, 0, QString::null, true );
00571 if ( mAskAgain )
00572 if ( makeConnection() != ImapAccountBase::Error )
00573 return;
00574
00575 if ( !mSlaveConnected ) {
00576 mSlaveConnectionError = true;
00577 resetConnectionList( this );
00578 if ( mSlave )
00579 {
00580 KIO::Scheduler::disconnectSlave( slave() );
00581 mSlave = 0;
00582 }
00583 }
00584 emit connectionResult( errorCode, errorMsg );
00585 }
00586
00587
00588 void ImapAccountBase::slotSchedulerSlaveConnected(KIO::Slave *aSlave)
00589 {
00590 if (aSlave != mSlave) return;
00591 mSlaveConnected = true;
00592 mNoopTimer.start( 60000 );
00593 emit connectionResult( 0, QString::null );
00594
00595 if ( mNamespaces.isEmpty() || mNamespaceToDelimiter.isEmpty() ) {
00596 connect( this, SIGNAL( namespacesFetched( const ImapAccountBase::nsDelimMap& ) ),
00597 this, SLOT( slotSaveNamespaces( const ImapAccountBase::nsDelimMap& ) ) );
00598 getNamespaces();
00599 }
00600
00601
00602 QByteArray packedArgs;
00603 QDataStream stream( packedArgs, IO_WriteOnly);
00604 stream << (int) 'c';
00605 KIO::SimpleJob *job = KIO::special( getUrl(), packedArgs, false );
00606 KIO::Scheduler::assignJobToSlave( mSlave, job );
00607 connect( job, SIGNAL(infoMessage(KIO::Job*, const QString&)),
00608 SLOT(slotCapabilitiesResult(KIO::Job*, const QString&)) );
00609 }
00610
00611
00612 void ImapAccountBase::slotCapabilitiesResult( KIO::Job*, const QString& result )
00613 {
00614 mCapabilities = QStringList::split(' ', result.lower() );
00615 kdDebug(5006) << "capabilities:" << mCapabilities << endl;
00616 }
00617
00618
00619 void ImapAccountBase::getNamespaces()
00620 {
00621 disconnect( this, SIGNAL( connectionResult(int, const QString&) ),
00622 this, SLOT( getNamespaces() ) );
00623 if ( makeConnection() != Connected || !mSlave ) {
00624 kdDebug(5006) << "getNamespaces - wait for connection" << endl;
00625 if ( mNamespaces.isEmpty() || mNamespaceToDelimiter.isEmpty() ) {
00626
00627 } else {
00628
00629 connect( this, SIGNAL( connectionResult(int, const QString&) ),
00630 this, SLOT( getNamespaces() ) );
00631 }
00632 return;
00633 }
00634
00635 QByteArray packedArgs;
00636 QDataStream stream( packedArgs, IO_WriteOnly);
00637 stream << (int) 'n';
00638 jobData jd;
00639 jd.total = 1; jd.done = 0; jd.cancellable = true;
00640 jd.progressItem = ProgressManager::createProgressItem(
00641 ProgressManager::getUniqueID(),
00642 i18n("Retrieving Namespaces"),
00643 QString::null, true, useSSL() || useTLS() );
00644 jd.progressItem->setTotalItems( 1 );
00645 connect ( jd.progressItem,
00646 SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
00647 this,
00648 SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
00649 KIO::SimpleJob *job = KIO::special( getUrl(), packedArgs, false );
00650 KIO::Scheduler::assignJobToSlave( mSlave, job );
00651 insertJob( job, jd );
00652 connect( job, SIGNAL( infoMessage(KIO::Job*, const QString&) ),
00653 SLOT( slotNamespaceResult(KIO::Job*, const QString&) ) );
00654 }
00655
00656
00657 void ImapAccountBase::slotNamespaceResult( KIO::Job* job, const QString& str )
00658 {
00659 JobIterator it = findJob( job );
00660 if ( it == jobsEnd() ) return;
00661
00662 nsDelimMap map;
00663 namespaceDelim nsDelim;
00664 QStringList ns = QStringList::split( ",", str );
00665 for ( QStringList::Iterator it = ns.begin(); it != ns.end(); ++it ) {
00666
00667 QStringList parts = QStringList::split( "=", *it, true );
00668 imapNamespace section = imapNamespace( parts[0].toInt() );
00669 if ( map.contains( section ) ) {
00670 nsDelim = map[section];
00671 } else {
00672 nsDelim.clear();
00673 }
00674
00675 nsDelim[parts[1]] = parts[2];
00676 map[section] = nsDelim;
00677 }
00678 removeJob(it);
00679
00680 kdDebug(5006) << "namespaces fetched" << endl;
00681 emit namespacesFetched( map );
00682 }
00683
00684
00685 void ImapAccountBase::slotSaveNamespaces( const ImapAccountBase::nsDelimMap& map )
00686 {
00687 kdDebug(5006) << "slotSaveNamespaces " << name() << endl;
00688
00689 mNamespaces.clear();
00690 mNamespaceToDelimiter.clear();
00691 for ( uint i = 0; i < 3; ++i ) {
00692 imapNamespace section = imapNamespace( i );
00693 namespaceDelim ns = map[ section ];
00694 namespaceDelim::ConstIterator it;
00695 QStringList list;
00696 for ( it = ns.begin(); it != ns.end(); ++it ) {
00697 list += it.key();
00698 mNamespaceToDelimiter[ it.key() ] = it.data();
00699 }
00700 if ( !list.isEmpty() ) {
00701 mNamespaces[section] = list;
00702 }
00703 }
00704
00705 if ( !mOldPrefix.isEmpty() ) {
00706 migratePrefix();
00707 }
00708 emit namespacesFetched();
00709 }
00710
00711
00712 void ImapAccountBase::migratePrefix()
00713 {
00714 if ( !mOldPrefix.isEmpty() && mOldPrefix != "/" ) {
00715
00716 if ( mOldPrefix.startsWith("/") ) {
00717 mOldPrefix = mOldPrefix.right( mOldPrefix.length()-1 );
00718 }
00719 if ( mOldPrefix.endsWith("/") ) {
00720 mOldPrefix = mOldPrefix.left( mOldPrefix.length()-1 );
00721 }
00722 QStringList list = mNamespaces[PersonalNS];
00723 bool done = false;
00724 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00725 if ( (*it).startsWith( mOldPrefix ) ) {
00726
00727 done = true;
00728 kdDebug(5006) << "migratePrefix - no migration needed" << endl;
00729 break;
00730 }
00731 }
00732 if ( !done ) {
00733 QString msg = i18n("KMail has detected a prefix entry in the "
00734 "configuration of the account \"%1\" which is obsolete with the "
00735 "support of IMAP namespaces.").arg( name() );
00736 if ( list.contains( "" ) ) {
00737
00738 list.remove( "" );
00739 list += mOldPrefix;
00740 mNamespaces[PersonalNS] = list;
00741 if ( mNamespaceToDelimiter.contains( "" ) ) {
00742 QString delim = mNamespaceToDelimiter[""];
00743 mNamespaceToDelimiter.remove( "" );
00744 mNamespaceToDelimiter[mOldPrefix] = delim;
00745 }
00746 kdDebug(5006) << "migratePrefix - replaced empty with " << mOldPrefix << endl;
00747 msg += i18n("The configuration was automatically migrated but you should check "
00748 "your account configuration.");
00749 } else if ( list.count() == 1 ) {
00750
00751 QString old = list.first();
00752 list.clear();
00753 list += mOldPrefix;
00754 mNamespaces[PersonalNS] = list;
00755 if ( mNamespaceToDelimiter.contains( old ) ) {
00756 QString delim = mNamespaceToDelimiter[old];
00757 mNamespaceToDelimiter.remove( old );
00758 mNamespaceToDelimiter[mOldPrefix] = delim;
00759 }
00760 kdDebug(5006) << "migratePrefix - replaced single with " << mOldPrefix << endl;
00761 msg += i18n("The configuration was automatically migrated but you should check "
00762 "your account configuration.");
00763 } else {
00764 kdDebug(5006) << "migratePrefix - migration failed" << endl;
00765 msg += i18n("It was not possible to migrate your configuration automatically "
00766 "so please check your account configuration.");
00767 }
00768 KMessageBox::information( kmkernel->getKMMainWidget(), msg );
00769 }
00770 } else
00771 {
00772 kdDebug(5006) << "migratePrefix - no migration needed" << endl;
00773 }
00774 mOldPrefix = "";
00775 }
00776
00777
00778 QString ImapAccountBase::namespaceForFolder( FolderStorage* storage )
00779 {
00780 QString path;
00781 if ( storage->folderType() == KMFolderTypeImap ) {
00782 path = static_cast<KMFolderImap*>( storage )->imapPath();
00783 } else if ( storage->folderType() == KMFolderTypeCachedImap ) {
00784 path = static_cast<KMFolderCachedImap*>( storage )->imapPath();
00785 }
00786
00787 nsMap::Iterator it;
00788 for ( it = mNamespaces.begin(); it != mNamespaces.end(); ++it )
00789 {
00790 QStringList::Iterator strit;
00791 for ( strit = it.data().begin(); strit != it.data().end(); ++strit )
00792 {
00793 QString ns = *strit;
00794 if ( ns.endsWith("/") || ns.endsWith(".") ) {
00795
00796 ns = ns.left( ns.length()-1 );
00797 }
00798
00799 if ( !ns.isEmpty() && path.find( ns ) != -1 ) {
00800 return (*strit);
00801 }
00802 }
00803 }
00804 return QString::null;
00805 }
00806
00807
00808 QString ImapAccountBase::delimiterForNamespace( const QString& prefix )
00809 {
00810
00811
00812 if ( mNamespaceToDelimiter.contains(prefix) ) {
00813 return mNamespaceToDelimiter[prefix];
00814 }
00815
00816
00817
00818 for ( namespaceDelim::ConstIterator it = mNamespaceToDelimiter.begin();
00819 it != mNamespaceToDelimiter.end(); ++it ) {
00820
00821
00822 QString stripped = it.key().left( it.key().length() - 1 );
00823 if ( !it.key().isEmpty() &&
00824 ( prefix.contains( it.key() ) || prefix.contains( stripped ) ) ) {
00825 return it.data();
00826 }
00827 }
00828
00829
00830 if ( mNamespaceToDelimiter.contains( "" ) ) {
00831 return mNamespaceToDelimiter[""];
00832 }
00833
00834
00835 return QString::null;
00836 }
00837
00838
00839 QString ImapAccountBase::delimiterForFolder( FolderStorage* storage )
00840 {
00841 QString prefix = namespaceForFolder( storage );
00842 QString delim = delimiterForNamespace( prefix );
00843 return delim;
00844 }
00845
00846
00847 void ImapAccountBase::slotSimpleResult(KIO::Job * job)
00848 {
00849 JobIterator it = findJob( job );
00850 bool quiet = false;
00851 if (it != mapJobData.end()) {
00852 quiet = (*it).quiet;
00853 if ( !(job->error() && !quiet) )
00854 removeJob(it);
00855 }
00856 if (job->error()) {
00857 if (!quiet)
00858 handleJobError(job, QString::null );
00859 else {
00860 if ( job->error() == KIO::ERR_CONNECTION_BROKEN && slave() ) {
00861
00862
00863 KIO::Scheduler::disconnectSlave( slave() );
00864 mSlave = 0;
00865 }
00866 if (job->error() == KIO::ERR_SLAVE_DIED)
00867 slaveDied();
00868 }
00869 }
00870 }
00871
00872
00873 bool ImapAccountBase::handlePutError( KIO::Job* job, jobData& jd, KMFolder* folder )
00874 {
00875 Q_ASSERT( !jd.msgList.isEmpty() );
00876 KMMessage* msg = jd.msgList.first();
00877
00878
00879 const QString subject = msg->subject().isEmpty() ? i18n( "<unknown>" ) : QString("\"%1\"").arg( msg->subject() );
00880 const QString from = msg->from().isEmpty() ? i18n( "<unknown>" ) : msg->from();
00881 QString myError = "<p><b>" + i18n("Error while uploading message")
00882 + "</b></p><p>"
00883 + i18n("Could not upload the message dated %1 from <i>%2</i> with subject <i>%3</i> to the server.").arg( msg->dateStr(), QStyleSheet::escape( from ), QStyleSheet::escape( subject ) )
00884 + "</p><p>"
00885 + i18n("The destination folder was: <b>%1</b>.").arg( QStyleSheet::escape( folder->prettyURL() ) )
00886 + "</p><p>"
00887 + i18n("The server reported:") + "</p>";
00888 return handleJobError( job, myError );
00889 }
00890
00891 QString ImapAccountBase::prettifyQuotaError( const QString& _error, KIO::Job * job )
00892 {
00893 QString error = _error;
00894 if ( error.find( "quota", 0, false ) == -1 ) return error;
00895
00896 JobIterator it = findJob( job );
00897 QString quotaAsString( i18n("No detailed quota information available.") );
00898 bool readOnly = false;
00899 if (it != mapJobData.end()) {
00900 const KMFolder * const folder = (*it).parent;
00901 if( !folder ) return _error;
00902 const KMFolderCachedImap * const imap = dynamic_cast<const KMFolderCachedImap*>( folder->storage() );
00903 if ( imap ) {
00904 quotaAsString = imap->quotaInfo().toString();
00905 }
00906 readOnly = folder->isReadOnly();
00907 }
00908 error = i18n("The folder is too close to its quota limit. (%1)").arg( quotaAsString );
00909 if ( readOnly ) {
00910 error += i18n("\nSince you do not have write privileges on this folder, "
00911 "please ask the owner of the folder to free up some space in it.");
00912 }
00913 return error;
00914 }
00915
00916
00917 bool ImapAccountBase::handleError( int errorCode, const QString &errorMsg, KIO::Job* job, const QString& context, bool abortSync )
00918 {
00919
00920 QStringList errors;
00921 if ( job && job->error() != KIO::ERR_SLAVE_DEFINED )
00922 errors = job->detailedErrorStrings();
00923
00924 bool jobsKilled = true;
00925 switch( errorCode ) {
00926 case KIO::ERR_SLAVE_DIED: slaveDied(); killAllJobs( true ); break;
00927 case KIO::ERR_COULD_NOT_AUTHENTICATE:
00928 mAskAgain = true;
00929
00930 case KIO::ERR_CONNECTION_BROKEN:
00931 case KIO::ERR_COULD_NOT_CONNECT:
00932 case KIO::ERR_SERVER_TIMEOUT:
00933
00934 killAllJobs( true );
00935 break;
00936 case KIO::ERR_COULD_NOT_LOGIN:
00937 case KIO::ERR_USER_CANCELED:
00938 killAllJobs( false );
00939 break;
00940 default:
00941 if ( abortSync )
00942 killAllJobs( false );
00943 else
00944 jobsKilled = false;
00945 break;
00946 }
00947
00948
00949 if ( !mErrorDialogIsActive && errorCode != KIO::ERR_USER_CANCELED ) {
00950 mErrorDialogIsActive = true;
00951 QString msg = context + '\n' + prettifyQuotaError( KIO::buildErrorString( errorCode, errorMsg ), job );
00952 QString caption = i18n("Error");
00953
00954 if ( jobsKilled || errorCode == KIO::ERR_COULD_NOT_LOGIN ) {
00955 if ( errorCode == KIO::ERR_SERVER_TIMEOUT || errorCode == KIO::ERR_CONNECTION_BROKEN ) {
00956 msg = i18n("The connection to the server %1 was unexpectedly closed or timed out. It will be re-established automatically if possible.").
00957 arg( name() );
00958 KMessageBox::information( kapp->activeWindow(), msg, caption, "kmailConnectionBrokenErrorDialog" );
00959
00960 if ( errorCode == KIO::ERR_CONNECTION_BROKEN )
00961 KPIM::BroadcastStatus::instance()->setStatusMsg(
00962 i18n( "The connection to account %1 was broken." ).arg( name() ) );
00963 else if ( errorCode == KIO::ERR_SERVER_TIMEOUT )
00964 KPIM::BroadcastStatus::instance()->setStatusMsg(
00965 i18n( "The connection to account %1 timed out." ).arg( name() ) );
00966 } else {
00967 if ( !errors.isEmpty() )
00968 KMessageBox::detailedError( kapp->activeWindow(), msg, errors.join("\n").prepend("<qt>"), caption );
00969 else
00970 KMessageBox::error( kapp->activeWindow(), msg, caption );
00971 }
00972 } else {
00973 if ( errors.count() >= 3 ) {
00974 QString error = prettifyQuotaError( errors[1], job );
00975 msg = QString( "<qt>") + context + error + '\n' + errors[2];
00976 caption = errors[0];
00977 }
00978 int ret = KMessageBox::warningContinueCancel( kapp->activeWindow(), msg, caption );
00979 if ( ret == KMessageBox::Cancel ) {
00980 jobsKilled = true;
00981 killAllJobs( false );
00982 }
00983 }
00984 mErrorDialogIsActive = false;
00985 } else {
00986 if ( mErrorDialogIsActive )
00987 kdDebug(5006) << "suppressing error:" << errorMsg << endl;
00988 }
00989 if ( job && !jobsKilled )
00990 removeJob( job );
00991 return !jobsKilled;
00992 }
00993
00994
00995 void ImapAccountBase::cancelMailCheck()
00996 {
00997 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00998 while ( it != mapJobData.end() ) {
00999 kdDebug(5006) << "cancelMailCheck: job is cancellable: " << (*it).cancellable << endl;
01000 if ( (*it).cancellable ) {
01001 it.key()->kill();
01002 QMap<KIO::Job*, jobData>::Iterator rmit = it;
01003 ++it;
01004 mapJobData.remove( rmit );
01005
01006 mSlave = 0;
01007 } else
01008 ++it;
01009 }
01010
01011 for( QPtrListIterator<FolderJob> it( mJobList ); it.current(); ++it ) {
01012 if ( it.current()->isCancellable() ) {
01013 FolderJob* job = it.current();
01014 job->setPassiveDestructor( true );
01015 mJobList.remove( job );
01016 delete job;
01017 } else
01018 ++it;
01019 }
01020 }
01021
01022
01023 void ImapAccountBase::processNewMailInFolder( KMFolder* folder, FolderListType type )
01024 {
01025 if ( mFoldersQueuedForChecking.contains( folder ) )
01026 return;
01027 mFoldersQueuedForChecking.append( folder );
01028 mCheckingSingleFolder = ( type == Single );
01029 if ( checkingMail() )
01030 {
01031 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01032 this, SLOT( slotCheckQueuedFolders() ) );
01033 connect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01034 this, SLOT( slotCheckQueuedFolders() ) );
01035 } else {
01036 slotCheckQueuedFolders();
01037 }
01038 }
01039
01040
01041 void ImapAccountBase::slotCheckQueuedFolders()
01042 {
01043 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01044 this, SLOT( slotCheckQueuedFolders() ) );
01045
01046 QValueList<QGuardedPtr<KMFolder> > mSaveList = mMailCheckFolders;
01047 mMailCheckFolders = mFoldersQueuedForChecking;
01048 if ( kmkernel->acctMgr() )
01049 kmkernel->acctMgr()->singleCheckMail(this, true);
01050 mMailCheckFolders = mSaveList;
01051 mFoldersQueuedForChecking.clear();
01052 }
01053
01054
01055 bool ImapAccountBase::checkingMail( KMFolder *folder )
01056 {
01057 if (checkingMail() && mFoldersQueuedForChecking.contains(folder))
01058 return true;
01059 return false;
01060 }
01061
01062
01063 void ImapAccountBase::handleBodyStructure( QDataStream & stream, KMMessage * msg,
01064 const AttachmentStrategy *as )
01065 {
01066 mBodyPartList.clear();
01067 mCurrentMsg = msg;
01068
01069 msg->deleteBodyParts();
01070
01071 constructParts( stream, 1, 0, 0, msg->asDwMessage() );
01072 if ( mBodyPartList.count() == 1 )
01073 msg->deleteBodyParts();
01074
01075 if ( !as )
01076 {
01077 kdWarning(5006) << k_funcinfo << " - found no attachment strategy!" << endl;
01078 return;
01079 }
01080
01081
01082 BodyVisitor *visitor = BodyVisitorFactory::getVisitor( as );
01083 visitor->visit( mBodyPartList );
01084 QPtrList<KMMessagePart> parts = visitor->partsToLoad();
01085 delete visitor;
01086 QPtrListIterator<KMMessagePart> it( parts );
01087 KMMessagePart *part;
01088 int partsToLoad = 0;
01089
01090 while ( (part = it.current()) != 0 )
01091 {
01092 ++it;
01093 if ( part->loadPart() )
01094 {
01095 ++partsToLoad;
01096 }
01097 }
01098
01099
01100
01101 if ( mBodyPartList.count() == 1 && partsToLoad == 0 )
01102 partsToLoad = 1;
01103
01104 if ( (mBodyPartList.count() * 0.5) < partsToLoad )
01105 {
01106
01107
01108 kdDebug(5006) << "Falling back to normal mode" << endl;
01109 FolderJob *job = msg->parent()->createJob(
01110 msg, FolderJob::tGetMessage, 0, "TEXT" );
01111 job->start();
01112 return;
01113 }
01114 it.toFirst();
01115 while ( (part = it.current()) != 0 )
01116 {
01117 ++it;
01118 kdDebug(5006) << "ImapAccountBase::handleBodyStructure - load " << part->partSpecifier()
01119 << " (" << part->originalContentTypeStr() << ")" << endl;
01120 if ( part->loadHeaders() )
01121 {
01122 kdDebug(5006) << "load HEADER" << endl;
01123 FolderJob *job = msg->parent()->createJob(
01124 msg, FolderJob::tGetMessage, 0, part->partSpecifier()+".MIME" );
01125 job->start();
01126 }
01127 if ( part->loadPart() )
01128 {
01129 kdDebug(5006) << "load Part" << endl;
01130 FolderJob *job = msg->parent()->createJob(
01131 msg, FolderJob::tGetMessage, 0, part->partSpecifier() );
01132 job->start();
01133 }
01134 }
01135 }
01136
01137
01138 void ImapAccountBase::constructParts( QDataStream & stream, int count, KMMessagePart* parentKMPart,
01139 DwBodyPart * parent, const DwMessage * dwmsg )
01140 {
01141 int children;
01142 for (int i = 0; i < count; i++)
01143 {
01144 stream >> children;
01145 KMMessagePart* part = new KMMessagePart( stream );
01146 part->setParent( parentKMPart );
01147 mBodyPartList.append( part );
01148 kdDebug(5006) << "ImapAccountBase::constructParts - created id " << part->partSpecifier()
01149 << " of type " << part->originalContentTypeStr() << endl;
01150 DwBodyPart *dwpart = mCurrentMsg->createDWBodyPart( part );
01151
01152 if ( parent )
01153 {
01154
01155 parent->Body().AddBodyPart( dwpart );
01156 dwpart->Parse();
01157
01158
01159 } else if ( part->partSpecifier() != "0" &&
01160 !part->partSpecifier().endsWith(".HEADER") )
01161 {
01162
01163 dwmsg->Body().AddBodyPart( dwpart );
01164 dwpart->Parse();
01165
01166
01167 } else
01168 dwpart = 0;
01169
01170 if ( !parentKMPart )
01171 parentKMPart = part;
01172
01173 if (children > 0)
01174 {
01175 DwBodyPart* newparent = dwpart;
01176 const DwMessage* newmsg = dwmsg;
01177 if ( part->originalContentTypeStr() == "MESSAGE/RFC822" && dwpart &&
01178 dwpart->Body().Message() )
01179 {
01180
01181 newparent = 0;
01182 newmsg = dwpart->Body().Message();
01183 }
01184 KMMessagePart* newParentKMPart = part;
01185 if ( part->partSpecifier().endsWith(".HEADER") )
01186 newParentKMPart = parentKMPart;
01187
01188 constructParts( stream, children, newParentKMPart, newparent, newmsg );
01189 }
01190 }
01191 }
01192
01193
01194 void ImapAccountBase::setImapStatus( KMFolder* folder, const QString& path, const QCString& flags )
01195 {
01196
01197 kdDebug(5006) << "setImapStatus path=" << path << " to: " << flags << endl;
01198 KURL url = getUrl();
01199 url.setPath(path);
01200
01201 QByteArray packedArgs;
01202 QDataStream stream( packedArgs, IO_WriteOnly);
01203
01204 stream << (int) 'S' << url << flags;
01205
01206 if ( makeConnection() != Connected )
01207 return;
01208
01209 KIO::SimpleJob *job = KIO::special(url, packedArgs, false);
01210 KIO::Scheduler::assignJobToSlave(slave(), job);
01211 ImapAccountBase::jobData jd( url.url(), folder );
01212 jd.path = path;
01213 insertJob(job, jd);
01214 connect(job, SIGNAL(result(KIO::Job *)),
01215 SLOT(slotSetStatusResult(KIO::Job *)));
01216 }
01217
01218 void ImapAccountBase::setImapSeenStatus(KMFolder * folder, const QString & path, bool seen)
01219 {
01220 KURL url = getUrl();
01221 url.setPath(path);
01222
01223 QByteArray packedArgs;
01224 QDataStream stream( packedArgs, IO_WriteOnly);
01225
01226 stream << (int) 's' << url << seen;
01227
01228 if ( makeConnection() != Connected )
01229 return;
01230
01231 KIO::SimpleJob *job = KIO::special(url, packedArgs, false);
01232 KIO::Scheduler::assignJobToSlave(slave(), job);
01233 ImapAccountBase::jobData jd( url.url(), folder );
01234 jd.path = path;
01235 insertJob(job, jd);
01236 connect(job, SIGNAL(result(KIO::Job *)),
01237 SLOT(slotSetStatusResult(KIO::Job *)));
01238 }
01239
01240
01241 void ImapAccountBase::slotSetStatusResult(KIO::Job * job)
01242 {
01243 ImapAccountBase::JobIterator it = findJob(job);
01244 if ( it == jobsEnd() ) return;
01245 int errorCode = job->error();
01246 KMFolder * const parent = (*it).parent;
01247 const QString path = (*it).path;
01248 if (errorCode && errorCode != KIO::ERR_CANNOT_OPEN_FOR_WRITING)
01249 {
01250 bool cont = handleJobError( job, i18n( "Error while uploading status of messages to server: " ) + '\n' );
01251 emit imapStatusChanged( parent, path, cont );
01252 }
01253 else
01254 {
01255 emit imapStatusChanged( parent, path, true );
01256 removeJob(it);
01257 }
01258 }
01259
01260
01261 void ImapAccountBase::setFolder(KMFolder* folder, bool addAccount)
01262 {
01263 if (folder)
01264 {
01265 folder->setSystemLabel(name());
01266 folder->setId(id());
01267 }
01268 NetworkAccount::setFolder(folder, addAccount);
01269 }
01270
01271
01272 void ImapAccountBase::removeJob( JobIterator& it )
01273 {
01274 if( (*it).progressItem ) {
01275 (*it).progressItem->setComplete();
01276 (*it).progressItem = 0;
01277 }
01278 mapJobData.remove( it );
01279 }
01280
01281
01282 void KMail::ImapAccountBase::removeJob( KIO::Job* job )
01283 {
01284 mapJobData.remove( job );
01285 }
01286
01287
01288 KPIM::ProgressItem* ImapAccountBase::listDirProgressItem()
01289 {
01290 if ( !mListDirProgressItem )
01291 {
01292 mListDirProgressItem = ProgressManager::createProgressItem(
01293 "ListDir" + name(),
01294 QStyleSheet::escape( name() ),
01295 i18n("retrieving folders"),
01296 true,
01297 useSSL() || useTLS() );
01298 connect ( mListDirProgressItem,
01299 SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
01300 this,
01301 SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
01302
01303
01304
01305 unsigned int count = folderCount();
01306 mListDirProgressItem->setTotalItems( count + (unsigned int)(count*0.05) );
01307 }
01308 return mListDirProgressItem;
01309 }
01310
01311
01312 unsigned int ImapAccountBase::folderCount() const
01313 {
01314 if ( !rootFolder() || !rootFolder()->folder() || !rootFolder()->folder()->child() )
01315 return 0;
01316 return kmkernel->imapFolderMgr()->folderCount( rootFolder()->folder()->child() );
01317 }
01318
01319
01320 QString ImapAccountBase::addPathToNamespace( const QString& prefix )
01321 {
01322 QString myPrefix = prefix;
01323 if ( !myPrefix.startsWith( "/" ) ) {
01324 myPrefix = "/" + myPrefix;
01325 }
01326 if ( !myPrefix.endsWith( "/" ) ) {
01327 myPrefix += "/";
01328 }
01329
01330 return myPrefix;
01331 }
01332
01333
01334 bool ImapAccountBase::isNamespaceFolder( QString& name )
01335 {
01336 QStringList ns = mNamespaces[OtherUsersNS];
01337 ns += mNamespaces[SharedNS];
01338 ns += mNamespaces[PersonalNS];
01339 QString nameWithDelimiter;
01340 for ( QStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
01341 {
01342 nameWithDelimiter = name + delimiterForNamespace( *it );
01343 if ( *it == name || *it == nameWithDelimiter )
01344 return true;
01345 }
01346 return false;
01347 }
01348
01349
01350 ImapAccountBase::nsDelimMap ImapAccountBase::namespacesWithDelimiter()
01351 {
01352 nsDelimMap map;
01353 nsMap::ConstIterator it;
01354 for ( uint i = 0; i < 3; ++i )
01355 {
01356 imapNamespace section = imapNamespace( i );
01357 QStringList namespaces = mNamespaces[section];
01358 namespaceDelim nsDelim;
01359 QStringList::Iterator lit;
01360 for ( lit = namespaces.begin(); lit != namespaces.end(); ++lit )
01361 {
01362 nsDelim[*lit] = delimiterForNamespace( *lit );
01363 }
01364 map[section] = nsDelim;
01365 }
01366 return map;
01367 }
01368
01369
01370 QString ImapAccountBase::createImapPath( const QString& parent,
01371 const QString& folderName )
01372 {
01373 kdDebug(5006) << "createImapPath parent="<<parent<<", folderName="<<folderName<<endl;
01374 QString newName = parent;
01375
01376 if ( newName.endsWith("/") ) {
01377 newName = newName.left( newName.length() - 1 );
01378 }
01379
01380 QString delim = delimiterForNamespace( newName );
01381
01382 if ( delim.isEmpty() ) {
01383 delim = "/";
01384 }
01385 if ( !newName.isEmpty() &&
01386 !newName.endsWith( delim ) && !folderName.startsWith( delim ) ) {
01387 newName = newName + delim;
01388 }
01389 newName = newName + folderName;
01390
01391 if ( !newName.endsWith("/") ) {
01392 newName = newName + "/";
01393 }
01394
01395 return newName;
01396 }
01397
01398
01399 QString ImapAccountBase::createImapPath( FolderStorage* parent,
01400 const QString& folderName )
01401 {
01402 QString path;
01403 if ( parent->folderType() == KMFolderTypeImap ) {
01404 path = static_cast<KMFolderImap*>( parent )->imapPath();
01405 } else if ( parent->folderType() == KMFolderTypeCachedImap ) {
01406 path = static_cast<KMFolderCachedImap*>( parent )->imapPath();
01407 } else {
01408
01409 return path;
01410 }
01411
01412 return createImapPath( path, folderName );
01413 }
01414
01415
01416 bool ImapAccountBase::locallySubscribedTo( const QString& imapPath )
01417 {
01418 return mLocalSubscriptionBlackList.find( imapPath ) == mLocalSubscriptionBlackList.end();
01419 }
01420
01421 void ImapAccountBase::changeLocalSubscription( const QString& imapPath, bool subscribe )
01422 {
01423 if ( subscribe ) {
01424
01425 mLocalSubscriptionBlackList.erase( imapPath );
01426 } else {
01427
01428 mLocalSubscriptionBlackList.insert( imapPath );
01429 }
01430 }
01431
01432
01433 QStringList ImapAccountBase::locallyBlacklistedFolders() const
01434 {
01435 QStringList list;
01436 std::set<QString>::const_iterator it = mLocalSubscriptionBlackList.begin();
01437 std::set<QString>::const_iterator end = mLocalSubscriptionBlackList.end();
01438 for ( ; it != end ; ++it )
01439 list.append( *it );
01440 return list;
01441 }
01442
01443 void ImapAccountBase::localBlacklistFromStringList( const QStringList &list )
01444 {
01445 for( QStringList::ConstIterator it = list.constBegin( ); it != list.constEnd( ); ++it )
01446 mLocalSubscriptionBlackList.insert( *it );
01447 }
01448
01449 }
01450
01451 #include "imapaccountbase.moc"