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