Source Code (Use browser search to find items of interest.)

Class Index

kmail'KMAcctPop (./kdenetwork/kmail/kmacctpop.h:18)

class KMAcctPop: public KMAccount
{
  Q_OBJECT

public:
  virtual ~KMAcctPop();
  virtual void init(void);

  /** Pop user login name */
  const QString& login(void) const { return mLogin; }
  virtual void setLogin(const QString&);

  /** Pop user password */
  const QString passwd(void) const;
  virtual void setPasswd(const QString&, bool storeInConfig=FALSE);

  /** Will the password be stored in the config file ? */
  bool storePasswd(void) const { return mStorePasswd; }
  virtual void setStorePasswd(bool);

  /** Pop host */
  const QString& host(void) const { return mHost; }
  virtual void setHost(const QString&);

  /** Port on pop host */
  unsigned short int port(void) { return mPort; }
  virtual void setPort(unsigned short int);

  /** Pop protocol: shall be 2 or 3 */
  short protocol(void) { return mProtocol; }
  virtual bool setProtocol(short);

  /** Shall messages be left on the server upon retreival (TRUE) 
    or deleted (FALSE). */
  bool leaveOnServer(void) const { return mLeaveOnServer; }
  virtual void setLeaveOnServer(bool);

  /** Retrieve all messages from server (TRUE) or unread messages only. */
  bool retrieveAll(void) const { return mRetrieveAll; }
  virtual void setRetrieveAll(bool);

  /** Inherited methods. */
  virtual const char* type(void) const;
  virtual void readConfig(KConfig&);
  virtual void writeConfig(KConfig&);
  virtual void processNewMail(bool interactive);

  
protected:
  friend class KMAcctMgr;
  friend class KMPasswdDialog;
  KMAcctPop(KMAcctMgr* owner, const char* accountName);

  /** Very primitive en/de-cryption so that the password is not
      readable in the config file. But still very easy breakable. */
  const QString encryptStr(const QString inStr) const;
  const QString decryptStr(const QString inStr) const;

  /** Mail processing main worker method. */
  virtual bool doProcessNewMail(bool interactive);

  /** Authenticate at POP server. Returns TRUE on success and FALSE
    on failure. Automatically asks for user/password if necessary. */
  virtual bool authenticate(DwPopClient&);

  /** Display POP error message. Always returns FALSE to simplify the
    code in doProcessNewMail(). */
  virtual bool popError(const QString stage, DwPopClient&) const;

  QString mLogin, mPasswd;
  QString mHost;
  unsigned short int mPort;
  short   mProtocol;
  bool    mStorePasswd;
  bool    mLeaveOnServer;
  bool    mRetrieveAll;
  bool    gotMsgs;
};


//-----------------------------------------------------------------------------

kmail'KMAcctPop::KMAcctPop() (./kdenetwork/kmail/kmacctpop.cpp:35)

