00001
00002
00003
00004
00005 #ifdef HAVE_CONFIG_H
00006 #include <config.h>
00007 #endif
00008
00009 #include "kmacctexppop.h"
00010
00011 #include "kmbroadcaststatus.h"
00012 #include "kmfoldermgr.h"
00013 #include "kmfiltermgr.h"
00014 #include "kmpopfiltercnfrmdlg.h"
00015 #include "kmkernel.h"
00016
00017 #include <kdebug.h>
00018 #include <kstandarddirs.h>
00019 #include <klocale.h>
00020 #include <kmessagebox.h>
00021 #include <kmainwindow.h>
00022 #include <kio/scheduler.h>
00023 #include <kio/passdlg.h>
00024 #include <kconfig.h>
00025 using KIO::MetaData;
00026
00027 static const unsigned short int pop3DefaultPort = 110;
00028
00029
00030 KMAcctExpPop::KMAcctExpPop(KMAcctMgr* aOwner, const QString& aAccountName)
00031 : NetworkAccount(aOwner, aAccountName),
00032 headerIt(headersOnServer)
00033 {
00034 init();
00035 job = 0;
00036 mSlave = 0;
00037 mPort = defaultPort();
00038 stage = Idle;
00039 indexOfCurrentMsg = -1;
00040 curMsgStrm = 0;
00041 processingDelay = 2*100;
00042 mProcessing = false;
00043 dataCounter = 0;
00044
00045 headersOnServer.setAutoDelete(true);
00046 connect(&processMsgsTimer,SIGNAL(timeout()),SLOT(slotProcessPendingMsgs()));
00047 ss = new QTimer();
00048 connect( ss, SIGNAL( timeout() ), this, SLOT( slotGetNextMsg() ));
00049 KIO::Scheduler::connect(
00050 SIGNAL(slaveError(KIO::Slave *, int, const QString &)),
00051 this, SLOT(slotSlaveError(KIO::Slave *, int, const QString &)));
00052
00053 headerDeleteUids.clear();
00054 headerDownUids.clear();
00055 headerLaterUids.clear();
00056 }
00057
00058
00059
00060 KMAcctExpPop::~KMAcctExpPop()
00061 {
00062 if (job) {
00063 job->kill();
00064 idsOfMsgsPendingDownload.clear();
00065 lensOfMsgsPendingDownload.clear();
00066 processRemainingQueuedMessagesAndSaveUidList();
00067 }
00068 delete ss;
00069 }
00070
00071
00072
00073 QString KMAcctExpPop::type(void) const
00074 {
00075 return "pop";
00076 }
00077
00078 QString KMAcctExpPop::protocol() const {
00079 return useSSL() ? "pop3s" : "pop3";
00080 }
00081
00082 unsigned short int KMAcctExpPop::defaultPort() const {
00083 return pop3DefaultPort;
00084 }
00085
00086
00087 void KMAcctExpPop::init(void)
00088 {
00089 NetworkAccount::init();
00090
00091 mUsePipelining = FALSE;
00092 mLeaveOnServer = FALSE;
00093 mFilterOnServer = FALSE;
00094
00095 mFilterOnServerCheckSize = 50000;
00096 }
00097
00098
00099 void KMAcctExpPop::pseudoAssign( const KMAccount * a ) {
00100 slotAbortRequested();
00101 NetworkAccount::pseudoAssign( a );
00102
00103 const KMAcctExpPop * p = dynamic_cast<const KMAcctExpPop*>( a );
00104 if ( !p ) return;
00105
00106 setUsePipelining( p->usePipelining() );
00107 setLeaveOnServer( p->leaveOnServer() );
00108 setFilterOnServer( p->filterOnServer() );
00109 setFilterOnServerCheckSize( p->filterOnServerCheckSize() );
00110 }
00111
00112
00113 void KMAcctExpPop::processNewMail(bool _interactive)
00114 {
00115 if (stage == Idle) {
00116
00117 if(mAskAgain || mPasswd.isEmpty() || mLogin.isEmpty()) {
00118 QString passwd = decryptStr(mPasswd);
00119 bool b = FALSE;
00120 if (KIO::PasswordDialog::getNameAndPassword(mLogin, passwd, &b,
00121 i18n("You need to supply a username and a password to access this "
00122 "mailbox."), FALSE, QString::null, mName, i18n("Account:"))
00123 != QDialog::Accepted)
00124 {
00125 checkDone(false, 0);
00126 return;
00127 } else {
00128 mPasswd = encryptStr(passwd);
00129 mAskAgain = FALSE;
00130 }
00131 }
00132
00133 QString seenUidList = locateLocal( "data", "kmail/" + mLogin + ":" + "@" +
mHost + ":" + QString("%1").arg(mPort) );
00134 KConfig config( seenUidList );
00135 uidsOfSeenMsgs = config.readListEntry( "seenUidList" );
00136 headerLaterUids = config.readListEntry( "downloadLater" );
00137 uidsOfNextSeenMsgs.clear();
00138
00139 interactive = _interactive;
00140 mUidlFinished = FALSE;
00141 startJob();
00142 }
00143 else {
00144 checkDone(false, -1);
00145 return;
00146 }
00147 }
00148
00149
00150
00151 void KMAcctExpPop::readConfig(KConfig& config)
00152 {
00153 NetworkAccount::readConfig(config);
00154
00155 mUsePipelining = config.readNumEntry("pipelining", FALSE);
00156 mLeaveOnServer = config.readNumEntry("leave-on-server", FALSE);
00157 mFilterOnServer = config.readNumEntry("filter-on-server", FALSE);
00158 mFilterOnServerCheckSize = config.readUnsignedNumEntry("filter-os-check-size", 50000);
00159 }
00160
00161
00162
00163 void KMAcctExpPop::writeConfig(KConfig& config)
00164 {
00165 NetworkAccount::writeConfig(config);
00166
00167 config.writeEntry("pipelining", mUsePipelining);
00168 config.writeEntry("leave-on-server", mLeaveOnServer);
00169 config.writeEntry("filter-on-server", mFilterOnServer);
00170 config.writeEntry("filter-os-check-size", mFilterOnServerCheckSize);
00171 }
00172
00173
00174
00175 void KMAcctExpPop::setUsePipelining(bool b)
00176 {
00177 mUsePipelining = b;
00178 }
00179
00180
00181 void KMAcctExpPop::setLeaveOnServer(bool b)
00182 {
00183 mLeaveOnServer = b;
00184 }
00185
00186
00187
00188 void KMAcctExpPop::setFilterOnServer(bool b)
00189 {
00190 mFilterOnServer = b;
00191 }
00192
00193
00194 void KMAcctExpPop::setFilterOnServerCheckSize(unsigned int aSize)
00195 {
00196 mFilterOnServerCheckSize = aSize;
00197 }
00198
00199
00200 void KMAcctExpPop::connectJob() {
00201 KIO::Scheduler::assignJobToSlave(mSlave, job);
00202 if (stage != Dele)
00203 connect(job, SIGNAL( data( KIO::Job*, const QByteArray &)),
00204 SLOT( slotData( KIO::Job*, const QByteArray &)));
00205 connect(job, SIGNAL( result( KIO::Job * ) ),
00206 SLOT( slotResult( KIO::Job * ) ) );
00207 connect(job, SIGNAL(infoMessage( KIO::Job*, const QString & )),
00208 SLOT( slotMsgRetrieved(KIO::Job*, const QString &)));
00209 }
00210
00211
00212
00213 void KMAcctExpPop::slotCancel()
00214 {
00215 idsOfMsgsPendingDownload.clear();
00216 lensOfMsgsPendingDownload.clear();
00217 processRemainingQueuedMessagesAndSaveUidList();
00218 slotJobFinished();
00219 }
00220
00221
00222
00223 void KMAcctExpPop::slotProcessPendingMsgs()
00224 {
00225 if (mProcessing)
00226 return;
00227 mProcessing = true;
00228
00229 bool addedOk;
00230 QValueList<KMMessage*>::Iterator cur = msgsAwaitingProcessing.begin();
00231 QStringList::Iterator curId = msgIdsAwaitingProcessing.begin();
00232 QStringList::Iterator curUid = msgUidsAwaitingProcessing.begin();
00233
00234 while (cur != msgsAwaitingProcessing.end()) {
00235
00236
00237
00238
00239
00240 addedOk = processNewMsg(*cur);
00241
00242 if (!addedOk) {
00243 idsOfMsgsPendingDownload.clear();
00244 lensOfMsgsPendingDownload.clear();
00245 msgIdsAwaitingProcessing.clear();
00246 msgUidsAwaitingProcessing.clear();
00247 break;
00248 }
00249 else {
00250 idsOfMsgsToDelete.append( *curId );
00251 uidsOfNextSeenMsgs.append( *curUid );
00252 }
00253 ++cur;
00254 ++curId;
00255 ++curUid;
00256 }
00257
00258 msgsAwaitingProcessing.clear();
00259 msgIdsAwaitingProcessing.clear();
00260 msgUidsAwaitingProcessing.clear();
00261 mProcessing = false;
00262 }
00263
00264
00265
00266 void KMAcctExpPop::slotAbortRequested()
00267 {
00268 if (stage == Idle) return;
00269 disconnect(KMBroadcastStatus::instance(), SIGNAL(signalAbortRequested()),
00270 this, SLOT(slotAbortRequested()));
00271 stage = Quit;
00272 if (job) job->kill();
00273 job = 0;
00274 mSlave = 0;
00275 slotCancel();
00276 }
00277
00278
00279
00280 void KMAcctExpPop::startJob() {
00281
00282
00283 if (!runPrecommand(precommand()))
00284 {
00285 KMessageBox::sorry(0,
00286 i18n("Couldn't execute precommand: %1").arg(precommand()),
00287 i18n("KMail Error Message"));
00288 checkDone((idsOfMsgs.count() > 0), -1);
00289 return;
00290 }
00291
00292
00293 KURL url = getUrl();
00294
00295 if ( !url.isValid() ) {
00296 KMessageBox::error(0, i18n("Source URL is malformed"),
00297 i18n("Kioslave Error Message") );
00298 return;
00299 }
00300
00301 idsOfMsgsPendingDownload.clear();
00302 lensOfMsgsPendingDownload.clear();
00303 idsOfMsgs.clear();
00304 uidsOfMsgs.clear();
00305 idsOfMsgsToDelete.clear();
00306
00307 headersOnServer.clear();
00308 headers = false;
00309 indexOfCurrentMsg = -1;
00310 KMBroadcastStatus::instance()->reset();
00311 KMBroadcastStatus::instance()->setStatusProgressEnable( "P" + mName, true );
00312 KMBroadcastStatus::instance()->setStatusMsg(
00313 i18n("Preparing transmission from \"%1\"...").arg(mName));
00314 connect(KMBroadcastStatus::instance(), SIGNAL(signalAbortRequested()),
00315 this, SLOT(slotAbortRequested()));
00316
00317 numBytes = 0;
00318 numBytesRead = 0;
00319 stage = List;
00320 mSlave = KIO::Scheduler::getConnectedSlave( url, slaveConfig() );
00321 if (!mSlave)
00322 {
00323 slotSlaveError(0, KIO::ERR_CANNOT_LAUNCH_PROCESS, url.protocol());
00324 return;
00325 }
00326 url.setPath(QString("/index"));
00327 job = KIO::get( url, false, false );
00328 connectJob();
00329 }
00330
00331 MetaData KMAcctExpPop::slaveConfig() const {
00332 MetaData m = NetworkAccount::slaveConfig();
00333
00334 m.insert("progress", "off");
00335 m.insert("pipelining", (mUsePipelining) ? "on" : "off");
00336 if (mAuth == "PLAIN" || mAuth == "LOGIN" || mAuth == "CRAM-MD5" ||
00337 mAuth == "DIGEST-MD5") {
00338 m.insert("auth", "SASL");
00339 m.insert("sasl", mAuth);
00340 } else if ( mAuth == "*" )
00341 m.insert("auth", "USER");
00342 else
00343 m.insert("auth", mAuth);
00344
00345 return m;
00346 }
00347
00348
00349
00350
00351 void KMAcctExpPop::slotMsgRetrieved(KIO::Job*, const QString & infoMsg)
00352 {
00353 if (infoMsg != "message complete") return;
00354 KMMessage *msg = new KMMessage;
00355
00356
00357 uint newSize = KMFolder::crlf2lf( curMsgData.data(), curMsgData.size() );
00358 curMsgData.resize( newSize );
00359 msg->fromByteArray( curMsgData , true );
00360 if (stage == Head)
00361 {
00362 kdDebug(5006) << "Size of Message: " << (*lensOfMsgsPendingDownload.at(
00363 uidsOfMsgs.findIndex(headerIt.current()->uid()))) << endl;
00364 msg->setMsgLength(*lensOfMsgsPendingDownload.at(
00365 uidsOfMsgs.findIndex(headerIt.current()->uid())));
00366 headerIt.current()->setHeader(msg);
00367 ++headerIt;
00368 slotGetNextHdr();
00369 } else {
00370 kdDebug(5006) << "stage == Retr" << endl;
00371 kdDebug(5006) << QString( "curMsgData.size() %1" ).arg( curMsgData.size() ) << endl;
00372 msg->setMsgLength( curMsgData.size() );
00373 msgsAwaitingProcessing.append(msg);
00374 msgIdsAwaitingProcessing.append(idsOfMsgs[indexOfCurrentMsg]);
00375 msgUidsAwaitingProcessing.append(uidsOfMsgs[indexOfCurrentMsg]);
00376 slotGetNextMsg();
00377 }
00378 }
00379
00380
00381
00382
00383 void KMAcctExpPop::slotJobFinished() {
00384 QStringList emptyList;
00385 if (stage == List) {
00386 kdDebug(5006) << "stage == List" << endl;
00387 KURL url = getUrl();
00388 url.setPath(QString("/uidl"));
00389 job = KIO::get( url, false, false );
00390 connectJob();
00391 stage = Uidl;
00392 }
00393 else if (stage == Uidl) {
00394 kdDebug(5006) << "stage == Uidl" << endl;
00395 mUidlFinished = TRUE;
00396
00397 if (mLeaveOnServer && uidsOfMsgs.isEmpty() && uidsOfNextSeenMsgs.isEmpty()
00398 && !idsOfMsgs.isEmpty())
00399 {
00400 KMessageBox::sorry(0, i18n("Your POP3 server doesn't support the UIDL "
00401 "command. This command is required to determine in a reliable way, "
00402 "which of the mails on the server KMail has already seen before.\n"
00403 "The feature to leave the mails on the server will therefore not "
00404 "work properly."));
00405 }
00406
00407 if (uidsOfNextSeenMsgs.isEmpty())
00408 uidsOfNextSeenMsgs = uidsOfSeenMsgs;
00409
00410
00411 if (mFilterOnServer == true) {
00412 QStringList::Iterator hids = idsOfMsgsPendingDownload.begin();
00413 for (hids = idsOfMsgsPendingDownload.begin();
00414 hids != idsOfMsgsPendingDownload.end(); hids++) {
00415 int idx = idsOfMsgsPendingDownload.findIndex(*hids);
00416 kdDebug(5006) << "Length: " << *(lensOfMsgsPendingDownload.at(idx)) << endl;
00417
00418 if ((unsigned int)*(lensOfMsgsPendingDownload.at(idx))
00419 >= mFilterOnServerCheckSize) {
00420 kdDebug(5006) << "bigger than " << mFilterOnServerCheckSize << endl;
00421 headersOnServer.append(new KMPopHeaders(*idsOfMsgsPendingDownload.at(idx),
00422 *uidsOfMsgs.at(idx),
00423 Later));
00424
00425 if(headerDeleteUids.contains(headersOnServer.current()->uid())) {
00426 headersOnServer.current()->setAction(Delete);
00427 }
00428 else if(headerDownUids.contains(headersOnServer.current()->uid())) {
00429 headersOnServer.current()->setAction(Down);
00430 }
00431 else if(headerLaterUids.contains(headersOnServer.current()->uid())) {
00432 headersOnServer.current()->setAction(Later);
00433 }
00434 }
00435 }
00436
00437 headerDeleteUids.clear();
00438 headerDownUids.clear();
00439 headerLaterUids.clear();
00440 }
00441
00442
00443 if ((headersOnServer.count() > 0) && (mFilterOnServer == true)) {
00444 headerIt.toFirst();
00445 KURL url = getUrl();
00446 QString headerIds;
00447 while (headerIt.current())
00448 {
00449 headerIds += headerIt.current()->id();
00450 if (!headerIt.atLast()) headerIds += ",";
00451 ++headerIt;
00452 }
00453 headerIt.toFirst();
00454 url.setPath(QString("/headers/") + headerIds);
00455 job = KIO::get( url, false, false );
00456 connectJob();
00457 slotGetNextHdr();
00458 stage = Head;
00459 }
00460 else {
00461 stage = Retr;
00462 numMsgs = idsOfMsgsPendingDownload.count();
00463 numBytesToRead = 0;
00464 QValueList<int>::Iterator len = lensOfMsgsPendingDownload.begin();
00465 for (len = lensOfMsgsPendingDownload.begin();
00466 len != lensOfMsgsPendingDownload.end(); len++)
00467 numBytesToRead += *len;
00468 KURL url = getUrl();
00469 url.setPath("/download/" + idsOfMsgsPendingDownload.join(","));
00470 job = KIO::get( url, false, false );
00471 connectJob();
00472 slotGetNextMsg();
00473 processMsgsTimer.start(processingDelay);
00474 }
00475 }
00476 else if (stage == Head) {
00477 kdDebug(5006) << "stage == Head" << endl;
00478
00479
00480
00481
00482
00483
00484 KMPopFilterAction action;
00485 bool dlgPopup = false;
00486 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
00487 action = (KMPopFilterAction)kmkernel->popFilterMgr()->process(headersOnServer.current()->header());
00488
00489 switch ( action ) {
00490 case NoAction:
00491 kdDebug(5006) << "PopFilterAction = NoAction" << endl;
00492 break;
00493 case Later:
00494 kdDebug(5006) << "PopFilterAction = Later" << endl;
00495 break;
00496 case Delete:
00497 kdDebug(5006) << "PopFilterAction = Delete" << endl;
00498 break;
00499 case Down:
00500 kdDebug(5006) << "PopFilterAction = Down" << endl;
00501 break;
00502 default:
00503 kdDebug(5006) << "PopFilterAction = default oops!" << endl;
00504 break;
00505 }
00506 switch ( action ) {
00507 case NoAction:
00508
00509 dlgPopup = true;
00510 break;
00511 case Later:
00512 if (kmkernel->popFilterMgr()->showLaterMsgs())
00513 dlgPopup = true;
00514 default:
00515 headersOnServer.current()->setAction(action);
00516 headersOnServer.current()->setRuleMatched(true);
00517 break;
00518 }
00519 }
00520
00521
00522
00523 headers = true;
00524 if (dlgPopup) {
00525 KMPopFilterCnfrmDlg dlg(&headersOnServer, this->name(), kmkernel->popFilterMgr()->showLaterMsgs());
00526 dlg.exec();
00527 }
00528
00529 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
00530 if (headersOnServer.current()->action() == Delete ||
00531 headersOnServer.current()->action() == Later) {
00532
00533
00534 int idx = idsOfMsgsPendingDownload.findIndex(headersOnServer.current()->id());
00535 if (idx != -1) {
00536 idsOfMsgsPendingDownload.remove( idsOfMsgsPendingDownload
00537 .at( idx ));
00538 lensOfMsgsPendingDownload.remove( lensOfMsgsPendingDownload
00539 .at( idx ));
00540 idsOfMsgs.remove(idsOfMsgs.at( idx ));
00541 uidsOfMsgs.remove(uidsOfMsgs.at( idx ));
00542 }
00543 if (headersOnServer.current()->action() == Delete) {
00544 headerDeleteUids.append(headersOnServer.current()->uid());
00545 uidsOfNextSeenMsgs.append(headersOnServer.current()->uid());
00546 idsOfMsgsToDelete.append(headersOnServer.current()->id());
00547 }
00548 else {
00549 headerLaterUids.append(headersOnServer.current()->uid());
00550 }
00551 }
00552 else if (headersOnServer.current()->action() == Down) {
00553 headerDownUids.append(headersOnServer.current()->uid());
00554 }
00555 }
00556
00557 headersOnServer.clear();
00558 stage = Retr;
00559 numMsgs = idsOfMsgsPendingDownload.count();
00560 numBytesToRead = 0;
00561 QValueList<int>::Iterator len = lensOfMsgsPendingDownload.begin();
00562 for (len = lensOfMsgsPendingDownload.begin();
00563 len != lensOfMsgsPendingDownload.end(); len++)
00564 numBytesToRead += *len;
00565 KURL url = getUrl();
00566 url.setPath("/download/" + idsOfMsgsPendingDownload.join(","));
00567 job = KIO::get( url, false, false );
00568 connectJob();
00569 slotGetNextMsg();
00570 processMsgsTimer.start(processingDelay);
00571 }
00572 else if (stage == Retr) {
00573 processRemainingQueuedMessagesAndSaveUidList();
00574
00575 headerDeleteUids.clear();
00576 headerDownUids.clear();
00577 headerLaterUids.clear();
00578
00579 kmkernel->folderMgr()->syncAllFolders();
00580
00581 KURL url = getUrl();
00582 if (mLeaveOnServer || idsOfMsgsToDelete.isEmpty()) {
00583 url.setPath(QString("/commit"));
00584 job = KIO::get(url, false, false );
00585 }
00586 else {
00587 stage = Dele;
00588 url.setPath("/remove/" + idsOfMsgsToDelete.join(","));
00589 idsOfMsgsToDelete.clear();
00590 job = KIO::get( url, false, false );
00591 }
00592 connectJob();
00593 }
00594 else if (stage == Dele) {
00595 kdDebug(5006) << "stage == Dele" << endl;
00596 KURL url = getUrl();
00597 url.setPath(QString("/commit"));
00598 job = KIO::get( url, false, false );
00599 stage = Quit;
00600 connectJob();
00601 }
00602 else if (stage == Quit) {
00603 kdDebug(5006) << "stage == Quit" << endl;
00604 job = 0;
00605 if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
00606 mSlave = 0;
00607 stage = Idle;
00608 KMBroadcastStatus::instance()->setStatusProgressPercent( "P" + mName, 100 );
00609 int numMessages = (KMBroadcastStatus::instance()->abortRequested()) ?
00610 indexOfCurrentMsg : idsOfMsgs.count();
00611 KMBroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00612 numMessages, numBytes, numBytesRead, numBytesToRead, mLeaveOnServer );
00613 KMBroadcastStatus::instance()->setStatusProgressEnable( "P" + mName,
00614 false );
00615 KMBroadcastStatus::instance()->reset();
00616
00617 checkDone((numMessages > 0), numMessages);
00618 }
00619 }
00620
00621
00622
00623 void KMAcctExpPop::processRemainingQueuedMessagesAndSaveUidList()
00624 {
00625 kdDebug(5006) << "processRemainingQueuedMessagesAndSaveUidList" << endl;
00626 slotProcessPendingMsgs();
00627 processMsgsTimer.stop();
00628
00629 stage = Quit;
00630 kmkernel->folderMgr()->syncAllFolders();
00631
00632
00633
00634 if (!mUidlFinished) return;
00635 QString seenUidList = locateLocal( "data", "kmail/" + mLogin + ":" + "@" +
mHost + ":" + QString("%1").arg(mPort) );
00636
00637 KConfig config( seenUidList );
00638 config.writeEntry( "seenUidList", uidsOfNextSeenMsgs );
00639 config.writeEntry( "downloadLater", headerLaterUids );
00640 config.sync();
00641 }
00642
00643
00644
00645 void KMAcctExpPop::slotGetNextMsg()
00646 {
00647 QStringList::Iterator next = idsOfMsgsPendingDownload.begin();
00648 QValueList<int>::Iterator nextLen = lensOfMsgsPendingDownload.begin();
00649
00650 curMsgData.resize(0);
00651 numMsgBytesRead = 0;
00652 curMsgLen = 0;
00653 if (curMsgStrm)
00654 delete curMsgStrm;
00655 curMsgStrm = 0;
00656
00657 if (next == idsOfMsgsPendingDownload.end()) {
00658 kdDebug(5006) << "KMAcctExpPop::slotGetNextMsg was called too often" << endl;
00659 }
00660 else {
00661 curMsgStrm = new QDataStream( curMsgData, IO_WriteOnly );
00662 curMsgLen = *nextLen;
00663 ++indexOfCurrentMsg;
00664 idsOfMsgsPendingDownload.remove( next );
00665 kdDebug(5006) << QString("Length of message about to get %1").arg( *nextLen ) << endl;
00666 lensOfMsgsPendingDownload.remove( nextLen );
00667 }
00668 }
00669
00670
00671
00672 void KMAcctExpPop::slotData( KIO::Job* job, const QByteArray &data)
00673 {
00674 if (data.size() == 0) {
00675 kdDebug(5006) << "Data: <End>" << endl;
00676 if ((stage == Retr) && (numMsgBytesRead < curMsgLen))
00677 numBytesRead += curMsgLen - numMsgBytesRead;
00678 else if (stage == Head){
00679 kdDebug(5006) << "Head: <End>" << endl;
00680 }
00681 return;
00682 }
00683
00684 int oldNumMsgBytesRead = numMsgBytesRead;
00685 if (stage == Retr) {
00686 headers = false;
00687 curMsgStrm->writeRawBytes( data.data(), data.size() );
00688 numMsgBytesRead += data.size();
00689 if (numMsgBytesRead > curMsgLen)
00690 numMsgBytesRead = curMsgLen;
00691 numBytesRead += numMsgBytesRead - oldNumMsgBytesRead;
00692 dataCounter++;
00693 if (dataCounter % 5 == 0)
00694 {
00695 QString msg;
00696 if (numBytes != numBytesToRead && mLeaveOnServer)
00697 {
00698 msg = i18n("Fetching message %1 of %2 (%3 of %4 KB) from %5 "
00699 "(%6 KB remain on the server).")
00700 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
00701 .arg(numBytesToRead/1024).arg(mHost).arg(numBytes/1024);
00702 }
00703 else
00704 {
00705 msg = i18n("Fetching message %1 of %2 (%3 of %4 KB) from %5.")
00706 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
00707 .arg(numBytesToRead/1024).arg(mHost);
00708 }
00709 KMBroadcastStatus::instance()->setStatusMsg( msg );
00710 KMBroadcastStatus::instance()->setStatusProgressPercent("P" + mName,
00711 (numBytesToRead <= 100) ? 50
00712
00713 : (numBytesRead / (numBytesToRead / 100)) );
00714 }
00715 return;
00716 }
00717
00718 if (stage == Head) {
00719 curMsgStrm->writeRawBytes( data.data(), data.size() );
00720 return;
00721 }
00722
00723
00724 QString qdata = data;
00725 qdata = qdata.simplifyWhiteSpace();
00726 int spc = qdata.find( ' ' );
00727 if (spc > 0) {
00728 if (stage == List) {
00729 QString length = qdata.mid(spc+1);
00730 if (length.find(' ') != -1) length.truncate(length.find(' '));
00731 int len = length.toInt();
00732 numBytes += len;
00733 QString id = qdata.left(spc);
00734 idsOfMsgs.append( id );
00735 lensOfMsgsPendingDownload.append( len );
00736 idsOfMsgsPendingDownload.append( id );
00737 }
00738 else {
00739 QString uid = qdata.mid(spc + 1);
00740 uidsOfMsgs.append( uid );
00741 if (uidsOfSeenMsgs.contains(uid)) {
00742 QString id = qdata.left(spc);
00743 int idx = idsOfMsgsPendingDownload.findIndex(id);
00744 if (idx != -1) {
00745 lensOfMsgsPendingDownload.remove( lensOfMsgsPendingDownload
00746 .at( idx ));
00747 idsOfMsgsPendingDownload.remove( id );
00748 idsOfMsgs.remove( id );
00749 uidsOfMsgs.remove( uid );
00750 }
00751 else
00752 kdDebug(5006) << "KMAcctExpPop::slotData synchronization failure." << endl;
00753 if (uidsOfSeenMsgs.contains( uid ))
00754 idsOfMsgsToDelete.append( id );
00755 uidsOfNextSeenMsgs.append( uid );
00756 }
00757 }
00758 }
00759 else {
00760 stage = Idle;
00761 if (job) job->kill();
00762 job = 0;
00763 mSlave = 0;
00764 KMessageBox::error(0, i18n( "Unable to complete LIST operation" ),
00765 i18n("Invalid Response From Server"));
00766 return;
00767 }
00768 }
00769
00770
00771
00772 void KMAcctExpPop::slotResult( KIO::Job* )
00773 {
00774 if (!job) return;
00775 if ( job->error() )
00776 {
00777 if (interactive) {
00778 if (headers) {
00779 idsOfMsgs.clear();
00780 }
00781 if (stage == Head && job->error() == KIO::ERR_COULD_NOT_READ)
00782 {
00783 KMessageBox::error(0, i18n("Your server does not support the "
00784 "TOP command. Therefore it is not possible to fetch the headers "
00785 "of large emails first, before downloading them."));
00786 slotCancel();
00787 return;
00788 }
00789
00790 if (!mStorePasswd) mPasswd = "";
00791 job->showErrorDialog();
00792 }
00793 slotCancel();
00794 }
00795 else
00796 slotJobFinished();
00797 }
00798
00799
00800
00801 void KMAcctExpPop::slotSlaveError(KIO::Slave *aSlave, int error,
00802 const QString &errorMsg)
00803 {
00804 if (aSlave != mSlave) return;
00805 if (error == KIO::ERR_SLAVE_DIED) mSlave = 0;
00806
00807
00808 if ( error == KIO::ERR_CONNECTION_BROKEN && mSlave ) {
00809 KIO::Scheduler::disconnectSlave( mSlave );
00810 mSlave = 0;
00811 }
00812
00813 if (interactive) {
00814 KMessageBox::error(kmkernel->mainWin(), KIO::buildErrorString(error, errorMsg));
00815 }
00816
00817
00818 stage = Quit;
00819 if (error == KIO::ERR_COULD_NOT_LOGIN && !mStorePasswd)
00820 mAskAgain = TRUE;
00821
00822
00823
00824 QTimer::singleShot(0, this, SLOT(slotCancel()));
00825 }
00826
00827
00828 void KMAcctExpPop::slotGetNextHdr(){
00829 kdDebug(5006) << "slotGetNextHeader" << endl;
00830
00831 curMsgData.resize(0);
00832 delete curMsgStrm;
00833 curMsgStrm = 0;
00834
00835 curMsgStrm = new QDataStream( curMsgData, IO_WriteOnly );
00836 }
00837
00838 void KMAcctExpPop::killAllJobs( bool ) {
00839
00840 }
00841
00842 #include "kmacctexppop.moc"
00843