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