00001
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "imapaccountbase.h"
00029 using KMail::SieveConfig;
00030
00031 #include "kmacctmgr.h"
00032 #include "kmfolder.h"
00033 #include "broadcaststatus.h"
00034 using KPIM::BroadcastStatus;
00035 #include "kmmainwin.h"
00036 #include "kmfolderimap.h"
00037 #include "kmmainwidget.h"
00038 #include "kmmainwin.h"
00039 #include "kmmsgpart.h"
00040 #include "acljobs.h"
00041 #include "kmfoldercachedimap.h"
00042 #include "bodyvisitor.h"
00043 using KMail::BodyVisitor;
00044 #include "imapjob.h"
00045 using KMail::ImapJob;
00046 #include "protocols.h"
00047 #include "progressmanager.h"
00048 using KPIM::ProgressManager;
00049 #include "kmfoldermgr.h"
00050
00051 #include <kapplication.h>
00052 #include <kdebug.h>
00053 #include <kconfig.h>
00054 #include <klocale.h>
00055 #include <kmessagebox.h>
00056 using KIO::MetaData;
00057 #include <kio/passdlg.h>
00058 using KIO::PasswordDialog;
00059 #include <kio/scheduler.h>
00060 #include <kio/slave.h>
00061 #include <mimelib/bodypart.h>
00062 #include <mimelib/body.h>
00063 #include <mimelib/headers.h>
00064 #include <mimelib/message.h>
00065
00066
00067 #include <qregexp.h>
00068 #include <qstylesheet.h>
00069
00070 namespace KMail {
00071
00072 static const unsigned short int imapDefaultPort = 143;
00073
00074
00075
00076
00077
00078
00079
00080 ImapAccountBase::ImapAccountBase( KMAcctMgr * parent, const QString & name, uint id )
00081 : NetworkAccount( parent, name, id ),
00082 mPrefix( "/" ),
00083 mTotal( 0 ),
00084 mCountUnread( 0 ),
00085 mCountLastUnread( 0 ),
00086 mAutoExpunge( true ),
00087 mHiddenFolders( false ),
00088 mOnlySubscribedFolders( false ),
00089 mOnlyLocallySubscribedFolders( false ),
00090 mLoadOnDemand( false ),
00091 mListOnlyOpenFolders( false ),
00092 mProgressEnabled( false ),
00093 mErrorDialogIsActive( false ),
00094 mPasswordDialogIsActive( false ),
00095 mACLSupport( true ),
00096 mAnnotationSupport( true ),
00097 mQuotaSupport( true ),
00098 mSlaveConnected( false ),
00099 mSlaveConnectionError( false ),
00100 mListDirProgressItem( 0 )
00101 {
00102 mPort = imapDefaultPort;
00103 mBodyPartList.setAutoDelete(true);
00104 KIO::Scheduler::connect(SIGNAL(slaveError(KIO::Slave *, int, const QString &)),
00105 this, SLOT(slotSchedulerSlaveError(KIO::Slave *, int, const QString &)));
00106 KIO::Scheduler::connect(SIGNAL(slaveConnected(KIO::Slave *)),
00107 this, SLOT(slotSchedulerSlaveConnected(KIO::Slave *)));
00108 connect(&mNoopTimer, SIGNAL(timeout()), SLOT(slotNoopTimeout()));
00109 connect(&mIdleTimer, SIGNAL(timeout()), SLOT(slotIdleTimeout()));
00110 }
00111
00112 ImapAccountBase::~ImapAccountBase() {
00113 kdWarning( mSlave, 5006 )
00114 << "slave should have been destroyed by subclass!" << endl;
00115 }
00116
00117 void ImapAccountBase::init() {
00118 mPrefix = '/';
00119 mAutoExpunge = true;
00120 mHiddenFolders = false;
00121 mOnlySubscribedFolders = false;
00122 mOnlyLocallySubscribedFolders = false;
00123 mLoadOnDemand = false;
00124 mListOnlyOpenFolders = false;
00125 mProgressEnabled = false;
00126 }
00127
00128 void ImapAccountBase::pseudoAssign( const KMAccount * a ) {
00129 NetworkAccount::pseudoAssign( a );
00130
00131 const ImapAccountBase * i = dynamic_cast<const ImapAccountBase*>( a );
00132 if ( !i ) return;
00133
00134 setPrefix( i->prefix() );
00135 setAutoExpunge( i->autoExpunge() );
00136 setHiddenFolders( i->hiddenFolders() );
00137 setOnlySubscribedFolders( i->onlySubscribedFolders() );
00138 setOnlyLocallySubscribedFolders( i->onlyLocallySubscribedFolders() );
00139 setLoadOnDemand( i->loadOnDemand() );
00140 setListOnlyOpenFolders( i->listOnlyOpenFolders() );
00141 localBlacklistFromStringList( i->locallyBlacklistedFolders() );
00142 }
00143
00144 unsigned short int ImapAccountBase::defaultPort() const {
00145 return imapDefaultPort;
00146 }
00147
00148 QString ImapAccountBase::protocol() const {
00149 return useSSL() ? IMAP_SSL_PROTOCOL : IMAP_PROTOCOL;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158 void ImapAccountBase::setPrefix( const QString & prefix ) {
00159 mPrefix = prefix;
00160 mPrefix.remove( QRegExp( "[%*\"]" ) );
00161 if ( mPrefix.isEmpty() || mPrefix[0] != '/' )
00162 mPrefix.prepend( '/' );
00163 if ( mPrefix[ mPrefix.length() - 1 ] != '/' )
00164 mPrefix += '/';
00165 #if 1
00166 setPrefixHook();
00167 #else
00168 if ( mFolder ) mFolder->setImapPath( mPrefix );
00169 #endif
00170 }
00171
00172 void ImapAccountBase::setAutoExpunge( bool expunge ) {
00173 mAutoExpunge = expunge;
00174 }
00175
00176 void ImapAccountBase::setHiddenFolders( bool show ) {
00177 mHiddenFolders = show;
00178 }
00179
00180 void ImapAccountBase::setOnlySubscribedFolders( bool show ) {
00181 mOnlySubscribedFolders = show;
00182 }
00183
00184 void ImapAccountBase::setOnlyLocallySubscribedFolders( bool show ) {
00185 mOnlyLocallySubscribedFolders = show;
00186 }
00187
00188 void ImapAccountBase::setLoadOnDemand( bool load ) {
00189 mLoadOnDemand = load;
00190 }
00191
00192 void ImapAccountBase::setListOnlyOpenFolders( bool only ) {
00193 mListOnlyOpenFolders = only;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 void ImapAccountBase::readConfig( KConfig & config ) {
00203 NetworkAccount::readConfig( config );
00204
00205 setPrefix( config.readEntry( "prefix", "/" ) );
00206 setAutoExpunge( config.readBoolEntry( "auto-expunge", false ) );
00207 setHiddenFolders( config.readBoolEntry( "hidden-folders", false ) );
00208 setOnlySubscribedFolders( config.readBoolEntry( "subscribed-folders", false ) );
00209 setOnlyLocallySubscribedFolders( config.readBoolEntry( "locally-subscribed-folders", false ) );
00210 setLoadOnDemand( config.readBoolEntry( "loadondemand", false ) );
00211 setListOnlyOpenFolders( config.readBoolEntry( "listOnlyOpenFolders", false ) );
00212 localBlacklistFromStringList( config.readListEntry( "locallyUnsubscribedFolders" ) );
00213 }
00214
00215 void ImapAccountBase::writeConfig( KConfig & config ) {
00216 NetworkAccount::writeConfig( config );
00217
00218 config.writeEntry( "prefix", prefix() );
00219 config.writeEntry( "auto-expunge", autoExpunge() );
00220 config.writeEntry( "hidden-folders", hiddenFolders() );
00221 config.writeEntry( "subscribed-folders", onlySubscribedFolders() );
00222 config.writeEntry( "locally-subscribed-folders", onlyLocallySubscribedFolders() );
00223 config.writeEntry( "loadondemand", loadOnDemand() );
00224 config.writeEntry( "listOnlyOpenFolders", listOnlyOpenFolders() );
00225 config.writeEntry( "locallyUnsubscribedFolders", locallyBlacklistedFolders() );
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 MetaData ImapAccountBase::slaveConfig() const {
00235 MetaData m = NetworkAccount::slaveConfig();
00236
00237 m.insert( "auth", auth() );
00238 if ( autoExpunge() )
00239 m.insert( "expunge", "auto" );
00240
00241 return m;
00242 }
00243
00244 ImapAccountBase::ConnectionState ImapAccountBase::makeConnection() {
00245
00246 if ( mSlave && mSlaveConnected ) return Connected;
00247 if ( mPasswordDialogIsActive ) return Connecting;
00248
00249 if( mAskAgain || passwd().isEmpty() || login().isEmpty() ) {
00250 Q_ASSERT( !mSlave );
00251 QString log = login();
00252 QString pass = passwd();
00253
00254
00255
00256
00257 bool store = true;
00258 KConfigGroup passwords( KGlobal::config(), "Passwords" );
00259 passwords.writeEntry( "Keep", storePasswd() );
00260 QString msg = i18n("You need to supply a username and a password to "
00261 "access this mailbox.");
00262 mPasswordDialogIsActive = true;
00263 if ( PasswordDialog::getNameAndPassword( log, pass, &store, msg, false,
00264 QString::null, name(),
00265 i18n("Account:") )
00266 != QDialog::Accepted ) {
00267 mPasswordDialogIsActive = false;
00268 mAskAgain = false;
00269 emit connectionResult( KIO::ERR_USER_CANCELED, QString::null );
00270 return Error;
00271 }
00272 mPasswordDialogIsActive = false;
00273
00274
00275 setPasswd( pass, store );
00276 setLogin( log );
00277 mAskAgain = false;
00278 }
00279
00280 if ( mSlave && !mSlaveConnected ) return Connecting;
00281
00282 mSlaveConnected = false;
00283 mSlave = KIO::Scheduler::getConnectedSlave( getUrl(), slaveConfig() );
00284 if ( !mSlave ) {
00285 KMessageBox::error(0, i18n("Could not start process for %1.")
00286 .arg( getUrl().protocol() ) );
00287 return Error;
00288 }
00289 if ( mSlave->isConnected() ) {
00290 mSlaveConnected = true;
00291 return Connected;
00292 }
00293
00294 return Connecting;
00295 }
00296
00297 bool ImapAccountBase::handleJobError( KIO::Job *job, const QString& context, bool abortSync )
00298 {
00299 return handleError( job->error(), job->errorText(), job, context, abortSync );
00300 }
00301
00302
00303 void ImapAccountBase::postProcessNewMail() {
00304 setCheckingMail(false);
00305 int newMails = 0;
00306 if ( mCountUnread > 0 && mCountUnread > mCountLastUnread ) {
00307 newMails = mCountUnread - mCountLastUnread;
00308 mCountLastUnread = mCountUnread;
00309 mCountUnread = 0;
00310 checkDone( true, CheckOK );
00311 } else {
00312 mCountUnread = 0;
00313 checkDone( false, CheckOK );
00314 }
00315 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00316 name(), newMails);
00317 }
00318
00319
00320 void ImapAccountBase::changeSubscription( bool subscribe, const QString& imapPath )
00321 {
00322
00323 KURL url = getUrl();
00324 url.setPath(imapPath);
00325
00326 QByteArray packedArgs;
00327 QDataStream stream( packedArgs, IO_WriteOnly);
00328
00329 if (subscribe)
00330 stream << (int) 'u' << url;
00331 else
00332 stream << (int) 'U' << url;
00333
00334
00335 if (makeConnection() != Connected)
00336 return;
00337 KIO::SimpleJob *job = KIO::special(url, packedArgs, FALSE);
00338 KIO::Scheduler::assignJobToSlave(mSlave, job);
00339 jobData jd( url.url(), NULL );
00340
00341 if (subscribe) jd.onlySubscribed = true;
00342 else jd.onlySubscribed = false;
00343 insertJob(job, jd);
00344
00345 connect(job, SIGNAL(result(KIO::Job *)),
00346 SLOT(slotSubscriptionResult(KIO::Job *)));
00347 }
00348
00349
00350 void ImapAccountBase::slotSubscriptionResult( KIO::Job * job )
00351 {
00352
00353 JobIterator it = findJob( job );
00354 if ( it == jobsEnd() ) return;
00355 bool onlySubscribed = (*it).onlySubscribed;
00356 QString path = static_cast<KIO::SimpleJob*>(job)->url().path();
00357 if (job->error())
00358 {
00359 handleJobError( job, i18n( "Error while trying to subscribe to %1:" ).arg( path ) + '\n' );
00360
00361 }
00362 else
00363 {
00364 emit subscriptionChanged( path, onlySubscribed );
00365 if (mSlave) removeJob(job);
00366 }
00367 }
00368
00369
00370
00371 void ImapAccountBase::getUserRights( KMFolder* parent, const QString& imapPath )
00372 {
00373
00374
00375
00376
00377 if ( imapPath == "/INBOX/" ) {
00378 if ( parent->folderType() == KMFolderTypeImap )
00379 static_cast<KMFolderImap*>( parent->storage() )->setUserRights( ACLJobs::All );
00380 else if ( parent->folderType() == KMFolderTypeCachedImap )
00381 static_cast<KMFolderCachedImap*>( parent->storage() )->setUserRights( ACLJobs::All );
00382 emit receivedUserRights( parent );
00383 return;
00384 }
00385
00386 KURL url = getUrl();
00387 url.setPath(imapPath);
00388
00389 ACLJobs::GetUserRightsJob* job = ACLJobs::getUserRights( mSlave, url );
00390
00391 jobData jd( url.url(), parent );
00392 jd.cancellable = true;
00393 insertJob(job, jd);
00394
00395 connect(job, SIGNAL(result(KIO::Job *)),
00396 SLOT(slotGetUserRightsResult(KIO::Job *)));
00397 }
00398
00399 void ImapAccountBase::slotGetUserRightsResult( KIO::Job* _job )
00400 {
00401 ACLJobs::GetUserRightsJob* job = static_cast<ACLJobs::GetUserRightsJob *>( _job );
00402 JobIterator it = findJob( job );
00403 if ( it == jobsEnd() ) return;
00404
00405 KMFolder* folder = (*it).parent;
00406 if ( job->error() ) {
00407 if ( job->error() == KIO::ERR_UNSUPPORTED_ACTION )
00408 mACLSupport = false;
00409 else
00410 kdWarning(5006) << "slotGetUserRightsResult: " << job->errorString() << endl;
00411 } else {
00412 #ifndef NDEBUG
00413
00414 #endif
00415
00416 if ( folder->folderType() == KMFolderTypeImap )
00417 static_cast<KMFolderImap*>( folder->storage() )->setUserRights( job->permissions() );
00418 else if ( folder->folderType() == KMFolderTypeCachedImap )
00419 static_cast<KMFolderCachedImap*>( folder->storage() )->setUserRights( job->permissions() );
00420 }
00421 if (mSlave) removeJob(job);
00422 emit receivedUserRights( folder );
00423 }
00424
00425
00426
00427 void ImapAccountBase::getACL( KMFolder* parent, const QString& imapPath )
00428 {
00429 KURL url = getUrl();
00430 url.setPath(imapPath);
00431
00432 ACLJobs::GetACLJob* job = ACLJobs::getACL( mSlave, url );
00433 jobData jd( url.url(), parent );
00434 jd.cancellable = true;
00435 insertJob(job, jd);
00436
00437 connect(job, SIGNAL(result(KIO::Job *)),
00438 SLOT(slotGetACLResult(KIO::Job *)));
00439 }
00440
00441 void ImapAccountBase::slotGetACLResult( KIO::Job* _job )
00442 {
00443 ACLJobs::GetACLJob* job = static_cast<ACLJobs::GetACLJob *>( _job );
00444 JobIterator it = findJob( job );
00445 if ( it == jobsEnd() ) return;
00446
00447 KMFolder* folder = (*it).parent;
00448 emit receivedACL( folder, job, job->entries() );
00449 if (mSlave) removeJob(job);
00450 }
00451
00452
00453
00454 void ImapAccountBase::getStorageQuotaInfo( KMFolder* parent, const QString& imapPath )
00455 {
00456 if ( !mSlave ) return;
00457 KURL url = getUrl();
00458 url.setPath(imapPath);
00459
00460 QuotaJobs::GetStorageQuotaJob* job = QuotaJobs::getStorageQuota( mSlave, url );
00461 jobData jd( url.url(), parent );
00462 jd.cancellable = true;
00463 insertJob(job, jd);
00464
00465 connect(job, SIGNAL(result(KIO::Job *)),
00466 SLOT(slotGetStorageQuotaInfoResult(KIO::Job *)));
00467 }
00468
00469 void ImapAccountBase::slotGetStorageQuotaInfoResult( KIO::Job* _job )
00470 {
00471 QuotaJobs::GetStorageQuotaJob* job = static_cast<QuotaJobs::GetStorageQuotaJob *>( _job );
00472 JobIterator it = findJob( job );
00473 if ( it == jobsEnd() ) return;
00474 if ( job->error() && job->error() == KIO::ERR_UNSUPPORTED_ACTION )
00475 setHasNoQuotaSupport();
00476
00477 KMFolder* folder = (*it).parent;
00478 emit receivedStorageQuotaInfo( folder, job, job->storageQuotaInfo() );
00479 if (mSlave) removeJob(job);
00480 }
00481
00482 void ImapAccountBase::slotNoopTimeout()
00483 {
00484 if ( mSlave ) {
00485 QByteArray packedArgs;
00486 QDataStream stream( packedArgs, IO_WriteOnly );
00487
00488 stream << ( int ) 'N';
00489
00490 KIO::SimpleJob *job = KIO::special( getUrl(), packedArgs, false );
00491 KIO::Scheduler::assignJobToSlave(mSlave, job);
00492 connect( job, SIGNAL(result( KIO::Job * ) ),
00493 this, SLOT( slotSimpleResult( KIO::Job * ) ) );
00494 } else {
00495
00496
00497 mNoopTimer.stop();
00498 }
00499 }
00500
00501 void ImapAccountBase::slotIdleTimeout()
00502 {
00503 if ( mSlave ) {
00504 KIO::Scheduler::disconnectSlave(mSlave);
00505 mSlave = 0;
00506 mSlaveConnected = false;
00507
00508
00509 mIdleTimer.stop();
00510 }
00511 }
00512
00513 void ImapAccountBase::slotAbortRequested( KPIM::ProgressItem* item )
00514 {
00515 if ( item )
00516 item->setComplete();
00517 killAllJobs();
00518 }
00519
00520
00521
00522 void ImapAccountBase::slotSchedulerSlaveError(KIO::Slave *aSlave, int errorCode,
00523 const QString &errorMsg)
00524 {
00525 if (aSlave != mSlave) return;
00526 handleError( errorCode, errorMsg, 0, QString::null, true );
00527 if ( mAskAgain )
00528 makeConnection();
00529 else {
00530 if ( !mSlaveConnected )
00531 mSlaveConnectionError = true;
00532 emit connectionResult( errorCode, errorMsg );
00533 }
00534 }
00535
00536
00537 void ImapAccountBase::slotSchedulerSlaveConnected(KIO::Slave *aSlave)
00538 {
00539 if (aSlave != mSlave) return;
00540 mSlaveConnected = true;
00541 emit connectionResult( 0, QString::null );
00542 }
00543
00544
00545 void ImapAccountBase::slotSimpleResult(KIO::Job * job)
00546 {
00547 JobIterator it = findJob( job );
00548 bool quiet = false;
00549 if (it != mapJobData.end()) {
00550 quiet = (*it).quiet;
00551 if ( !(job->error() && !quiet) )
00552 removeJob(it);
00553 }
00554 if (job->error()) {
00555 if (!quiet)
00556 handleJobError(job, QString::null );
00557 else {
00558 if ( job->error() == KIO::ERR_CONNECTION_BROKEN && slave() ) {
00559
00560
00561 KIO::Scheduler::disconnectSlave( slave() );
00562 mSlave = 0;
00563 }
00564 if (job->error() == KIO::ERR_SLAVE_DIED)
00565 slaveDied();
00566 }
00567 }
00568 }
00569
00570
00571 bool ImapAccountBase::handlePutError( KIO::Job* job, jobData& jd, KMFolder* folder )
00572 {
00573 Q_ASSERT( !jd.msgList.isEmpty() );
00574 KMMessage* msg = jd.msgList.first();
00575
00576
00577 const QString subject = msg->subject().isEmpty() ? i18n( "<unknown>" ) : QString("\"%1\"").arg( msg->subject() );
00578 const QString from = msg->from().isEmpty() ? i18n( "<unknown>" ) : msg->from();
00579 QString myError = "<p><b>" + i18n("Error while uploading message")
00580 + "</b></p><p>"
00581 + 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 ) )
00582 + "</p><p>"
00583 + i18n("The destination folder was %1, which has the URL %2.").arg( QStyleSheet::escape( folder->label() ), QStyleSheet::escape( jd.htmlURL() ) )
00584 + "</p><p>"
00585 + i18n("The error message from the server communication is here:") + "</p>";
00586 return handleJobError( job, myError );
00587 }
00588
00589
00590 bool ImapAccountBase::handleError( int errorCode, const QString &errorMsg, KIO::Job* job, const QString& context, bool abortSync )
00591 {
00592
00593 QStringList errors;
00594 if ( job && job->error() != KIO::ERR_SLAVE_DEFINED )
00595 errors = job->detailedErrorStrings();
00596
00597 bool jobsKilled = true;
00598 switch( errorCode ) {
00599 case KIO::ERR_SLAVE_DIED: slaveDied(); killAllJobs( true ); break;
00600 case KIO::ERR_COULD_NOT_LOGIN:
00601 mAskAgain = true;
00602
00603 case KIO::ERR_CONNECTION_BROKEN:
00604 case KIO::ERR_COULD_NOT_CONNECT:
00605
00606 killAllJobs( true );
00607 break;
00608 case KIO::ERR_USER_CANCELED:
00609 killAllJobs( false );
00610 break;
00611 default:
00612 if ( abortSync )
00613 killAllJobs( false );
00614 else
00615 jobsKilled = false;
00616 break;
00617 }
00618
00619
00620
00621 if ( !mErrorDialogIsActive
00622 && errorCode != KIO::ERR_USER_CANCELED
00623 && errorCode != KIO::ERR_CONNECTION_BROKEN ) {
00624 mErrorDialogIsActive = true;
00625 QString msg = context + '\n' + KIO::buildErrorString( errorCode, errorMsg );
00626 QString caption = i18n("Error");
00627
00628 if ( jobsKilled || errorCode == KIO::ERR_COULD_NOT_LOGIN ) {
00629 if ( !errors.isEmpty() )
00630 KMessageBox::detailedError( kapp->activeWindow(), msg, errors.join("\n").prepend("<qt>"), caption );
00631 else
00632 KMessageBox::error( kapp->activeWindow(), msg, caption );
00633 }
00634 else
00635 {
00636 if ( errors.count() >= 3 ) {
00637 msg = QString( "<qt>") + context + errors[1] + '\n' + errors[2];
00638 caption = errors[0];
00639 }
00640 int ret = KMessageBox::warningContinueCancel( kapp->activeWindow(), msg, caption );
00641 if ( ret == KMessageBox::Cancel ) {
00642 jobsKilled = true;
00643 killAllJobs( false );
00644 }
00645 }
00646 mErrorDialogIsActive = false;
00647 } else if ( errorCode != KIO::ERR_USER_CANCELED )
00648 kdDebug(5006) << "suppressing error:" << errorMsg << endl;
00649
00650 if ( job && !jobsKilled )
00651 removeJob( job );
00652 return !jobsKilled;
00653 }
00654
00655
00656 void ImapAccountBase::cancelMailCheck()
00657 {
00658 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00659 while ( it != mapJobData.end() ) {
00660 kdDebug(5006) << "cancelMailCheck: job is cancellable: " << (*it).cancellable << endl;
00661 if ( (*it).cancellable ) {
00662 it.key()->kill();
00663 QMap<KIO::Job*, jobData>::Iterator rmit = it;
00664 ++it;
00665 mapJobData.remove( rmit );
00666
00667 mSlave = 0;
00668 } else
00669 ++it;
00670 }
00671
00672 for( QPtrListIterator<FolderJob> it( mJobList ); it.current(); ++it ) {
00673 if ( it.current()->isCancellable() ) {
00674 FolderJob* job = it.current();
00675 job->setPassiveDestructor( true );
00676 mJobList.remove( job );
00677 delete job;
00678 } else
00679 ++it;
00680 }
00681 }
00682
00683
00684
00685 QString ImapAccountBase::jobData::htmlURL() const
00686 {
00687 KURL u( url );
00688 return u.htmlURL();
00689 }
00690
00691
00692 void ImapAccountBase::processNewMailSingleFolder(KMFolder* folder)
00693 {
00694 mFoldersQueuedForChecking.append(folder);
00695 if ( checkingMail() )
00696 {
00697 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00698 this, SLOT( slotCheckQueuedFolders() ) );
00699 connect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00700 this, SLOT( slotCheckQueuedFolders() ) );
00701 } else {
00702 slotCheckQueuedFolders();
00703 }
00704 }
00705
00706
00707 void ImapAccountBase::slotCheckQueuedFolders()
00708 {
00709 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00710 this, SLOT( slotCheckQueuedFolders() ) );
00711
00712 QValueList<QGuardedPtr<KMFolder> > mSaveList = mMailCheckFolders;
00713 mMailCheckFolders = mFoldersQueuedForChecking;
00714 kmkernel->acctMgr()->singleCheckMail(this, true);
00715 mMailCheckFolders = mSaveList;
00716 mFoldersQueuedForChecking.clear();
00717 }
00718
00719
00720 bool ImapAccountBase::checkingMail( KMFolder *folder )
00721 {
00722 if (checkingMail() && mFoldersQueuedForChecking.contains(folder))
00723 return true;
00724 return false;
00725 }
00726
00727
00728 void ImapAccountBase::handleBodyStructure( QDataStream & stream, KMMessage * msg,
00729 const AttachmentStrategy *as )
00730 {
00731 mBodyPartList.clear();
00732 mCurrentMsg = msg;
00733
00734 constructParts( stream, 1, 0, 0, msg->asDwMessage() );
00735 if ( mBodyPartList.count() == 1 )
00736 msg->deleteBodyParts();
00737
00738 if ( !as )
00739 {
00740 kdWarning(5006) << "ImapAccountBase::handleBodyStructure - found no attachment strategy!" << endl;
00741 return;
00742 }
00743
00744
00745 BodyVisitor *visitor = BodyVisitorFactory::getVisitor( as );
00746 visitor->visit( mBodyPartList );
00747 QPtrList<KMMessagePart> parts = visitor->partsToLoad();
00748 QPtrListIterator<KMMessagePart> it( parts );
00749 KMMessagePart *part;
00750 while ( (part = it.current()) != 0 )
00751 {
00752 ++it;
00753 kdDebug(5006) << "ImapAccountBase::handleBodyStructure - load " << part->partSpecifier()
00754 << " (" << part->originalContentTypeStr() << ")" << endl;
00755 if ( part->loadHeaders() )
00756 {
00757 kdDebug(5006) << "load HEADER" << endl;
00758 FolderJob *job = msg->parent()->createJob(
00759 msg, FolderJob::tGetMessage, 0, part->partSpecifier()+".MIME" );
00760 job->start();
00761 }
00762 if ( part->loadPart() )
00763 {
00764 kdDebug(5006) << "load Part" << endl;
00765 FolderJob *job = msg->parent()->createJob(
00766 msg, FolderJob::tGetMessage, 0, part->partSpecifier() );
00767 job->start();
00768 }
00769 }
00770 delete visitor;
00771 }
00772
00773
00774 void ImapAccountBase::constructParts( QDataStream & stream, int count, KMMessagePart* parentKMPart,
00775 DwBodyPart * parent, const DwMessage * dwmsg )
00776 {
00777 int children;
00778 for (int i = 0; i < count; i++)
00779 {
00780 stream >> children;
00781 KMMessagePart* part = new KMMessagePart( stream );
00782 part->setParent( parentKMPart );
00783 mBodyPartList.append( part );
00784 kdDebug(5006) << "ImapAccountBase::constructParts - created id " << part->partSpecifier()
00785 << " of type " << part->originalContentTypeStr() << endl;
00786 DwBodyPart *dwpart = mCurrentMsg->createDWBodyPart( part );
00787 dwpart->Parse();
00788
00789
00790
00791
00792 if ( parent )
00793 {
00794
00795 parent->Body().AddBodyPart( dwpart );
00796 } else if ( part->partSpecifier() != "0" &&
00797 !part->partSpecifier().endsWith(".HEADER") )
00798 {
00799
00800 dwmsg->Body().AddBodyPart( dwpart );
00801 } else
00802 dwpart = 0;
00803
00804 if ( !parentKMPart )
00805 parentKMPart = part;
00806
00807 if (children > 0)
00808 {
00809 DwBodyPart* newparent = dwpart;
00810 const DwMessage* newmsg = dwmsg;
00811 if ( part->originalContentTypeStr() == "MESSAGE/RFC822" &&
00812 dwpart->Body().Message() )
00813 {
00814
00815 newparent = 0;
00816 newmsg = dwpart->Body().Message();
00817 }
00818 KMMessagePart* newParentKMPart = part;
00819 if ( part->partSpecifier().endsWith(".HEADER") )
00820 newParentKMPart = parentKMPart;
00821
00822 constructParts( stream, children, newParentKMPart, newparent, newmsg );
00823 }
00824 }
00825 }
00826
00827
00828 void ImapAccountBase::setImapStatus( KMFolder* folder, const QString& path, const QCString& flags )
00829 {
00830
00831 kdDebug(5006) << "setImapStatus path=" << path << " to: " << flags << endl;
00832 KURL url = getUrl();
00833 url.setPath(path);
00834
00835 QByteArray packedArgs;
00836 QDataStream stream( packedArgs, IO_WriteOnly);
00837
00838 stream << (int) 'S' << url << flags;
00839
00840 if ( makeConnection() != ImapAccountBase::Connected )
00841 return;
00842
00843 KIO::SimpleJob *job = KIO::special(url, packedArgs, FALSE);
00844 KIO::Scheduler::assignJobToSlave(slave(), job);
00845 ImapAccountBase::jobData jd( url.url(), folder );
00846 jd.path = path;
00847 insertJob(job, jd);
00848 connect(job, SIGNAL(result(KIO::Job *)),
00849 SLOT(slotSetStatusResult(KIO::Job *)));
00850 }
00851
00852 void ImapAccountBase::slotSetStatusResult(KIO::Job * job)
00853 {
00854 ImapAccountBase::JobIterator it = findJob(job);
00855 if ( it == jobsEnd() ) return;
00856 int errorCode = job->error();
00857 KMFolder * const parent = (*it).parent;
00858 const QString path = (*it).path;
00859 if (errorCode && errorCode != KIO::ERR_CANNOT_OPEN_FOR_WRITING)
00860 {
00861 bool cont = handleJobError( job, i18n( "Error while uploading status of messages to server: " ) + '\n' );
00862 emit imapStatusChanged( parent, path, cont );
00863 }
00864 else
00865 {
00866 emit imapStatusChanged( parent, path, true );
00867 removeJob(it);
00868 }
00869 }
00870
00871
00872 void ImapAccountBase::setFolder(KMFolder* folder, bool addAccount)
00873 {
00874 if (folder)
00875 {
00876 folder->setSystemLabel(name());
00877 folder->setId(id());
00878 }
00879 NetworkAccount::setFolder(folder, addAccount);
00880 }
00881
00882
00883 void ImapAccountBase::removeJob( JobIterator& it )
00884 {
00885 if( (*it).progressItem ) {
00886 (*it).progressItem->setComplete();
00887 (*it).progressItem = 0;
00888 }
00889 mapJobData.remove( it );
00890 }
00891
00892
00893 void ImapAccountBase::removeJob( KIO::Job* job )
00894 {
00895 mapJobData.remove( job );
00896 }
00897
00898
00899 KPIM::ProgressItem* ImapAccountBase::listDirProgressItem()
00900 {
00901 if ( !mListDirProgressItem )
00902 {
00903 mListDirProgressItem = ProgressManager::createProgressItem(
00904 "ListDir" + name(),
00905 name(),
00906 i18n("retrieving folders"),
00907 true,
00908 useSSL() || useTLS() );
00909 connect ( mListDirProgressItem,
00910 SIGNAL( progressItemCanceled( ProgressItem* ) ),
00911 this,
00912 SLOT( slotAbortRequested( ProgressItem* ) ) );
00913
00914
00915
00916 unsigned int count = folderCount();
00917 mListDirProgressItem->setTotalItems( count + (unsigned int)(count*0.05) );
00918 }
00919 return mListDirProgressItem;
00920 }
00921
00922 unsigned int ImapAccountBase::folderCount() const
00923 {
00924 if ( !rootFolder() || !rootFolder()->folder() || !rootFolder()->folder()->child() )
00925 return 0;
00926 return kmkernel->imapFolderMgr()->folderCount( rootFolder()->folder()->child() );
00927 }
00928
00929
00930 bool ImapAccountBase::locallySubscribedTo( const QString& imapPath )
00931 {
00932 return mLocalSubscriptionBlackList.find( imapPath ) == mLocalSubscriptionBlackList.end();
00933 }
00934
00935 void ImapAccountBase::changeLocalSubscription( const QString& imapPath, bool subscribe )
00936 {
00937 if ( subscribe ) {
00938
00939 mLocalSubscriptionBlackList.erase( imapPath );
00940 } else {
00941
00942 mLocalSubscriptionBlackList.insert( imapPath );
00943 }
00944 }
00945
00946
00947 QStringList ImapAccountBase::locallyBlacklistedFolders() const
00948 {
00949 QStringList list;
00950 std::set<QString>::const_iterator it = mLocalSubscriptionBlackList.begin();
00951 std::set<QString>::const_iterator end = mLocalSubscriptionBlackList.end();
00952 for ( ; it != end ; ++it )
00953 list.append( *it );
00954 return list;
00955 }
00956
00957 void ImapAccountBase::localBlacklistFromStringList( const QStringList &list )
00958 {
00959 for( QStringList::ConstIterator it = list.constBegin( ); it != list.constEnd( ); ++it )
00960 mLocalSubscriptionBlackList.insert( *it );
00961 }
00962
00963 }
00964
00965 #include "imapaccountbase.moc"