483void PopAccount::slotJobFinished() {
484 TQStringList emptyList;
486 kdDebug(5006) << k_funcinfo <<
"stage == List" << endl;
489 mUidsOfNextSeenMsgsDict.resize( KMail::nextPrime( ( idsOfMsgs.count() * 11 ) / 10 ) );
491 url.setPath(TQString(
"/uidl"));
492 job = TDEIO::get( url,
false,
false );
496 else if (stage == Uidl) {
497 kdDebug(5006) << k_funcinfo <<
"stage == Uidl" << endl;
498 mUidlFinished =
true;
500 if ( mLeaveOnServer && mUidForIdMap.isEmpty() &&
501 mUidsOfNextSeenMsgsDict.isEmpty() && !idsOfMsgs.isEmpty() ) {
502 KMessageBox::sorry(0, i18n(
"Your POP3 server (Account: %1) does not support "
503 "the UIDL command: this command is required to determine, in a reliable way, "
504 "which of the mails on the server KMail has already seen before;\n"
505 "the feature to leave the mails on the server will therefore not "
506 "work properly.").arg(NetworkAccount::name()) );
508 mUidsOfNextSeenMsgsDict = mUidsOfSeenMsgsDict;
512 if (mFilterOnServer ==
true) {
513 TQMap<TQString, int>::Iterator hids;
514 for ( hids = mMsgsPendingDownload.begin();
515 hids != mMsgsPendingDownload.end(); hids++ ) {
516 kdDebug(5006) <<
"Length: " << hids.data() << endl;
518 if ( (
unsigned int)hids.data() >= mFilterOnServerCheckSize ) {
519 kdDebug(5006) <<
"bigger than " << mFilterOnServerCheckSize << endl;
520 headersOnServer.append(
new KMPopHeaders( hids.key(),
521 mUidForIdMap[hids.key()],
524 if( mHeaderDeleteUids.contains( headersOnServer.current()->uid() ) ) {
525 headersOnServer.current()->setAction(Delete);
527 else if( mHeaderDownUids.contains( headersOnServer.current()->uid() ) ) {
528 headersOnServer.current()->setAction(Down);
530 else if( mHeaderLaterUids.contains( headersOnServer.current()->uid() ) ) {
531 headersOnServer.current()->setAction(Later);
536 mHeaderDeleteUids.clear();
537 mHeaderDownUids.clear();
538 mHeaderLaterUids.clear();
542 if ((headersOnServer.count() > 0) && (mFilterOnServer ==
true)) {
546 while (headerIt.current())
548 headerIds += headerIt.current()->id();
549 if (!headerIt.atLast()) headerIds +=
",";
553 url.setPath(TQString(
"/headers/") + headerIds);
554 job = TDEIO::get( url,
false,
false );
561 numMsgs = mMsgsPendingDownload.count();
563 TQMap<TQString, int>::Iterator len;
564 for ( len = mMsgsPendingDownload.begin();
565 len != mMsgsPendingDownload.end(); len++ )
566 numBytesToRead += len.data();
567 idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
569 url.setPath(
"/download/" + idsOfMsgs.join(
",") );
570 job = TDEIO::get( url,
false,
false );
573 processMsgsTimer.start(processingDelay);
576 else if (stage == Head) {
577 kdDebug(5006) << k_funcinfo <<
"stage == Head" << endl;
584 KMPopFilterAction action;
585 bool dlgPopup =
false;
586 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
587 action = (KMPopFilterAction)kmkernel->popFilterMgr()->process(headersOnServer.current()->header());
591 kdDebug(5006) <<
"PopFilterAction = NoAction" << endl;
594 kdDebug(5006) <<
"PopFilterAction = Later" << endl;
597 kdDebug(5006) <<
"PopFilterAction = Delete" << endl;
600 kdDebug(5006) <<
"PopFilterAction = Down" << endl;
603 kdDebug(5006) <<
"PopFilterAction = default oops!" << endl;
612 if (kmkernel->popFilterMgr()->showLaterMsgs())
616 headersOnServer.current()->setAction(action);
617 headersOnServer.current()->setRuleMatched(
true);
626 KMPopFilterCnfrmDlg dlg(&headersOnServer, this->name(), kmkernel->popFilterMgr()->showLaterMsgs());
630 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
631 if (headersOnServer.current()->action() == Delete ||
632 headersOnServer.current()->action() == Later) {
635 if ( mMsgsPendingDownload.contains( headersOnServer.current()->id() ) ) {
636 mMsgsPendingDownload.remove( headersOnServer.current()->id() );
638 if (headersOnServer.current()->action() == Delete) {
639 mHeaderDeleteUids.insert(headersOnServer.current()->uid(),
true);
640 mUidsOfNextSeenMsgsDict.insert( headersOnServer.current()->uid(),
642 idsOfMsgsToDelete.append(headersOnServer.current()->id());
643 mTimeOfNextSeenMsgsMap.insert( headersOnServer.current()->uid(),
647 mHeaderLaterUids.insert(headersOnServer.current()->uid(),
true);
650 else if (headersOnServer.current()->action() == Down) {
651 mHeaderDownUids.insert(headersOnServer.current()->uid(),
true);
655 headersOnServer.clear();
657 numMsgs = mMsgsPendingDownload.count();
659 TQMap<TQString, int>::Iterator len;
660 for (len = mMsgsPendingDownload.begin();
661 len != mMsgsPendingDownload.end(); len++)
662 numBytesToRead += len.data();
663 idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
665 url.setPath(
"/download/" + idsOfMsgs.join(
",") );
666 job = TDEIO::get( url,
false,
false );
669 processMsgsTimer.start(processingDelay);
671 else if (stage == Retr) {
672 if ( mMailCheckProgressItem )
673 mMailCheckProgressItem->setProgress( 100 );
674 processRemainingQueuedMessages();
676 mHeaderDeleteUids.clear();
677 mHeaderDownUids.clear();
678 mHeaderLaterUids.clear();
680 kmkernel->folderMgr()->syncAllFolders();
683 TQMap< TQPair<time_t, TQString>,
int > idsToSave;
686 if ( mLeaveOnServer && !idsOfMsgsToDelete.isEmpty() ) {
688 if ( mLeaveOnServerDays == -1 && mLeaveOnServerCount <= 0 &&
689 mLeaveOnServerSize <= 0)
690 idsOfMsgsToDelete.clear();
692 else if ( mLeaveOnServerDays > 0 && !mTimeOfNextSeenMsgsMap.isEmpty() ) {
693 time_t timeLimit = time(0) - (86400 * mLeaveOnServerDays);
694 kdDebug() <<
"timeLimit is " << timeLimit << endl;
695 TQStringList::Iterator cur = idsOfMsgsToDelete.begin();
696 for ( ; cur != idsOfMsgsToDelete.end(); ++cur) {
697 time_t msgTime = mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]];
698 kdDebug() <<
"id: " << *cur <<
" msgTime: " << msgTime << endl;
699 if (msgTime >= timeLimit ||
700 !mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]]) {
701 kdDebug() <<
"Saving msg id " << *cur << endl;
702 TQPair<time_t, TQString> msg(msgTime, *cur);
703 idsToSave.insert( msg, 1 );
708 if ( mLeaveOnServerCount > 0 ) {
709 int numToDelete = idsToSave.count() - mLeaveOnServerCount;
710 kdDebug() <<
"numToDelete is " << numToDelete << endl;
711 if ( numToDelete > 0 && (
unsigned)numToDelete < idsToSave.count() ) {
712 TQMap< TQPair<time_t, TQString>,
int >::Iterator cur = idsToSave.begin();
713 for (
int deleted = 0; deleted < numToDelete && cur != idsToSave.end()
714 ; deleted++, cur++ ) {
715 kdDebug() <<
"deleting msg id " << cur.key().second << endl;
716 idsToSave.remove( cur );
719 else if ( numToDelete > 0 && (
unsigned)numToDelete >= idsToSave.count() )
723 if ( mLeaveOnServerSize > 0 ) {
724 double sizeOnServer = 0;
725 TQMap< TQPair<time_t, TQString>,
int >::Iterator cur = idsToSave.begin();
726 for ( ; cur != idsToSave.end(); cur++ ) {
728 *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
730 kdDebug() <<
"sizeOnServer is " << sizeOnServer/(1024*1024) <<
"MB" << endl;
731 long limitInBytes = mLeaveOnServerSize * ( 1024 * 1024 );
732 for ( cur = idsToSave.begin(); cur != idsToSave.end()
733 && sizeOnServer > limitInBytes; cur++ ) {
735 *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
736 idsToSave.remove( cur );
740 TQMap< TQPair<time_t, TQString>,
int >::Iterator it = idsToSave.begin();
741 kdDebug() <<
"Going to save " << idsToSave.count() << endl;
742 for ( ; it != idsToSave.end(); ++it ) {
743 kdDebug() <<
"saving msg id " << it.key().second << endl;
744 idsOfMsgsToDelete.remove( it.key().second );
748 if ( !idsOfForcedDeletes.isEmpty() ) {
749 idsOfMsgsToDelete += idsOfForcedDeletes;
750 idsOfForcedDeletes.clear();
754 if ( !idsOfMsgsToDelete.isEmpty() ) {
756 if ( mMailCheckProgressItem )
757 mMailCheckProgressItem->setStatus(
758 i18n(
"Fetched 1 message from %1. Deleting messages from server...",
759 "Fetched %n messages from %1. Deleting messages from server...",
762 url.setPath(
"/remove/" + idsOfMsgsToDelete.join(
","));
763 kdDebug(5006) <<
"url: " << url.prettyURL() << endl;
766 if ( mMailCheckProgressItem )
767 mMailCheckProgressItem->setStatus(
768 i18n(
"Fetched 1 message from %1. Terminating transmission...",
769 "Fetched %n messages from %1. Terminating transmission...",
772 url.setPath(TQString(
"/commit"));
773 kdDebug(5006) <<
"url: " << url.prettyURL() << endl;
775 job = TDEIO::get( url,
false,
false );
778 else if (stage == Dele) {
779 kdDebug(5006) << k_funcinfo <<
"stage == Dele" << endl;
781 for ( TQStringList::ConstIterator it = idsOfMsgsToDelete.begin();
782 it != idsOfMsgsToDelete.end(); ++it ) {
783 mUidsOfNextSeenMsgsDict.remove( mUidForIdMap[*it] );
785 idsOfMsgsToDelete.clear();
786 if ( mMailCheckProgressItem )
787 mMailCheckProgressItem->setStatus(
788 i18n(
"Fetched 1 message from %1. Terminating transmission...",
789 "Fetched %n messages from %1. Terminating transmission...",
793 url.setPath(TQString(
"/commit"));
794 job = TDEIO::get( url,
false,
false );
798 else if (stage == Quit) {
799 kdDebug(5006) << k_funcinfo <<
"stage == Quit" << endl;
802 if (mSlave) TDEIO::Scheduler::disconnectSlave(mSlave);
805 if( mMailCheckProgressItem ) {
806 bool canceled = !kmkernel || kmkernel->mailCheckAborted() || mMailCheckProgressItem->canceled();
807 int numMessages = canceled ? indexOfCurrentMsg : idsOfMsgs.count();
808 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
809 this->name(), numMessages, numBytes, numBytesRead, numBytesToRead, mLeaveOnServer, mMailCheckProgressItem );
812 ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
813 mMailCheckProgressItem = 0;
814 savedMailCheckProgressItem->setComplete();
815 checkDone( ( numMessages > 0 ), canceled ? CheckAborted : CheckOK );
884void PopAccount::slotData( TDEIO::Job* job,
const TQByteArray &data)
886 if (data.size() == 0) {
887 kdDebug(5006) <<
"Data: <End>" << endl;
888 if ((stage == Retr) && (numMsgBytesRead < curMsgLen))
889 numBytesRead += curMsgLen - numMsgBytesRead;
890 else if (stage == Head){
891 kdDebug(5006) <<
"Head: <End>" << endl;
896 int oldNumMsgBytesRead = numMsgBytesRead;
899 curMsgStrm->writeRawBytes( data.data(), data.size() );
900 numMsgBytesRead += data.size();
901 if (numMsgBytesRead > curMsgLen)
902 numMsgBytesRead = curMsgLen;
903 numBytesRead += numMsgBytesRead - oldNumMsgBytesRead;
905 if ( mMailCheckProgressItem &&
906 ( dataCounter % 5 == 0 ||
907 ( indexOfCurrentMsg + 1 == numMsgs && numMsgBytesRead == curMsgLen ) ) )
910 if (numBytes != numBytesToRead && mLeaveOnServer)
912 msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6 "
913 "(%7 KB remain on the server).")
914 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
915 .arg(numBytesToRead/1024).arg(mLogin).arg(mHost).arg(numBytes/1024);
919 msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6.")
920 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
921 .arg(numBytesToRead/1024).arg(mLogin).arg(mHost);
923 mMailCheckProgressItem->setStatus( msg );
924 mMailCheckProgressItem->setProgress(
925 (numBytesToRead <= 100) ? 50
927 : (numBytesRead / (numBytesToRead / 100)) );
933 curMsgStrm->writeRawBytes( data.data(), data.size() );
938 TQString qdata = data;
939 qdata = qdata.simplifyWhiteSpace();
940 int spc = qdata.find(
' ' );
941 if ( stage == List ) {
943 TQString length = qdata.mid(spc+1);
944 if (length.find(
' ') != -1) length.truncate(length.find(
' '));
945 int len = length.toInt();
947 TQString
id = qdata.left(spc);
948 idsOfMsgs.append(
id );
949 mMsgsPendingDownload.insert(
id, len );
953 if ( job ) job->kill();
956 KMessageBox::error( 0, i18n(
"Unable to complete LIST operation." ),
957 i18n(
"Invalid Response From Server") );
962 Q_ASSERT ( stage == Uidl);
973 int testid = atoi ( qdata.ascii() );
976 kdDebug(5006) <<
"PopAccount::slotData skipping UIDL entry due to parse error "
977 << endl << qdata.ascii() << endl;
980 id.setNum (testid, 10);
982 TQString datestring, serialstring;
984 serialstring.setNum ( ++dataCounter, 10 );
985 datestring.setNum ( time(NULL),10 );
986 uid = TQString(
"uidlgen" ) + datestring + TQString(
"." ) + serialstring;
987 kdDebug(5006) <<
"PopAccount::slotData message " <<
id.ascii()
988 <<
"%d has bad UIDL, cannot keep a copy on server" << endl;
989 idsOfForcedDeletes.append(
id );
992 id = qdata.left( spc );
993 uid = qdata.mid( spc + 1 );
997 *size = mMsgsPendingDownload[id];
998 mSizeOfNextSeenMsgsDict.insert( uid, size );
999 if ( mUidsOfSeenMsgsDict.find( uid ) != 0 ) {
1000 if ( mMsgsPendingDownload.contains(
id ) ) {
1001 mMsgsPendingDownload.remove(
id );
1004 kdDebug(5006) <<
"PopAccount::slotData synchronization failure." << endl;
1005 idsOfMsgsToDelete.append(
id );
1006 mUidsOfNextSeenMsgsDict.insert( uid, (
const int *)1 );
1007 if ( mTimeOfSeenMsgsVector.empty() ) {
1008 mTimeOfNextSeenMsgsMap.insert( uid, time(0) );
1013 mTimeOfNextSeenMsgsMap.insert( uid, mTimeOfSeenMsgsVector[(
int)(
long )
1014 mUidsOfSeenMsgsDict[uid] - 1] );
1017 mUidForIdMap.insert(
id, uid );