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