27#include "popaccount.h" 
   29#include "broadcaststatus.h" 
   30using KPIM::BroadcastStatus;
 
   31#include "progressmanager.h" 
   32#include "kmfoldermgr.h" 
   33#include "kmfiltermgr.h" 
   34#include "kmpopfiltercnfrmdlg.h" 
   38#include "accountmanager.h" 
   41#include <tdestandarddirs.h> 
   43#include <tdemessagebox.h> 
   44#include <tdemainwindow.h> 
   45#include <tdeio/scheduler.h> 
   46#include <tdeio/passdlg.h> 
   50#include <tqstylesheet.h> 
   52static const unsigned short int pop3DefaultPort = 110;
 
   56PopAccount::PopAccount(
AccountManager* aOwner, 
const TQString& aAccountName, uint 
id)
 
   57  : NetworkAccount(aOwner, aAccountName, id),
 
   58    headerIt(headersOnServer),
 
   59    processMsgsTimer( 0, 
"processMsgsTimer" )
 
   64  mPort = defaultPort();
 
   66  indexOfCurrentMsg = -1;
 
   68  processingDelay = 2*100;
 
   71  mUidsOfSeenMsgsDict.setAutoDelete( 
false );
 
   72  mUidsOfNextSeenMsgsDict.setAutoDelete( 
false );
 
   74  headersOnServer.setAutoDelete(
true);
 
   75  connect(&processMsgsTimer,TQ_SIGNAL(timeout()),TQ_SLOT(slotProcessPendingMsgs()));
 
   76  TDEIO::Scheduler::connect(
 
   77    TQ_SIGNAL(slaveError(TDEIO::Slave *, 
int, 
const TQString &)),
 
   78    this, TQ_SLOT(slotSlaveError(TDEIO::Slave *, 
int, 
const TQString &)));
 
   80  mHeaderDeleteUids.clear();
 
   81  mHeaderDownUids.clear();
 
   82  mHeaderLaterUids.clear();
 
   87PopAccount::~PopAccount()
 
   91    mMsgsPendingDownload.clear();
 
   92    processRemainingQueuedMessages();
 
   99TQString PopAccount::type(
void)
 const 
  104TQString PopAccount::protocol()
 const {
 
  105  return useSSL() ? POP_SSL_PROTOCOL : POP_PROTOCOL;
 
  108unsigned short int PopAccount::defaultPort()
 const {
 
  109  return pop3DefaultPort;
 
  113void PopAccount::init(
void)
 
  115  NetworkAccount::init();
 
  117  mUsePipelining = 
false;
 
  118  mLeaveOnServer = 
false;
 
  119  mLeaveOnServerDays = -1;
 
  120  mLeaveOnServerCount = -1;
 
  121  mLeaveOnServerSize = -1;
 
  122  mFilterOnServer = 
false;
 
  124  mFilterOnServerCheckSize = 50000;
 
  128void PopAccount::pseudoAssign( 
const KMAccount * a ) {
 
  129  slotAbortRequested();
 
  130  NetworkAccount::pseudoAssign( a );
 
  145void PopAccount::processNewMail(
bool _interactive)
 
  149    if ( (mAskAgain || passwd().isEmpty() || mLogin.isEmpty()) &&
 
  150      mAuth != 
"GSSAPI" ) {
 
  151      TQString passwd = NetworkAccount::passwd();
 
  152      bool b = storePasswd();
 
  153      if (TDEIO::PasswordDialog::getNameAndPassword(mLogin, passwd, &b,
 
  154        i18n(
"You need to supply a username and a password to access this " 
  155        "mailbox."), 
false, TQString(), mName, i18n(
"Account:"))
 
  156        != TQDialog::Accepted)
 
  158        checkDone( 
false, CheckAborted );
 
  161        setPasswd( passwd, b );
 
  163          kmkernel->acctMgr()->writeConfig( 
true );
 
  169    TQString seenUidList = locateLocal( 
"data", 
"kmail/" + mLogin + 
":" + 
"@" +
 
  170                                       mHost + 
":" + TQString(
"%1").arg(mPort) );
 
  171    TDEConfig config( seenUidList );
 
  172    TQStringList uidsOfSeenMsgs = config.readListEntry( 
"seenUidList" );
 
  173    TQValueList<int> timeOfSeenMsgs = config.readIntListEntry( 
"seenUidTimeList" );
 
  174    mUidsOfSeenMsgsDict.clear();
 
  175    mUidsOfSeenMsgsDict.resize( KMail::nextPrime( ( uidsOfSeenMsgs.count() * 11 ) / 10 ) );
 
  177    for ( TQStringList::ConstIterator it = uidsOfSeenMsgs.begin();
 
  178          it != uidsOfSeenMsgs.end(); ++it, idx++ ) {
 
  182      mUidsOfSeenMsgsDict.insert( *it, (
const int *)idx );
 
  184    mTimeOfSeenMsgsVector.clear();
 
  185    mTimeOfSeenMsgsVector.reserve( timeOfSeenMsgs.size() );
 
  186    for ( TQValueList<int>::ConstIterator it = timeOfSeenMsgs.begin();
 
  187          it != timeOfSeenMsgs.end(); ++it) {
 
  188      mTimeOfSeenMsgsVector.append( *it );
 
  193    if ( mTimeOfSeenMsgsVector.count() != mUidsOfSeenMsgsDict.count() )
 
  194      mTimeOfSeenMsgsVector.clear();
 
  195    TQStringList downloadLater = config.readListEntry( 
"downloadLater" );
 
  196    for ( TQStringList::Iterator it = downloadLater.begin(); it != downloadLater.end(); ++it ) {
 
  197        mHeaderLaterUids.insert( *it, 
true );
 
  199    mUidsOfNextSeenMsgsDict.clear();
 
  200    mTimeOfNextSeenMsgsMap.clear();
 
  201    mSizeOfNextSeenMsgsDict.clear();
 
  203    interactive = _interactive;
 
  204    mUidlFinished = 
false;
 
  208    checkDone( 
false, CheckIgnored );
 
  215void PopAccount::readConfig(TDEConfig& config)
 
  217  NetworkAccount::readConfig(config);
 
  219  mUsePipelining = config.readNumEntry(
"pipelining", 
false);
 
  220  mLeaveOnServer = config.readNumEntry(
"leave-on-server", 
false);
 
  221  mLeaveOnServerDays = config.readNumEntry(
"leave-on-server-days", -1);
 
  222  mLeaveOnServerCount = config.readNumEntry(
"leave-on-server-count", -1);
 
  223  mLeaveOnServerSize = config.readNumEntry(
"leave-on-server-size", -1);
 
  224  mFilterOnServer = config.readNumEntry(
"filter-on-server", 
false);
 
  225  mFilterOnServerCheckSize = config.readUnsignedNumEntry(
"filter-os-check-size", 50000);
 
  230void PopAccount::writeConfig(TDEConfig& config)
 
  232  NetworkAccount::writeConfig(config);
 
  234  config.writeEntry(
"pipelining", mUsePipelining);
 
  235  config.writeEntry(
"leave-on-server", mLeaveOnServer);
 
  236  config.writeEntry(
"leave-on-server-days", mLeaveOnServerDays);
 
  237  config.writeEntry(
"leave-on-server-count", mLeaveOnServerCount);
 
  238  config.writeEntry(
"leave-on-server-size", mLeaveOnServerSize);
 
  239  config.writeEntry(
"filter-on-server", mFilterOnServer);
 
  240  config.writeEntry(
"filter-os-check-size", mFilterOnServerCheckSize);
 
  245void PopAccount::setUsePipelining(
bool b)
 
  251void PopAccount::setLeaveOnServer(
bool b)
 
  257void PopAccount::setLeaveOnServerDays(
int days)
 
  259  mLeaveOnServerDays = days;
 
  263void PopAccount::setLeaveOnServerCount(
int count)
 
  265  mLeaveOnServerCount = count;
 
  269void PopAccount::setLeaveOnServerSize(
int size)
 
  271  mLeaveOnServerSize = size;
 
  275void PopAccount::setFilterOnServer(
bool b)
 
  281void PopAccount::setFilterOnServerCheckSize(
unsigned int aSize)
 
  283  mFilterOnServerCheckSize = aSize;
 
  287void PopAccount::connectJob() {
 
  288  TDEIO::Scheduler::assignJobToSlave(mSlave, job);
 
  289  connect(job, TQ_SIGNAL( data( TDEIO::Job*, 
const TQByteArray &)),
 
  290         TQ_SLOT( slotData( TDEIO::Job*, 
const TQByteArray &)));
 
  291  connect(job, TQ_SIGNAL( result( TDEIO::Job * ) ),
 
  292         TQ_SLOT( slotResult( TDEIO::Job * ) ) );
 
  293  connect(job, TQ_SIGNAL(infoMessage( TDEIO::Job*, 
const TQString & )),
 
  294         TQ_SLOT( slotMsgRetrieved(TDEIO::Job*, 
const TQString &)));
 
  299void PopAccount::slotCancel()
 
  301  mMsgsPendingDownload.clear();
 
  302  processRemainingQueuedMessages();
 
  309void PopAccount::slotProcessPendingMsgs()
 
  316  TQValueList<KMMessage*>::Iterator cur = msgsAwaitingProcessing.begin();
 
  317  TQStringList::Iterator curId = msgIdsAwaitingProcessing.begin();
 
  318  TQStringList::Iterator curUid = msgUidsAwaitingProcessing.begin();
 
  320  while (cur != msgsAwaitingProcessing.end()) {
 
  326    addedOk = processNewMsg(*cur); 
 
  329      mMsgsPendingDownload.clear();
 
  330      msgIdsAwaitingProcessing.clear();
 
  331      msgUidsAwaitingProcessing.clear();
 
  335      idsOfMsgsToDelete.append( *curId );
 
  336      mUidsOfNextSeenMsgsDict.insert( *curUid, (
const int *)1 );
 
  337      mTimeOfNextSeenMsgsMap.insert( *curUid, time(0) );
 
  344  msgsAwaitingProcessing.clear();
 
  345  msgIdsAwaitingProcessing.clear();
 
  346  msgUidsAwaitingProcessing.clear();
 
  352void PopAccount::slotAbortRequested()
 
  354  if (stage == Idle) 
return;
 
  355  if ( mMailCheckProgressItem )
 
  356    disconnect( mMailCheckProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
 
  357                this, TQ_SLOT( slotAbortRequested() ) );
 
  359  if (job) job->kill();
 
  367void PopAccount::startJob()
 
  370  if (!runPrecommand(precommand()))
 
  372      KMessageBox::sorry(0,
 
  373                         i18n(
"Could not execute precommand: %1").arg(precommand()),
 
  374                         i18n(
"KMail Error Message"));
 
  375      checkDone( 
false, CheckError );
 
  382  if ( !url.isValid() ) {
 
  383    KMessageBox::error(0, i18n(
"Source URL is malformed"),
 
  384                          i18n(
"Kioslave Error Message") );
 
  388  mMsgsPendingDownload.clear();
 
  390  mUidForIdMap.clear();
 
  391  idsOfMsgsToDelete.clear();
 
  392  idsOfForcedDeletes.clear();
 
  395  headersOnServer.clear();
 
  397  indexOfCurrentMsg = -1;
 
  399  Q_ASSERT( !mMailCheckProgressItem );
 
  400  TQString escapedName = TQStyleSheet::escape( mName );
 
  401  mMailCheckProgressItem = KPIM::ProgressManager::createProgressItem(
 
  404    i18n(
"Preparing transmission from \"%1\"...").arg( escapedName ),
 
  406    useSSL() || useTLS() );
 
  407  connect( mMailCheckProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
 
  408           this, TQ_SLOT( slotAbortRequested() ) );
 
  413  mSlave = TDEIO::Scheduler::getConnectedSlave( url, slaveConfig() );
 
  416    slotSlaveError(0, TDEIO::ERR_CANNOT_LAUNCH_PROCESS, url.protocol());
 
  419  url.setPath(TQString(
"/index"));
 
  420  job = TDEIO::get( url, 
false, 
false );
 
  424MetaData PopAccount::slaveConfig()
 const {
 
  425  MetaData m = NetworkAccount::slaveConfig();
 
  427  m.insert(
"progress", 
"off");
 
  428  m.insert(
"pipelining", (mUsePipelining) ? 
"on" : 
"off");
 
  429  if (mAuth == 
"PLAIN" || mAuth == 
"LOGIN" || mAuth == 
"CRAM-MD5" ||
 
  430      mAuth == 
"DIGEST-MD5" || mAuth == 
"NTLM" || mAuth == 
"GSSAPI") {
 
  431    m.insert(
"auth", 
"SASL");
 
  432    m.insert(
"sasl", mAuth);
 
  433  } 
else if ( mAuth == 
"*" )
 
  434    m.insert(
"auth", 
"USER");
 
  436    m.insert(
"auth", mAuth);
 
  444void PopAccount::slotMsgRetrieved(TDEIO::Job*, 
const TQString & infoMsg)
 
  446  if (infoMsg != 
"message complete") 
return;
 
  451  uint newSize = Util::crlf2lf( curMsgData.data(), curMsgData.size() );
 
  452  curMsgData.resize( newSize );
 
  453  msg->fromByteArray( curMsgData , 
true );
 
  456    int size = mMsgsPendingDownload[ headerIt.current()->id() ];
 
  457    kdDebug(5006) << 
"Size of Message: " << size << endl;
 
  458    msg->setMsgLength( size );
 
  459    headerIt.current()->setHeader(msg);
 
  465    msg->setMsgLength( curMsgData.size() );
 
  466    msgsAwaitingProcessing.append(msg);
 
  467    msgIdsAwaitingProcessing.append(idsOfMsgs[indexOfCurrentMsg]);
 
  468    msgUidsAwaitingProcessing.append( mUidForIdMap[idsOfMsgs[indexOfCurrentMsg]] );
 
  476void PopAccount::slotJobFinished() {
 
  477  TQStringList emptyList;
 
  479    kdDebug(5006) << k_funcinfo << 
"stage == List" << endl;
 
  482    mUidsOfNextSeenMsgsDict.resize( KMail::nextPrime( ( idsOfMsgs.count() * 11 ) / 10 ) );
 
  484    url.setPath(TQString(
"/uidl"));
 
  485    job = TDEIO::get( url, 
false, 
false );
 
  489  else if (stage == Uidl) {
 
  490    kdDebug(5006) << k_funcinfo << 
"stage == Uidl" << endl;
 
  491    mUidlFinished = 
true;
 
  493    if ( mLeaveOnServer && mUidForIdMap.isEmpty() &&
 
  494        mUidsOfNextSeenMsgsDict.isEmpty() && !idsOfMsgs.isEmpty() ) {
 
  495      KMessageBox::sorry(0, i18n(
"Your POP3 server (Account: %1) does not support " 
  496      "the UIDL command: this command is required to determine, in a reliable way, " 
  497      "which of the mails on the server KMail has already seen before;\n" 
  498      "the feature to leave the mails on the server will therefore not " 
  499      "work properly.").arg(NetworkAccount::name()) );
 
  501      mUidsOfNextSeenMsgsDict = mUidsOfSeenMsgsDict;
 
  505    if (mFilterOnServer == 
true) {
 
  506      TQMap<TQString, int>::Iterator hids;
 
  507      for ( hids = mMsgsPendingDownload.begin();
 
  508            hids != mMsgsPendingDownload.end(); hids++ ) {
 
  509          kdDebug(5006) << 
"Length: " << hids.data() << endl;
 
  511          if ( (
unsigned int)hids.data() >= mFilterOnServerCheckSize ) {
 
  512            kdDebug(5006) << 
"bigger than " << mFilterOnServerCheckSize << endl;
 
  513            headersOnServer.append(
new KMPopHeaders( hids.key(),
 
  514                                                     mUidForIdMap[hids.key()],
 
  517            if( mHeaderDeleteUids.contains( headersOnServer.current()->uid() ) ) {
 
  518              headersOnServer.current()->setAction(Delete);
 
  520            else if( mHeaderDownUids.contains( headersOnServer.current()->uid() ) ) {
 
  521              headersOnServer.current()->setAction(Down);
 
  523            else if( mHeaderLaterUids.contains( headersOnServer.current()->uid() ) ) {
 
  524              headersOnServer.current()->setAction(Later);
 
  529      mHeaderDeleteUids.clear();
 
  530      mHeaderDownUids.clear();
 
  531      mHeaderLaterUids.clear();
 
  535    if ((headersOnServer.count() > 0) && (mFilterOnServer == 
true)) {
 
  539      while (headerIt.current())
 
  541        headerIds += headerIt.current()->id();
 
  542        if (!headerIt.atLast()) headerIds += 
",";
 
  546      url.setPath(TQString(
"/headers/") + headerIds);
 
  547      job = TDEIO::get( url, 
false, 
false );
 
  554      numMsgs = mMsgsPendingDownload.count();
 
  556      TQMap<TQString, int>::Iterator len;
 
  557      for ( len  = mMsgsPendingDownload.begin();
 
  558            len != mMsgsPendingDownload.end(); len++ )
 
  559        numBytesToRead += len.data();
 
  560      idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
 
  562      url.setPath( 
"/download/" + idsOfMsgs.join(
",") );
 
  563      job = TDEIO::get( url, 
false, 
false );
 
  566      processMsgsTimer.start(processingDelay);
 
  569  else if (stage == Head) {
 
  570    kdDebug(5006) << k_funcinfo << 
"stage == Head" << endl;
 
  577    KMPopFilterAction action;
 
  578    bool dlgPopup = 
false;
 
  579    for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
 
  580      action = (KMPopFilterAction)kmkernel->popFilterMgr()->process(headersOnServer.current()->header());
 
  584          kdDebug(5006) << 
"PopFilterAction = NoAction" << endl;
 
  587          kdDebug(5006) << 
"PopFilterAction = Later" << endl;
 
  590          kdDebug(5006) << 
"PopFilterAction = Delete" << endl;
 
  593          kdDebug(5006) << 
"PopFilterAction = Down" << endl;
 
  596          kdDebug(5006) << 
"PopFilterAction = default oops!" << endl;
 
  605          if (kmkernel->popFilterMgr()->showLaterMsgs())
 
  609          headersOnServer.current()->setAction(action);
 
  610          headersOnServer.current()->setRuleMatched(
true);
 
  619      KMPopFilterCnfrmDlg dlg(&headersOnServer, this->name(), kmkernel->popFilterMgr()->showLaterMsgs());
 
  623    for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
 
  624      if (headersOnServer.current()->action() == Delete ||
 
  625          headersOnServer.current()->action() == Later) {
 
  628        if ( mMsgsPendingDownload.contains( headersOnServer.current()->id() ) ) {
 
  629          mMsgsPendingDownload.remove( headersOnServer.current()->id() );
 
  631        if (headersOnServer.current()->action() == Delete) {
 
  632          mHeaderDeleteUids.insert(headersOnServer.current()->uid(), 
true);
 
  633          mUidsOfNextSeenMsgsDict.insert( headersOnServer.current()->uid(),
 
  635          idsOfMsgsToDelete.append(headersOnServer.current()->id());
 
  636          mTimeOfNextSeenMsgsMap.insert( headersOnServer.current()->uid(),
 
  640          mHeaderLaterUids.insert(headersOnServer.current()->uid(), 
true);
 
  643      else if (headersOnServer.current()->action() == Down) {
 
  644        mHeaderDownUids.insert(headersOnServer.current()->uid(), 
true);
 
  648    headersOnServer.clear();
 
  650    numMsgs = mMsgsPendingDownload.count();
 
  652    TQMap<TQString, int>::Iterator len;
 
  653    for (len = mMsgsPendingDownload.begin();
 
  654         len != mMsgsPendingDownload.end(); len++)
 
  655      numBytesToRead += len.data();
 
  656    idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
 
  658    url.setPath( 
"/download/" + idsOfMsgs.join(
",") );
 
  659    job = TDEIO::get( url, 
false, 
false );
 
  662    processMsgsTimer.start(processingDelay);
 
  664  else if (stage == Retr) {
 
  665    if ( mMailCheckProgressItem )
 
  666      mMailCheckProgressItem->setProgress( 100 );
 
  667    processRemainingQueuedMessages();
 
  669    mHeaderDeleteUids.clear();
 
  670    mHeaderDownUids.clear();
 
  671    mHeaderLaterUids.clear();
 
  673    kmkernel->folderMgr()->syncAllFolders();
 
  676    TQMap< TQPair<time_t, TQString>, 
int > idsToSave;
 
  679    if ( mLeaveOnServer && !idsOfMsgsToDelete.isEmpty() ) {
 
  681      if ( mLeaveOnServerDays == -1 && mLeaveOnServerCount <= 0 &&
 
  682           mLeaveOnServerSize <= 0)
 
  683        idsOfMsgsToDelete.clear();
 
  685      else if ( mLeaveOnServerDays > 0 && !mTimeOfNextSeenMsgsMap.isEmpty() ) {
 
  686        time_t timeLimit = time(0) - (86400 * mLeaveOnServerDays);
 
  687        kdDebug() << 
"timeLimit is " << timeLimit << endl;
 
  688        TQStringList::Iterator cur = idsOfMsgsToDelete.begin();
 
  689        for ( ; cur != idsOfMsgsToDelete.end(); ++cur) {
 
  690          time_t msgTime = mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]];
 
  691          kdDebug() << 
"id: " << *cur << 
" msgTime: " << msgTime << endl;
 
  692          if (msgTime >= timeLimit ||
 
  693                !mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]]) {
 
  694            kdDebug() << 
"Saving msg id " << *cur << endl;
 
  695            TQPair<time_t, TQString> msg(msgTime, *cur);
 
  696            idsToSave.insert( msg, 1 );
 
  701      if ( mLeaveOnServerCount > 0 ) {
 
  702        int numToDelete = idsToSave.count() - mLeaveOnServerCount;
 
  703        kdDebug() << 
"numToDelete is " << numToDelete << endl;
 
  704        if ( numToDelete > 0 && (
unsigned)numToDelete < idsToSave.count() ) {
 
  705          TQMap< TQPair<time_t, TQString>, 
int >::Iterator cur = idsToSave.begin();
 
  706          for ( 
int deleted = 0; deleted < numToDelete && cur != idsToSave.end()
 
  707                ; deleted++, cur++ ) {
 
  708            kdDebug() << 
"deleting msg id " << cur.key().second << endl;
 
  709            idsToSave.remove( cur );
 
  712        else if ( numToDelete > 0 && (
unsigned)numToDelete >= idsToSave.count() )
 
  716      if ( mLeaveOnServerSize > 0 ) {
 
  717        double sizeOnServer = 0;
 
  718        TQMap< TQPair<time_t, TQString>, 
int >::Iterator cur = idsToSave.begin();
 
  719        for ( ; cur != idsToSave.end(); cur++ ) {
 
  721            *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
 
  723        kdDebug() << 
"sizeOnServer is " << sizeOnServer/(1024*1024) << 
"MB" << endl;
 
  724        long limitInBytes = mLeaveOnServerSize * ( 1024 * 1024 );
 
  725        for ( cur = idsToSave.begin(); cur != idsToSave.end()
 
  726                && sizeOnServer > limitInBytes; cur++ ) {
 
  728            *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
 
  729          idsToSave.remove( cur );
 
  733      TQMap< TQPair<time_t, TQString>, 
int >::Iterator it = idsToSave.begin();
 
  734      kdDebug() << 
"Going to save " << idsToSave.count() << endl;
 
  735      for ( ; it != idsToSave.end(); ++it ) {
 
  736        kdDebug() << 
"saving msg id " << it.key().second << endl;
 
  737        idsOfMsgsToDelete.remove( it.key().second );
 
  741    if ( !idsOfForcedDeletes.isEmpty() ) {
 
  742      idsOfMsgsToDelete += idsOfForcedDeletes;
 
  743      idsOfForcedDeletes.clear();
 
  747    if ( !idsOfMsgsToDelete.isEmpty() ) {
 
  749      if ( mMailCheckProgressItem )
 
  750        mMailCheckProgressItem->setStatus(
 
  751          i18n( 
"Fetched 1 message from %1. Deleting messages from server...",
 
  752                "Fetched %n messages from %1. Deleting messages from server...",
 
  755      url.setPath(
"/remove/" + idsOfMsgsToDelete.join(
","));
 
  756      kdDebug(5006) << 
"url: " << url.prettyURL() << endl;
 
  759      if ( mMailCheckProgressItem )
 
  760        mMailCheckProgressItem->setStatus(
 
  761          i18n( 
"Fetched 1 message from %1. Terminating transmission...",
 
  762                "Fetched %n messages from %1. Terminating transmission...",
 
  765      url.setPath(TQString(
"/commit"));
 
  766      kdDebug(5006) << 
"url: " << url.prettyURL() << endl;
 
  768    job = TDEIO::get( url, 
false, 
false );
 
  771  else if (stage == Dele) {
 
  772    kdDebug(5006) << k_funcinfo << 
"stage == Dele" << endl;
 
  774    for ( TQStringList::ConstIterator it = idsOfMsgsToDelete.begin();
 
  775          it != idsOfMsgsToDelete.end(); ++it ) {
 
  776      mUidsOfNextSeenMsgsDict.remove( mUidForIdMap[*it] );
 
  778    idsOfMsgsToDelete.clear();
 
  779    if ( mMailCheckProgressItem )
 
  780      mMailCheckProgressItem->setStatus(
 
  781        i18n( 
"Fetched 1 message from %1. Terminating transmission...",
 
  782              "Fetched %n messages from %1. Terminating transmission...",
 
  786    url.setPath(TQString(
"/commit"));
 
  787    job = TDEIO::get( url, 
false, 
false );
 
  791  else if (stage == Quit) {
 
  792    kdDebug(5006) << k_funcinfo << 
"stage == Quit" << endl;
 
  795    if (mSlave) TDEIO::Scheduler::disconnectSlave(mSlave);
 
  798    if( mMailCheckProgressItem ) { 
 
  799      bool canceled = !kmkernel || kmkernel->mailCheckAborted() || mMailCheckProgressItem->canceled();
 
  800      int numMessages = canceled ? indexOfCurrentMsg : idsOfMsgs.count();
 
  801      BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
 
  802        this->name(), numMessages, numBytes, numBytesRead, numBytesToRead, mLeaveOnServer, mMailCheckProgressItem );
 
  805      ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
 
  806      mMailCheckProgressItem = 0;
 
  807      savedMailCheckProgressItem->setComplete(); 
 
  808      checkDone( ( numMessages > 0 ), canceled ? CheckAborted : CheckOK );
 
  815void PopAccount::processRemainingQueuedMessages()
 
  817  kdDebug(5006) << k_funcinfo << endl;
 
  818  slotProcessPendingMsgs(); 
 
  819  processMsgsTimer.stop();
 
  822  if ( kmkernel && kmkernel->folderMgr() ) {
 
  823    kmkernel->folderMgr()->syncAllFolders();
 
  829void PopAccount::saveUidList()
 
  831  kdDebug(5006) << k_funcinfo << endl;
 
  834  if (!mUidlFinished) 
return;
 
  836  TQStringList uidsOfNextSeenMsgs;
 
  837  TQValueList<int> seenUidTimeList;
 
  838  TQDictIterator<int> it( mUidsOfNextSeenMsgsDict );
 
  839  for( ; it.current(); ++it ) {
 
  840    uidsOfNextSeenMsgs.append( it.currentKey() );
 
  841    seenUidTimeList.append( mTimeOfNextSeenMsgsMap[it.currentKey()] );
 
  843  TQString seenUidList = locateLocal( 
"data", 
"kmail/" + mLogin + 
":" + 
"@" +
 
  844                                      mHost + 
":" + TQString(
"%1").arg(mPort) );
 
  845  TDEConfig config( seenUidList );
 
  846  config.writeEntry( 
"seenUidList", uidsOfNextSeenMsgs );
 
  847  config.writeEntry( 
"seenUidTimeList", seenUidTimeList );
 
  848  config.writeEntry( 
"downloadLater", TQStringList( mHeaderLaterUids.keys() ) );
 
  854void PopAccount::slotGetNextMsg()
 
  856  TQMap<TQString, int>::Iterator next = mMsgsPendingDownload.begin();
 
  858  curMsgData.resize(0);
 
  864  if ( next != mMsgsPendingDownload.end() ) {
 
  866    int nextLen = next.data();
 
  867    curMsgStrm = 
new TQDataStream( curMsgData, IO_WriteOnly );
 
  870    kdDebug(5006) << TQString(
"Length of message about to get %1").arg( nextLen ) << endl;
 
  871    mMsgsPendingDownload.remove( next.key() );
 
  877void PopAccount::slotData( TDEIO::Job* job, 
const TQByteArray &data)
 
  879  if (data.size() == 0) {
 
  880    kdDebug(5006) << 
"Data: <End>" << endl;
 
  881    if ((stage == Retr) && (numMsgBytesRead < curMsgLen))
 
  882      numBytesRead += curMsgLen - numMsgBytesRead;
 
  883    else if (stage == Head){
 
  884      kdDebug(5006) << 
"Head: <End>" << endl;
 
  889  int oldNumMsgBytesRead = numMsgBytesRead;
 
  892    curMsgStrm->writeRawBytes( data.data(), data.size() );
 
  893    numMsgBytesRead += data.size();
 
  894    if (numMsgBytesRead > curMsgLen)
 
  895      numMsgBytesRead = curMsgLen;
 
  896    numBytesRead += numMsgBytesRead - oldNumMsgBytesRead;
 
  898    if ( mMailCheckProgressItem &&
 
  899         ( dataCounter % 5 == 0 ||
 
  900           ( indexOfCurrentMsg + 1 == numMsgs && numMsgBytesRead == curMsgLen ) ) )
 
  903      if (numBytes != numBytesToRead && mLeaveOnServer)
 
  905        msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6 " 
  906                   "(%7 KB remain on the server).")
 
  907          .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
 
  908          .arg(numBytesToRead/1024).arg(mLogin).arg(mHost).arg(numBytes/1024);
 
  912        msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6.")
 
  913          .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
 
  914          .arg(numBytesToRead/1024).arg(mLogin).arg(mHost);
 
  916      mMailCheckProgressItem->setStatus( msg );
 
  917      mMailCheckProgressItem->setProgress(
 
  918        (numBytesToRead <= 100) ? 50  
 
  920        : (numBytesRead / (numBytesToRead / 100)) );
 
  926    curMsgStrm->writeRawBytes( data.data(), data.size() );
 
  931  TQString qdata = data;
 
  932  qdata = qdata.simplifyWhiteSpace(); 
 
  933  int spc = qdata.find( 
' ' );
 
  934  if ( stage == List ) {
 
  936      TQString length = qdata.mid(spc+1);
 
  937      if (length.find(
' ') != -1) length.truncate(length.find(
' '));
 
  938      int len = length.toInt();
 
  940      TQString 
id = qdata.left(spc);
 
  941      idsOfMsgs.append( 
id );
 
  942      mMsgsPendingDownload.insert( 
id, len );
 
  946      if ( job ) job->kill();
 
  949      KMessageBox::error( 0, i18n( 
"Unable to complete LIST operation." ),
 
  950                             i18n( 
"Invalid Response From Server") );
 
  955    Q_ASSERT ( stage == Uidl);
 
  966      int testid = atoi ( qdata.ascii() );
 
  969        kdDebug(5006) << 
"PopAccount::slotData skipping UIDL entry due to parse error " 
  970                      << endl << qdata.ascii() << endl;
 
  973      id.setNum (testid, 10);
 
  975      TQString datestring, serialstring;
 
  977      serialstring.setNum ( ++dataCounter, 10 );
 
  978      datestring.setNum ( time(NULL),10 );
 
  979      uid = TQString( 
"uidlgen" ) + datestring + TQString( 
"." ) + serialstring;
 
  980      kdDebug(5006) << 
"PopAccount::slotData message " << 
id.ascii()
 
  981                    <<  
"%d has bad UIDL, cannot keep a copy on server" << endl;
 
  982      idsOfForcedDeletes.append( 
id );
 
  985      id = qdata.left( spc );
 
  986      uid = qdata.mid( spc + 1 );
 
  990    *size = mMsgsPendingDownload[id];
 
  991    mSizeOfNextSeenMsgsDict.insert( uid, size );
 
  992    if ( mUidsOfSeenMsgsDict.find( uid ) != 0 ) {
 
  993      if ( mMsgsPendingDownload.contains( 
id ) ) {
 
  994        mMsgsPendingDownload.remove( 
id );
 
  997        kdDebug(5006) << 
"PopAccount::slotData synchronization failure." << endl;
 
  998      idsOfMsgsToDelete.append( 
id );
 
  999      mUidsOfNextSeenMsgsDict.insert( uid, (
const int *)1 );
 
 1000      if ( mTimeOfSeenMsgsVector.empty() ) {
 
 1001        mTimeOfNextSeenMsgsMap.insert( uid, time(0) );
 
 1006        mTimeOfNextSeenMsgsMap.insert( uid, mTimeOfSeenMsgsVector[(
int)( 
long )
 
 1007                                                 mUidsOfSeenMsgsDict[uid] - 1] );
 
 1010    mUidForIdMap.insert( 
id, uid );
 
 1015void PopAccount::slotResult( TDEIO::Job* )
 
 1024      if (stage == Head && job->error() == TDEIO::ERR_COULD_NOT_READ)
 
 1026        KMessageBox::error(0, i18n(
"Your server does not support the " 
 1027          "TOP command. Therefore it is not possible to fetch the headers " 
 1028          "of large emails first, before downloading them."));
 
 1033      if (!mStorePasswd) mPasswd = 
"";
 
 1034      job->showErrorDialog();
 
 1044void PopAccount::slotSlaveError(TDEIO::Slave *aSlave, 
int error,
 
 1045  const TQString &errorMsg)
 
 1047  if (aSlave != mSlave) 
return;
 
 1048  if (error == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
 
 1051  if ( error == TDEIO::ERR_CONNECTION_BROKEN && mSlave ) {
 
 1052    TDEIO::Scheduler::disconnectSlave( mSlave );
 
 1056  if (interactive && kmkernel) {
 
 1057    KMessageBox::error(kmkernel->mainWin(), TDEIO::buildErrorString(error, errorMsg));
 
 1062  if (error == TDEIO::ERR_COULD_NOT_LOGIN && !mStorePasswd)
 
 1067  TQTimer::singleShot(0, 
this, TQ_SLOT(slotCancel()));
 
 1071void PopAccount::slotGetNextHdr(){
 
 1072  kdDebug(5006) << 
"slotGetNextHeader" << endl;
 
 1074  curMsgData.resize(0);
 
 1078  curMsgStrm = 
new TQDataStream( curMsgData, IO_WriteOnly );
 
 1081void PopAccount::killAllJobs( 
bool ) {
 
 1086#include "popaccount.moc" 
void setComplete(bool v)
Set if the message is a complete message.
 
The account manager is responsible for creating accounts of various types via the factory method crea...
 
KMail account for pop mail account.
 
bool filterOnServer(void) const
Shall messages be filter on the server (true) or not (false).
 
bool usePipelining(void) const
Sending of several commands at once.
 
int leaveOnServerDays(void) const
If value is positive, leave mail on the server for so many days.
 
int leaveOnServerSize(void) const
If value is positive, leave so many MBs on the server.
 
bool leaveOnServer(void) const
Shall messages be left on the server upon retreival (true) or deleted (false).
 
int leaveOnServerCount(void) const
If value is positive, leave so many messages on the server.
 
unsigned int filterOnServerCheckSize(void) const
Size of messages which should be check on the pop server before download.