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 %2 with subject %3 on the server.").arg( msg->dateStr(), QStyleSheet::escape( from ), QStyleSheet::escape( subject ) )
00879 + "</p><p>"
00880 + i18n("The destination folder was %1, which has the URL %2.").arg( QStyleSheet::escape( folder->label() ), QStyleSheet::escape( jd.htmlURL() ) )
00881 + "</p><p>"
00882 + i18n("The error message from the server communication is here:") + "</p>";
00883 return handleJobError( job, myError );
00884 }
00885
00886
00887 bool ImapAccountBase::handleError( int errorCode, const QString &errorMsg, KIO::Job* job, const QString& context, bool abortSync )
00888 {
00889
00890 QStringList errors;
00891 if ( job && job->error() != KIO::ERR_SLAVE_DEFINED )
00892 errors = job->detailedErrorStrings();
00893
00894 bool jobsKilled = true;
00895 switch( errorCode ) {
00896 case KIO::ERR_SLAVE_DIED: slaveDied(); killAllJobs( true ); break;
00897 case KIO::ERR_COULD_NOT_AUTHENTICATE:
00898 mAskAgain = true;
00899
00900 case KIO::ERR_CONNECTION_BROKEN:
00901 case KIO::ERR_COULD_NOT_CONNECT:
00902 case KIO::ERR_SERVER_TIMEOUT:
00903
00904 killAllJobs( true );
00905 break;
00906 case KIO::ERR_COULD_NOT_LOGIN:
00907 case KIO::ERR_USER_CANCELED:
00908 killAllJobs( false );
00909 break;
00910 default:
00911 if ( abortSync )
00912 killAllJobs( false );
00913 else
00914 jobsKilled = false;
00915 break;
00916 }
00917
00918
00919 if ( !mErrorDialogIsActive && errorCode != KIO::ERR_USER_CANCELED ) {
00920 mErrorDialogIsActive = true;
00921 QString msg = context + '\n' + KIO::buildErrorString( errorCode, errorMsg );
00922 QString caption = i18n("Error");
00923
00924 if ( jobsKilled || errorCode == KIO::ERR_COULD_NOT_LOGIN ) {
00925 if ( errorCode == KIO::ERR_SERVER_TIMEOUT || errorCode == KIO::ERR_CONNECTION_BROKEN ) {
00926 msg = i18n("The connection to the server %1 was unexpectedly closed or timed out. It will be re-established automatically if possible.").
00927 arg( name() );
00928 KMessageBox::information( kapp->activeWindow(), msg, caption, "kmailConnectionBrokenErrorDialog" );
00929
00930 if ( errorCode == KIO::ERR_CONNECTION_BROKEN )
00931 KPIM::BroadcastStatus::instance()->setStatusMsg(
00932 i18n( "The connection to account %1 was broken." ).arg( name() ) );
00933 else if ( errorCode == KIO::ERR_SERVER_TIMEOUT )
00934 KPIM::BroadcastStatus::instance()->setStatusMsg(
00935 i18n( "The connection to account %1 timed out." ).arg( name() ) );
00936 } else {
00937 if ( !errors.isEmpty() )
00938 KMessageBox::detailedError( kapp->activeWindow(), msg, errors.join("\n").prepend("<qt>"), caption );
00939 else
00940 KMessageBox::error( kapp->activeWindow(), msg, caption );
00941 }
00942 }
00943 else {
00944 if ( errors.count() >= 3 ) {
00945 msg = QString( "<qt>") + context + errors[1] + '\n' + errors[2];
00946 caption = errors[0];
00947 }
00948 int ret = KMessageBox::warningContinueCancel( kapp->activeWindow(), msg, caption );
00949 if ( ret == KMessageBox::Cancel ) {
00950 jobsKilled = true;
00951 killAllJobs( false );
00952 }
00953 }
00954 mErrorDialogIsActive = false;
00955 } else {
00956 if ( mErrorDialogIsActive )
00957 kdDebug(5006) << "suppressing error:" << errorMsg << endl;
00958 }
00959 if ( job && !jobsKilled )
00960 removeJob( job );
00961 return !jobsKilled;
00962 }
00963
00964
00965 void ImapAccountBase::cancelMailCheck()
00966 {
00967 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00968 while ( it != mapJobData.end() ) {
00969 kdDebug(5006) << "cancelMailCheck: job is cancellable: " << (*it).cancellable << endl;
00970 if ( (*it).cancellable ) {
00971 it.key()->kill();
00972 QMap<KIO::Job*, jobData>::Iterator rmit = it;
00973 ++it;
00974 mapJobData.remove( rmit );
00975
00976 mSlave = 0;
00977 } else
00978 ++it;
00979 }
00980
00981 for( QPtrListIterator<FolderJob> it( mJobList ); it.current(); ++it ) {
00982 if ( it.current()->isCancellable() ) {
00983 FolderJob* job = it.current();
00984 job->setPassiveDestructor( true );
00985 mJobList.remove( job );
00986 delete job;
00987 } else
00988 ++it;
00989 }
00990 }
00991
00992
00993
00994 QString ImapAccountBase::jobData::htmlURL() const
00995 {
00996 KURL u( url );
00997 return u.htmlURL();
00998 }
00999
01000
01001 void ImapAccountBase::processNewMailSingleFolder(KMFolder* folder)
01002 {
01003 mFoldersQueuedForChecking.append(folder);
01004 mCheckingSingleFolder = true;
01005 if ( checkingMail() )
01006 {
01007 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01008 this, SLOT( slotCheckQueuedFolders() ) );
01009 connect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01010 this, SLOT( slotCheckQueuedFolders() ) );
01011 } else {
01012 slotCheckQueuedFolders();
01013 }
01014 }
01015
01016
01017 void ImapAccountBase::slotCheckQueuedFolders()
01018 {
01019 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01020 this, SLOT( slotCheckQueuedFolders() ) );
01021
01022 QValueList<QGuardedPtr<KMFolder> > mSaveList = mMailCheckFolders;
01023 mMailCheckFolders = mFoldersQueuedForChecking;
01024 if ( kmkernel->acctMgr() )
01025 kmkernel->acctMgr()->singleCheckMail(this, true);
01026 mMailCheckFolders = mSaveList;
01027 mFoldersQueuedForChecking.clear();
01028 }
01029
01030
01031 bool ImapAccountBase::checkingMail( KMFolder *folder )
01032 {
01033 if (checkingMail() && mFoldersQueuedForChecking.contains(folder))
01034 return true;
01035 return false;
01036 }
01037
01038
01039 void ImapAccountBase::handleBodyStructure( QDataStream & stream, KMMessage * msg,
01040 const AttachmentStrategy *as )
01041 {
01042 mBodyPartList.clear();
01043 mCurrentMsg = msg;
01044
01045 msg->deleteBodyParts();
01046
01047 constructParts( stream, 1, 0, 0, msg->asDwMessage() );
01048 if ( mBodyPartList.count() == 1 )
01049 msg->deleteBodyParts();
01050
01051 if ( !as )
01052 {
01053 kdWarning(5006) << k_funcinfo << " - found no attachment strategy!" << endl;
01054 return;
01055 }
01056
01057
01058 BodyVisitor *visitor = BodyVisitorFactory::getVisitor( as );
01059 visitor->visit( mBodyPartList );
01060 QPtrList<KMMessagePart> parts = visitor->partsToLoad();
01061 delete visitor;
01062 QPtrListIterator<KMMessagePart> it( parts );
01063 KMMessagePart *part;
01064 int partsToLoad = 0;
01065
01066 while ( (part = it.current()) != 0 )
01067 {
01068 ++it;
01069 if ( part->loadPart() )
01070 {
01071 ++partsToLoad;
01072 }
01073 }
01074
01075
01076
01077 if ( mBodyPartList.count() == 1 && partsToLoad == 0 )
01078 partsToLoad = 1;
01079
01080 if ( (mBodyPartList.count() * 0.5) < partsToLoad )
01081 {
01082
01083
01084 kdDebug(5006) << "Falling back to normal mode" << endl;
01085 FolderJob *job = msg->parent()->createJob(
01086 msg, FolderJob::tGetMessage, 0, "TEXT" );
01087 job->start();
01088 return;
01089 }
01090 it.toFirst();
01091 while ( (part = it.current()) != 0 )
01092 {
01093 ++it;
01094 kdDebug(5006) << "ImapAccountBase::handleBodyStructure - load " << part->partSpecifier()
01095 << " (" << part->originalContentTypeStr() << ")" << endl;
01096 if ( part->loadHeaders() )
01097 {
01098 kdDebug(5006) << "load HEADER" << endl;
01099 FolderJob *job = msg->parent()->createJob(
01100 msg, FolderJob::tGetMessage, 0, part->partSpecifier()+".MIME" );
01101 job->start();
01102 }
01103 if ( part->loadPart() )
01104 {
01105 kdDebug(5006) << "load Part" << endl;
01106 FolderJob *job = msg->parent()->createJob(
01107 msg, FolderJob::tGetMessage, 0, part->partSpecifier() );
01108 job->start();
01109 }
01110 }
01111 }
01112
01113
01114 void ImapAccountBase::constructParts( QDataStream & stream, int count, KMMessagePart* parentKMPart,
01115 DwBodyPart * parent, const DwMessage * dwmsg )
01116 {
01117 int children;
01118 for (int i = 0; i < count; i++)
01119 {
01120 stream >> children;
01121 KMMessagePart* part = new KMMessagePart( stream );
01122 part->setParent( parentKMPart );
01123 mBodyPartList.append( part );
01124 kdDebug(5006) << "ImapAccountBase::constructParts - created id " << part->partSpecifier()
01125 << " of type " << part->originalContentTypeStr() << endl;
01126 DwBodyPart *dwpart = mCurrentMsg->createDWBodyPart( part );
01127
01128 if ( parent )
01129 {
01130
01131 parent->Body().AddBodyPart( dwpart );
01132 dwpart->Parse();
01133
01134
01135 } else if ( part->partSpecifier() != "0" &&
01136 !part->partSpecifier().endsWith(".HEADER") )
01137 {
01138
01139 dwmsg->Body().AddBodyPart( dwpart );
01140 dwpart->Parse();
01141
01142
01143 } else
01144 dwpart = 0;
01145
01146 if ( !parentKMPart )
01147 parentKMPart = part;
01148
01149 if (children > 0)
01150 {
01151 DwBodyPart* newparent = dwpart;
01152 const DwMessage* newmsg = dwmsg;
01153 if ( part->originalContentTypeStr() == "MESSAGE/RFC822" && dwpart &&
01154 dwpart->Body().Message() )
01155 {
01156
01157 newparent = 0;
01158 newmsg = dwpart->Body().Message();
01159 }
01160 KMMessagePart* newParentKMPart = part;
01161 if ( part->partSpecifier().endsWith(".HEADER") )
01162 newParentKMPart = parentKMPart;
01163
01164 constructParts( stream, children, newParentKMPart, newparent, newmsg );
01165 }
01166 }
01167 }
01168
01169
01170 void ImapAccountBase::setImapStatus( KMFolder* folder, const QString& path, const QCString& flags )
01171 {
01172
01173 kdDebug(5006) << "setImapStatus path=" << path << " to: " << flags << endl;
01174 KURL url = getUrl();
01175 url.setPath(path);
01176
01177 QByteArray packedArgs;
01178 QDataStream stream( packedArgs, IO_WriteOnly);
01179
01180 stream << (int) 'S' << url << flags;
01181
01182 if ( makeConnection() != Connected )
01183 return;
01184
01185 KIO::SimpleJob *job = KIO::special(url, packedArgs, FALSE);
01186 KIO::Scheduler::assignJobToSlave(slave(), job);
01187 ImapAccountBase::jobData jd( url.url(), folder );
01188 jd.path = path;
01189 insertJob(job, jd);
01190 connect(job, SIGNAL(result(KIO::Job *)),
01191 SLOT(slotSetStatusResult(KIO::Job *)));
01192 }
01193
01194 void ImapAccountBase::setImapSeenStatus(KMFolder * folder, const QString & path, bool seen)
01195 {
01196 KURL url = getUrl();
01197 url.setPath(path);
01198
01199 QByteArray packedArgs;
01200 QDataStream stream( packedArgs, IO_WriteOnly);
01201
01202 stream << (int) 's' << url << seen;
01203
01204 if ( makeConnection() != Connected )
01205 return;
01206
01207 KIO::SimpleJob *job = KIO::special(url, packedArgs, false);
01208 KIO::Scheduler::assignJobToSlave(slave(), job);
01209 ImapAccountBase::jobData jd( url.url(), folder );
01210 jd.path = path;
01211 insertJob(job, jd);
01212 connect(job, SIGNAL(result(KIO::Job *)),
01213 SLOT(slotSetStatusResult(KIO::Job *)));
01214 }
01215
01216
01217 void ImapAccountBase::slotSetStatusResult(KIO::Job * job)
01218 {
01219 ImapAccountBase::JobIterator it = findJob(job);
01220 if ( it == jobsEnd() ) return;
01221 int errorCode = job->error();
01222 KMFolder * const parent = (*it).parent;
01223 const QString path = (*it).path;
01224 if (errorCode && errorCode != KIO::ERR_CANNOT_OPEN_FOR_WRITING)
01225 {
01226 bool cont = handleJobError( job, i18n( "Error while uploading status of messages to server: " ) + '\n' );
01227 emit imapStatusChanged( parent, path, cont );
01228 }
01229 else
01230 {
01231 emit imapStatusChanged( parent, path, true );
01232 removeJob(it);
01233 }
01234 }
01235
01236
01237 void ImapAccountBase::setFolder(KMFolder* folder, bool addAccount)
01238 {
01239 if (folder)
01240 {
01241 folder->setSystemLabel(name());
01242 folder->setId(id());
01243 }
01244 NetworkAccount::setFolder(folder, addAccount);
01245 }
01246
01247
01248 void ImapAccountBase::removeJob( JobIterator& it )
01249 {
01250 if( (*it).progressItem ) {
01251 (*it).progressItem->setComplete();
01252 (*it).progressItem = 0;
01253 }
01254 mapJobData.remove( it );
01255 }
01256
01257
01258 void KMail::ImapAccountBase::removeJob( KIO::Job* job )
01259 {
01260 mapJobData.remove( job );
01261 }
01262
01263
01264 KPIM::ProgressItem* ImapAccountBase::listDirProgressItem()
01265 {
01266 if ( !mListDirProgressItem )
01267 {
01268 mListDirProgressItem = ProgressManager::createProgressItem(
01269 "ListDir" + name(),
01270 QStyleSheet::escape( name() ),
01271 i18n("retrieving folders"),
01272 true,
01273 useSSL() || useTLS() );
01274 connect ( mListDirProgressItem,
01275 SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
01276 this,
01277 SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
01278
01279
01280
01281 unsigned int count = folderCount();
01282 mListDirProgressItem->setTotalItems( count + (unsigned int)(count*0.05) );
01283 }
01284 return mListDirProgressItem;
01285 }
01286
01287
01288 unsigned int ImapAccountBase::folderCount() const
01289 {
01290 if ( !rootFolder() || !rootFolder()->folder() || !rootFolder()->folder()->child() )
01291 return 0;
01292 return kmkernel->imapFolderMgr()->folderCount( rootFolder()->folder()->child() );
01293 }
01294
01295
01296 QString ImapAccountBase::addPathToNamespace( const QString& prefix )
01297 {
01298 QString myPrefix = prefix;
01299 if ( !myPrefix.startsWith( "/" ) ) {
01300 myPrefix = "/" + myPrefix;
01301 }
01302 if ( !myPrefix.endsWith( "/" ) ) {
01303 myPrefix += "/";
01304 }
01305
01306 return myPrefix;
01307 }
01308
01309
01310 bool ImapAccountBase::isNamespaceFolder( QString& name )
01311 {
01312 QStringList ns = mNamespaces[OtherUsersNS];
01313 ns += mNamespaces[SharedNS];
01314 ns += mNamespaces[PersonalNS];
01315 QString nameWithDelimiter;
01316 for ( QStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
01317 {
01318 nameWithDelimiter = name + delimiterForNamespace( *it );
01319 if ( *it == name || *it == nameWithDelimiter )
01320 return true;
01321 }
01322 return false;
01323 }
01324
01325
01326 ImapAccountBase::nsDelimMap ImapAccountBase::namespacesWithDelimiter()
01327 {
01328 nsDelimMap map;
01329 nsMap::ConstIterator it;
01330 for ( uint i = 0; i < 3; ++i )
01331 {
01332 imapNamespace section = imapNamespace( i );
01333 QStringList namespaces = mNamespaces[section];
01334 namespaceDelim nsDelim;
01335 QStringList::Iterator lit;
01336 for ( lit = namespaces.begin(); lit != namespaces.end(); ++lit )
01337 {
01338 nsDelim[*lit] = delimiterForNamespace( *lit );
01339 }
01340 map[section] = nsDelim;
01341 }
01342 return map;
01343 }
01344
01345
01346 QString ImapAccountBase::createImapPath( const QString& parent,
01347 const QString& folderName )
01348 {
01349 kdDebug(5006) << "createImapPath parent="<<parent<<", folderName="<<folderName<<endl;
01350 QString newName = parent;
01351
01352 if ( newName.endsWith("/") ) {
01353 newName = newName.left( newName.length() - 1 );
01354 }
01355
01356 QString delim = delimiterForNamespace( newName );
01357
01358 if ( delim.isEmpty() ) {
01359 delim = "/";
01360 }
01361 if ( !newName.isEmpty() &&
01362 !newName.endsWith( delim ) && !folderName.startsWith( delim ) ) {
01363 newName = newName + delim;
01364 }
01365 newName = newName + folderName;
01366
01367 if ( !newName.endsWith("/") ) {
01368 newName = newName + "/";
01369 }
01370
01371 return newName;
01372 }
01373
01374
01375 QString ImapAccountBase::createImapPath( FolderStorage* parent,
01376 const QString& folderName )
01377 {
01378 QString path;
01379 if ( parent->folderType() == KMFolderTypeImap ) {
01380 path = static_cast<KMFolderImap*>( parent )->imapPath();
01381 } else if ( parent->folderType() == KMFolderTypeCachedImap ) {
01382 path = static_cast<KMFolderCachedImap*>( parent )->imapPath();
01383 } else {
01384
01385 return path;
01386 }
01387
01388 return createImapPath( path, folderName );
01389 }
01390
01391
01392 bool ImapAccountBase::locallySubscribedTo( const QString& imapPath )
01393 {
01394 return mLocalSubscriptionBlackList.find( imapPath ) == mLocalSubscriptionBlackList.end();
01395 }
01396
01397 void ImapAccountBase::changeLocalSubscription( const QString& imapPath, bool subscribe )
01398 {
01399 if ( subscribe ) {
01400
01401 mLocalSubscriptionBlackList.erase( imapPath );
01402 } else {
01403
01404 mLocalSubscriptionBlackList.insert( imapPath );
01405 }
01406 }
01407
01408
01409 QStringList ImapAccountBase::locallyBlacklistedFolders() const
01410 {
01411 QStringList list;
01412 std::set<QString>::const_iterator it = mLocalSubscriptionBlackList.begin();
01413 std::set<QString>::const_iterator end = mLocalSubscriptionBlackList.end();
01414 for ( ; it != end ; ++it )
01415 list.append( *it );
01416 return list;
01417 }
01418
01419 void ImapAccountBase::localBlacklistFromStringList( const QStringList &list )
01420 {
01421 for( QStringList::ConstIterator it = list.constBegin( ); it != list.constEnd( ); ++it )
01422 mLocalSubscriptionBlackList.insert( *it );
01423 }
01424
01425 }
01426
01427 #include "imapaccountbase.moc"