KMAcctPop::KMAcctPop(KMAcctMgr* aOwner, const char* aAccountName):
  KMAcctPopInherited(aOwner, aAccountName)
{
  initMetaObject();

  mStorePasswd = FALSE;
  mLeaveOnServer = FALSE;
  mRetrieveAll = TRUE;
  mProtocol = 3;
  mPort = 110;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::~KMAcctPop() (./kdenetwork/kmail/kmacctpop.cpp:49)

KMAcctPop::~KMAcctPop()
{
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::type() (./kdenetwork/kmail/kmacctpop.cpp:55)

const char* KMAcctPop::type(void) const
{
  return "pop";
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::init() (./kdenetwork/kmail/kmacctpop.cpp:62)

void KMAcctPop::init(void)
{
  mHost   = "";
  mPort   = 110;
  mLogin  = "";
  mPasswd = "";
  mProtocol = 3;
  mStorePasswd = FALSE;
  mLeaveOnServer = FALSE;
  mRetrieveAll = TRUE;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::processNewMail() (./kdenetwork/kmail/kmacctpop.cpp:76)

void KMAcctPop::processNewMail(bool interactive)
{
  void (*oldHandler)(int);
  void (*pipeHandler)(int);
  bool hasNewMail;

  // Before we do anything else let's ignore the friggin' SIGALRM signal
  // This signal somehow interrupts the network functions and messed up
  // DwPopClient::Open().
  oldHandler = signal(SIGALRM, SIG_IGN);
  // Another one of those nice little SIGNALS which default action is to 
  // abort the app when received. SIGPIPE is send when e.g the client attempts
  // to write to a TCP socket when the connection was shutdown by the server.
  pipeHandler = signal(SIGPIPE, SIG_IGN);
  KMBroadcastStatus::instance()->reset();
  KMBroadcastStatus::instance()->setStatusMsg( 
                     i18n( "Preparing transmission..." ));
  KMBroadcastStatus::instance()->setStatusProgressEnable( true );
  hasNewMail = doProcessNewMail(interactive);
  KMBroadcastStatus::instance()->setStatusProgressEnable( false );
  KMBroadcastStatus::instance()->reset();

  signal(SIGALRM, oldHandler);
  signal(SIGPIPE, pipeHandler);
  emit finishedCheck(hasNewMail);
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::authenticate() (./kdenetwork/kmail/kmacctpop.cpp:105)

bool KMAcctPop::authenticate(DwPopClient& client)
{
  QString passwd;
  const char* msg=0;
  KMPasswdDialog* dlg;
  bool opened = FALSE;
  int replyCode;

  if(mPasswd.isEmpty() || mLogin.isEmpty())
    msg = i18n("Please set Password and Username");

  passwd = decryptStr(mPasswd);
  

  while (1)
  {
    if (msg)
    {
      dlg = new KMPasswdDialog(NULL, NULL, this, msg,
			       mLogin, passwd);
      if (!dlg->exec()) return FALSE;
      delete dlg;
      msg = 0;
    }

    // Some POP servers close the connection upon failed
    // user/password. So we close the connection here to
    // be sure that everything below runs as we expect it.
    if (opened)
    {
      client.Quit();
      client.Close();
    }
      
    // Open connection to server
    if (client.Open(mHost,mPort) != '+')
      return popError("OPEN", client);
    opened = TRUE;
    kapp->processEvents();

    // Send user name
    replyCode = client.User((const char*)mLogin);
    if (replyCode == '-')
    {
      msg = i18n("Incorrect Username");
      continue;
    }
    else if (replyCode != '+')
      return popError("USER", client);
    kapp->processEvents();

    // Send password
    passwd = decryptStr(mPasswd);
    
    replyCode = client.Pass((const char*)passwd);
    if (replyCode == '-')
    {
      msg = i18n("Incorrect Password");
      continue;
    }
    else if (replyCode != '+')
      return popError("PASS", client);

    // Ok, we are done
    break;
  }

  KMBroadcastStatus::instance()->setStatusMsg( 
		     i18n( "Transmission completed..." ));
  return TRUE;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::doProcessNewMail() (./kdenetwork/kmail/kmacctpop.cpp:179)

bool KMAcctPop::doProcessNewMail(bool /* interactive */)
{
  DwPopClient client;
  QString passwd;
  QString response, status;
  int num, size;	// number of all msgs / size of all msgs
  int id, i;		// id of message to read
  int tmout;
  int dummy;
  char dummyStr[32];
  // int replyCode; // ReplyCode need from User & Passwd call.
  KMMessage* msg;
  gotMsgs = FALSE;
  bool doFetchMsg;
  bool addedOk;   //Flag if msg was delivered succesfully

  // is everything specified ?
  kapp->processEvents();

  if (mHost.isEmpty() || mPort==0)
  {
    KMessageBox::information(0,i18n("Please specify Host, Port  and\n"
				    "destination folder in the settings\n"
				    "and try again."));
    return FALSE;
  }

  client.SetReceiveTimeout(20);

  // Handle connect, user, and password.
  if (!authenticate(client)) return FALSE;

  if (client.Stat() != '+') return popError("STAT", client);
  response = client.SingleLineResponse().c_str();
  sscanf(response.data(), "%3s %d %d", dummyStr, &num, &size);

//#warning "*** If client.Last() cannot be found then install the latest kdesupport"
  if (client.Last() == '+' && !mRetrieveAll)
  {
    response = client.SingleLineResponse().c_str();
    sscanf(response.data(), "%3s %d", dummyStr, &id);
    id++;
  }
  else id = 1;

  // workaround but still is no good. If msgs are too big in size
  // we will get a timeout.
  client.SetReceiveTimeout(40);

  addedOk = true;
 
  // do while there are mesages to take and last msg wass added succesfully
  while (id <= num && addedOk)
  {
    client.SetReceiveTimeout(40);

    if (KMBroadcastStatus::instance()->abortRequested()) {
      client.Quit();
      return gotMsgs;
    }

    KMBroadcastStatus::instance()->setStatusMsg( i18n("Message ") +
			                QString("%1/%2").arg(id).arg(num) );
    KMBroadcastStatus::instance()->setStatusProgressPercent( (id*100) / num );

    kapp->processEvents();
    if (client.List(id) != '+')
      return popError("LIST", client);
    response = client.SingleLineResponse().c_str();
    sscanf(response.data(), "%3s %d %d", dummyStr, &dummy, &size);

    doFetchMsg = TRUE;
    if (size > 4500 && !mRetrieveAll)
    {
      // If the message is large it is cheaper to first load
      // the header to check the status of the message.
      // We will have to load the entire message with the RETR
      // command below, so we will not fetch the header for
      // small messages.
      if (client.Top(id,1) != '+')
	return popError("TOP", client);
      response = client.MultiLineResponse().c_str();
      i = response.find("\nStatus:");
      if (i<0) i = response.find("\rStatus:");
      if (i>=0)
      {
	status = response.mid(i+8,32).stripWhiteSpace();
	if (strnicmp(status,"RO",2)==0 ||
	    strnicmp(status,"OR",2)==0)
	{
	  doFetchMsg=FALSE;
	  debug("message %d is old -- no need to download it", id);
	}
      }
    }

    if (doFetchMsg)
    {
      // set timeout depending on size
      tmout = size >> 8;
      if (tmout < 30) tmout = 30;
      client.SetReceiveTimeout(tmout);

      if (client.Retr(id) != '+')
      return popError("RETR", client);
      response = client.MultiLineResponse().c_str();

      msg = new KMMessage;
      msg->fromString(response,TRUE);
      if (mRetrieveAll || msg->status()!=KMMsgStatusOld)
      addedOk = processNewMsg(msg); //added ok? Error displayed if not.
      else delete msg;
    }

    // If we should delete from server _and_ we added ok then delete it
    if(!mLeaveOnServer && addedOk)
    {
      if(client.Dele(id) != '+')
	return popError("DELE",client);
      else 
	cout << client.SingleLineResponse().c_str();
    }

    gotMsgs = TRUE;
    id++;
  }
  client.Quit();

  return gotMsgs;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::popError() (./kdenetwork/kmail/kmacctpop.cpp:312)

bool KMAcctPop::popError(const QString aStage, DwPopClient& aClient) const
{
  QString msg, caption;
  kernel->kbp()->idle();

  caption = i18n("Pop Mail Error");

  // First we assume the worst: A network error
  if (aClient.LastFailure() != DwProtocolClient::kFailNoFailure)
  {
    caption = i18n("Pop Mail Network Error");
    msg = aClient.LastFailureStr();
  }

  // Maybe it is an app specific error
  else if (aClient.LastError() != DwProtocolClient::kErrNoError)
  {
    msg = aClient.LastErrorStr();
  }
  
  // Not all commands return multiLineResponses. If they do not
  // they return singleLineResponses and the multiLR command return NULL
  else
  {
    msg = aClient.MultiLineResponse().c_str();
    if (msg.isEmpty()) msg = aClient.SingleLineResponse().c_str();
    if (msg.isEmpty()) msg = i18n("Unknown error");
    // Negative response by the server e.g STAT responses '- ....'
  }

  QString tmp;
  tmp = i18n("Account: %1\nIn %2:\n%3")
		.arg(name())
		.arg(aStage)
		.arg(msg);
  KMessageBox::information(0, tmp, caption);
  //kernel->kbp()->busy();
  aClient.Quit();
  return gotMsgs;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::readConfig() (./kdenetwork/kmail/kmacctpop.cpp:355)

void KMAcctPop::readConfig(KConfig& config)
{
  KMAcctPopInherited::readConfig(config);


  mLogin = config.readEntry("login", "");
  mStorePasswd = config.readNumEntry("store-passwd", TRUE);
  if (mStorePasswd) mPasswd = config.readEntry("passwd");
  else mPasswd = "";
  mHost = config.readEntry("host");
  mPort = config.readNumEntry("port");
  mProtocol = config.readNumEntry("protocol");
  mLeaveOnServer = config.readNumEntry("leave-on-server", FALSE);
  mRetrieveAll = config.readNumEntry("retrieve-all", FALSE);
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::writeConfig() (./kdenetwork/kmail/kmacctpop.cpp:373)

void KMAcctPop::writeConfig(KConfig& config)
{
  KMAcctPopInherited::writeConfig(config);

  config.writeEntry("login", mLogin);
  config.writeEntry("store-passwd", mStorePasswd);
  if (mStorePasswd) config.writeEntry("passwd", mPasswd);
  else config.writeEntry("passwd", "");

  config.writeEntry("host", mHost);
  config.writeEntry("port", static_cast<int>(mPort));
  config.writeEntry("protocol", mProtocol);
  config.writeEntry("leave-on-server", mLeaveOnServer);
  config.writeEntry("retrieve-all", mRetrieveAll);
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::encryptStr() (./kdenetwork/kmail/kmacctpop.cpp:391)

const QString KMAcctPop::encryptStr(const QString aStr) const
{
  unsigned int i, val;
  unsigned int len = aStr.length();
  QCString result;
  result.resize(len+1);

  for (i=0; i<len; i++)
  {
    val = aStr[i] - ' ';
    val = (255-' ') - val;
    result[i] = (char)(val + ' ');
  }
  result[i] = '\0';

  return result;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::decryptStr() (./kdenetwork/kmail/kmacctpop.cpp:411)

const QString KMAcctPop::decryptStr(const QString aStr) const
{
  return encryptStr(aStr);
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setStorePasswd() (./kdenetwork/kmail/kmacctpop.cpp:418)

void KMAcctPop::setStorePasswd(bool b)
{
  mStorePasswd = b;
}

//-----------------------------------------------------------------------------

kmail'KMAcctPop::setLeaveOnServer() (./kdenetwork/kmail/kmacctpop.cpp:424)

void KMAcctPop::setLeaveOnServer(bool b)
{
  mLeaveOnServer = b;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setRetrieveAll() (./kdenetwork/kmail/kmacctpop.cpp:431)

void KMAcctPop::setRetrieveAll(bool b)
{
  mRetrieveAll = b;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setLogin() (./kdenetwork/kmail/kmacctpop.cpp:438)

void KMAcctPop::setLogin(const QString& aLogin)
{
  mLogin = aLogin;
}
//-----------------------------------------------------------------------------

kmail'KMAcctPop::passwd() (./kdenetwork/kmail/kmacctpop.cpp:443)

const QString KMAcctPop::passwd(void) const
{
  return decryptStr(mPasswd);
}

//-----------------------------------------------------------------------------

kmail'KMAcctPop::setPasswd() (./kdenetwork/kmail/kmacctpop.cpp:449)

void KMAcctPop::setPasswd(const QString& aPasswd, bool aStoreInConfig)
{
  mPasswd = encryptStr(aPasswd);
  mStorePasswd = aStoreInConfig;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setHost() (./kdenetwork/kmail/kmacctpop.cpp:457)

void KMAcctPop::setHost(const QString& aHost)
{
  mHost = aHost;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setPort() (./kdenetwork/kmail/kmacctpop.cpp:464)

void KMAcctPop::setPort(unsigned short int aPort)
{
  mPort = aPort;
}


//-----------------------------------------------------------------------------

kmail'KMAcctPop::setProtocol() (./kdenetwork/kmail/kmacctpop.cpp:471)

bool KMAcctPop::setProtocol(short aProtocol)
{
  //assert(aProtocol==2 || aProtocol==3);
  if(aProtocol != 2 || aProtocol != 3)
    return false;
  mProtocol = aProtocol;
  return true;
}


//=============================================================================
//
//  Class  KMPasswdDialog
//
//=============================================================================