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