/*
 * Copyright (c) 2000, 2001 Alex Zepeda <zipzippy@sonic.net>
 * Copyright (c) 2001 Michael Häckel <Michael@Haeckel.Net>
 * Copyright (c) 2002 Aaron J. Seigo <aseigo@olympusproject.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$Id: smtp.cc,v 1.100.2.9 2003/05/18 12:35:57 mueller Exp $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif

#include <netinet/in.h>
#include <arpa/inet.h>

#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#include <qbuffer.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qcstring.h>
#include <qglobal.h>
#include <qregexp.h>

#include <kprotocolmanager.h>
#include <kemailsettings.h>
#include <ksock.h>
#include <kdebug.h>
#include <kmdcodec.h>
#include <kinstance.h>
#include <kio/connection.h>
#include <kio/slaveinterface.h>
#include <kio/kdesasl.h>
#include <klocale.h>

#include "smtp.h"

//using namespace KIO;

extern "C" {
  int kdemain(int argc, char **argv);
} 

int kdemain(int argc, char **argv)
{
  KInstance instance("kio_smtp");

  if (argc != 4) {
    fprintf(stderr,
            "Usage: kio_smtp protocol domain-socket1 domain-socket2\n");
    exit(-1);
  }

  // We might as well allocate it on the heap.  Since there's a heap o room there..
  SMTPProtocol *slave = new SMTPProtocol( argv[2], argv[3],
					  qstricmp( argv[1], "smtps" ) == 0 );
  slave->dispatchLoop();

  delete slave;
  return 0;
}


SMTPProtocol::SMTPProtocol(const QCString & pool, const QCString & app,
                           bool useSSL)
:  TCPSlaveBase(useSSL ? 465 : 25, 
                useSSL ? "smtps" : "smtp", 
                pool, app, useSSL),
   m_iOldPort(0),
   m_opened(false),
   m_haveTLS(false),
   m_errorSent(false)
{
  //kdDebug() << "SMTPProtocol::SMTPProtocol" << endl;
}


SMTPProtocol::~SMTPProtocol()
{
  //kdDebug() << "SMTPProtocol::~SMTPProtocol" << endl;
  smtp_close();
}

void SMTPProtocol::openConnection()
{
  if (smtp_open()) {
    connected();
  } 
  else {
    closeConnection();
  }
}

void SMTPProtocol::closeConnection()
{
  smtp_close();
}

void SMTPProtocol::special(const QByteArray & /* aData */)
{
  QString result;
  if (m_haveTLS)
    result = " STARTTLS";
  if (!m_sAuthConfig.isEmpty())
    result += " " + m_sAuthConfig;
  infoMessage(result.mid(1));
  finished();
}


// Usage: smtp://smtphost:port/send?to=user@host.com&subject=blah
// If smtphost is the name of a profile, it'll use the information 
// provided by that profile.  If it's not a profile name, it'll use it as
// nature intended.
// One can also specify in the query:
// headers=0 (turns of header generation)
// to=emailaddress
// cc=emailaddress
// bcc=emailaddress
// subject=text
// profile=text (this will override the "host" setting)
// hostname=text (used in the HELO)
void SMTPProtocol::put(const KURL & url, int /*permissions */ ,
                       bool /*overwrite */ , bool /*resume */ )
{
  QStringList query = QStringList::split('&', url.query().remove(0, 1));
  QString subject = QString::fromLatin1("missing subject");
  QString profile;
  QString from;
  QString localHostname;
  QStringList recip, bcc, cc, temp_list;
  bool headers = true;

  // sort out our query string
  for (QStringList::Iterator it = query.begin(); it != query.end(); ++it)
  {
    int equalsAt = (*it).find('=');

    if (equalsAt > 0 && 
        equalsAt < (*it).length()) 
    {
      QString key = (*it).left(equalsAt);
      QString value = KURL::decode_string((*it).right((*it).length() - (equalsAt + 1)));

      if (key == "to")
      {
        recip.append(value);
      }
      else if (key == "cc")
      {
        cc.append(value);
      }
      else if (key == "bcc")
      {
        bcc.append(value);
      }
      else if (key == "headers")
      {
        headers = (value == "0");
        headers = false;
      }
      else if (key == "subject")
      {
        subject = value;
      }
      else if (key == "from")
      {
        from = value;
      }
      else if (key == "profile")
      {
        profile = value;
      }
      else if (key == "hostname")
      {
        localHostname = value;
      }
    }
  }

  KEMailSettings mset;
  KURL open_url = url;
  if (profile == QString::null) {
    //kdDebug() << "kio_smtp: Profile is null" << endl;
    QStringList profiles = mset.profiles();
    bool hasProfile = false;
    for (QStringList::Iterator it = profiles.begin(); it != profiles.end(); ++it) {
      if ((*it) == open_url.host()) {
        hasProfile = true;
        break;
      }
    }
    if (hasProfile) {
      mset.setProfile(open_url.host());
      open_url.setHost(mset.getSetting(KEMailSettings::OutServer));
      m_sUser = mset.getSetting(KEMailSettings::OutServerLogin);
      m_sPass = mset.getSetting(KEMailSettings::OutServerPass);

      if (m_sUser.isEmpty())
        m_sUser = QString::null;
      if (m_sPass.isEmpty())
        m_sPass = QString::null;
      open_url.setUser(m_sUser);
      open_url.setPass(m_sPass);
      m_sServer = open_url.host();
      m_iPort = open_url.port();
    } 
    else {
      mset.setProfile(mset.defaultProfileName());
    }
  } 
  else {
    mset.setProfile(profile);
  }

  // Check KEMailSettings to see if we've specified an E-Mail address
  // if that worked, check to see if we've specified a real name
  // and then format accordingly (either: emailaddress@host.com or
  // Real Name <emailaddress@host.com>)
  if (from.isEmpty()) {
    if (mset.getSetting(KEMailSettings::EmailAddress) != QString::null) {
      from = mset.getSetting(KEMailSettings::EmailAddress);
    } 
    else {
      error(KIO::ERR_NO_CONTENT, i18n("The sender address is missing."));
      smtp_close();
      return;
    }
  }
  from.prepend(QString::fromLatin1("MAIL FROM: <"));
  from.append(QString::fromLatin1(">"));

  if (!smtp_open(localHostname))
  {
    error(KIO::ERR_SERVICE_NOT_AVAILABLE,
          i18n("SMTPProtocol::smtp_open failed (%1)")
              .arg(open_url.path()));
    return;
  }

  if (!command(from, false))
  {
    if (!m_errorSent)
    {
      error(KIO::ERR_NO_CONTENT, i18n("The server did not accept the "
                                 "sender address.\nThe server responded: \"%1\"").arg(m_lastError));
    }

    smtp_close();
    return;
  }

  // Loop through our To and CC recipients, and send the proper
  // SMTP commands, for the benefit of the server.
  if (!PutRecipients(recip))
    return;                     // To
  if (!PutRecipients(cc))
    return;                     // Carbon Copy (CC)
  if (!PutRecipients(bcc))
    return;                     // Blind Carbon Copy (BCC)

  // Begin sending the actual message contents (most headers+body)
  if (!command(QString::fromLatin1("DATA"), false)) 
  {
    if (!m_errorSent)
    {
      error(KIO::ERR_NO_CONTENT, 
            i18n("The attempt to start sending the "
                 "message content failed.\nThe server responded: \"%1\"")
                .arg(m_lastError));
    }

    smtp_close();
    return;
  }

  if (headers) {
    if (mset.getSetting(KEMailSettings::EmailAddress) != QString::null) {
      if (mset.getSetting(KEMailSettings::RealName) != QString::null) {
        from =
            QString::fromLatin1("From: %1 <%2>\r\n").arg(mset.
                                           getSetting(KEMailSettings::
                                                      RealName))
            .arg(mset.getSetting(KEMailSettings::EmailAddress));
      } 
      else {
        from =
            QString::fromLatin1("From: %1\r\n").arg(mset.
                                      getSetting(KEMailSettings::
                                                 EmailAddress));
      }
    } 
    else {
      error(KIO::ERR_NO_CONTENT, i18n("The sender address is missing."));
      smtp_close(); // TODO: do we _really_ need to close the connection here/
      return;
    }
    write(from.latin1(), strlen(from.latin1()));

    subject = QString::fromLatin1("Subject: %1\r\n").arg(subject);
    write(subject.latin1(), strlen(subject.latin1()));

    // Write out the To header for the benefit of the mail clients
    QString header = QString::fromLatin1("To: %1\r\n");
    for (QStringList::Iterator it = recip.begin(); it != recip.end(); ++it) {
      header = header.arg(*it);
      write(header.latin1(), strlen(header.latin1()));
      header = QString::fromLatin1("To: %1\r\n");
    }

    // Write out the CC header for the benefit of the mail clients
    header = QString::fromLatin1("CC: %1\r\n");
    for (QStringList::Iterator it = cc.begin(); it != cc.end(); ++it) {
      header = header.arg(*it);
      write(header.latin1(), strlen(header.latin1()));
      header = QString::fromLatin1("CC: %1\r\n");
    }
  }

  // Loop until we got 0 (end of data)
  int result;
  QByteArray buffer;

  do {
    dataReq();                  // Request for data
    buffer.resize(0);
    result = readData(buffer);
    if (result > 0) {
      write(buffer.data(), buffer.size());
    } 
    else if (result < 0) {
      error(KIO::ERR_COULD_NOT_WRITE, open_url.path());
    }
  } while (result > 0);

  write("\r\n.\r\n", 5);
  if (getResponse(false) >= SMTP_MIN_NEGATIVE_REPLY) {
    if (!m_errorSent)
      error(KIO::ERR_NO_CONTENT, 
            i18n("The message content was not accepted.\nThe server responded: \"%1\"").arg(m_lastError));
    smtp_close();
    return;
  }

  command(QString::fromLatin1("RSET"));
  finished();
}

bool SMTPProtocol::PutRecipients(QStringList & list)
{
  QString formatted_recip = QString::fromLatin1("RCPT TO: <%1>");
  for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
    if (!command(formatted_recip.arg(*it), false)) {
      if (!m_errorSent)
      {
        error(KIO::ERR_NO_CONTENT,
              i18n("One of the recipients was not accepted.\nThe server responded: \"%1\"")
                  .arg(m_lastError));
      }

      smtp_close();
      return false;
    }
  }
  return true;
}

void SMTPProtocol::setHost(const QString & host, int port,
                           const QString & user, const QString & pass)
{
  m_sServer = host;
  m_iPort = port;
  m_sUser = user;
  m_sPass = pass;
}

int SMTPProtocol::getResponse(bool handleErrors,
                              char *r_buf,
                              unsigned int r_len)
{
  char *buf = 0;
  ssize_t recv_len = 0, len;
  int retVal;
  m_lastError.truncate(0);
  m_errorSent = false;

  // Give the buffer the appropiate size
  // a buffer of less than 5 bytes will *not* work
  if (r_len) {
    buf = static_cast < char *>(calloc(r_len, sizeof(char)));
    len = r_len;
  } 
  else {
    buf = static_cast < char *>(calloc(DEFAULT_RESPONSE_BUFFER, sizeof(char)));
    len = DEFAULT_RESPONSE_BUFFER;
  }

  while (recv_len < 1)
  {
    if (!waitForResponse(60))
    {
      if (handleErrors)
      {
          error(KIO::ERR_SERVER_TIMEOUT, m_sServer + QString("<<") + buf + QString(">>"));
          m_errorSent = true;
      }
      free(buf);
      return 999;
    }

    // grab the data
    recv_len = readLine(buf, len - 1);
    if ((recv_len < 1) && !isConnectionValid())
    {
      error(KIO::ERR_CONNECTION_BROKEN, m_sServer);
      m_errorSent = true;
      free(buf);
      return 999;
    }
  }

  if (recv_len < 4) {
    error(KIO::ERR_NO_CONTENT, i18n("Invalid SMTP response received."));
    m_errorSent = true;
    free(buf);
    return 999;
  }

  if (buf[3] == '-') {          // Multiline response
    char *origbuf = buf;
    while ((buf[3] == '-') && (len - recv_len > 3)) {   // Three is quite arbitrary
      buf += recv_len;
      len -= (recv_len + 1);
      waitForResponse(60);
      recv_len = readLine(buf, len - 1);
      if (recv_len < 1) {
        if (isConnectionValid())
          error(KIO::ERR_SERVER_TIMEOUT, m_sServer + " strangeness!");
        else
          error(KIO::ERR_CONNECTION_BROKEN, m_sServer);
        m_errorSent = true;
        free(buf);
        return 999;
      }
      if (recv_len < 4) {
        error(KIO::ERR_NO_CONTENT, i18n("Invalid SMTP response received."));
        m_errorSent = true;
        free(buf);
        return 999;
      }
    }

    buf = origbuf;

    int bufLen = strlen(buf);
    if (r_len) 
    {
      memcpy(r_buf, buf, bufLen);
      r_buf[r_len - 1] = '\0';
    }
    m_lastError = QCString(buf, bufLen);
  }
  else
  {
    // single line response
    if (r_len && recv_len > 4) {
      memcpy(r_buf, buf + 4, recv_len - 4);
    }
    m_lastError = QCString(buf + 4, recv_len - 4);
  }

  retVal = GetVal(buf);
  
  if (retVal == -1) {
    if (!isConnectionValid())
      error(KIO::ERR_CONNECTION_BROKEN, m_sServer);
    else
      error(KIO::ERR_NO_CONTENT,
            i18n("Invalid SMTP response received: \"%1\"").arg(m_lastError));
    m_errorSent = true;
    free(buf);
    return 999;
  }

  free(buf);
  return retVal;
}

bool SMTPProtocol::command(const QString & cmd, 
                           bool handleError,
                           char *recv_buf,
                           unsigned int len)
{
  QCString write_buf = cmd.latin1();
  write_buf += "\r\n";

  // Write the command
  if (write(static_cast < const char *>(write_buf), write_buf.length()) !=
      static_cast < ssize_t > (write_buf.length())) 
  {
    return false;
  }

  return (getResponse(handleError, recv_buf, len) < SMTP_MIN_NEGATIVE_REPLY);
}

bool SMTPProtocol::smtp_open(const QString& fakeHostname)
{
  m_haveTLS = false;
  if (m_opened && 
      m_iOldPort == port(m_iPort) &&
      m_sOldServer == m_sServer && 
      m_sOldUser == m_sUser &&
      (fakeHostname == QString::null || m_hostname == fakeHostname)) 
  {
    return true;
  } 
  else 
  {
    smtp_close();
    if (!connectToHost(m_sServer, m_iPort))
      return false;             // connectToHost has already send an error message.
    m_opened = true;
  }

  if (getResponse(false) >= SMTP_MIN_NEGATIVE_REPLY) 
  {
    if (!m_errorSent)
    {
      error(KIO::ERR_COULD_NOT_LOGIN, 
            i18n("The server did not accept the connection: \"%1\"").arg(m_lastError));
    }
    smtp_close();
    return false;
  }

  QByteArray ehloByteArray(DEFAULT_EHLO_BUFFER);
  ehloByteArray.fill(0);

  if (fakeHostname != QString::null)
  {
    m_hostname = fakeHostname;
  }
  else
  { 
    QString tmpPort;
    KSocketAddress* addr = KExtendedSocket::localAddress(m_iSock);
    KExtendedSocket::resolve(addr, m_hostname, tmpPort);
    delete addr;

    if(m_hostname == QString::null)
    {
      m_hostname = "localhost.invalid";
    }
  }

  if (!command(("EHLO " + m_hostname), false, ehloByteArray.data(), DEFAULT_EHLO_BUFFER - 1)) 
  {
    if (m_errorSent)
    {
      smtp_close();
      return false;
    }

    // Let's just check to see if it speaks plain ol' SMTP
    if (!command(("HELO " + m_hostname))) {
      if (!m_errorSent)
        error(KIO::ERR_COULD_NOT_LOGIN,
              i18n("The server responded: \"%1\"").arg(m_lastError));
      smtp_close();
      return false;
    }
  }
  // We parse the ESMTP extensions here... pipelining would be really cool
  char ehlo_line[DEFAULT_EHLO_BUFFER];
  QBuffer ehlobuf(ehloByteArray);
  if (ehlobuf.open(IO_ReadWrite)) {
    while (ehlobuf.readLine(ehlo_line, DEFAULT_EHLO_BUFFER - 1) > 0)
      ParseFeatures(const_cast < const char *>(ehlo_line));
  }

  if ((m_haveTLS && canUseTLS() && metaData("tls") != "off")
      || metaData("tls") == "on") {
    // For now we're gonna force it on.

    if (command(QString::fromLatin1("STARTTLS"))) {
      int tlsrc = startTLS();

      if (tlsrc != 1) {
        if (tlsrc != -3) {
          //kdDebug() << "TLS negotiation failed!" << endl;
          messageBox(Information,
                     i18n("Your SMTP server claims to "
                          "support TLS, but negotiation "
                          "was unsuccessful.\nYou can "
                          "disable TLS in KDE using the "
                          "crypto settings module."),
                     i18n("Connection Failed"));
        }
        smtp_close();
        return false;
      }

      /*
       * we now have TLS going
       * send our ehlo line
       * reset our features, and reparse them
       */
      //kdDebug() << "TLS has been enabled!" << endl;
      ehloByteArray.fill(0);

      if (!command("EHLO " + m_hostname, false, ehloByteArray.data(), DEFAULT_EHLO_BUFFER - 1))
      {
        if (!m_errorSent)
        {
            error(KIO::ERR_COULD_NOT_LOGIN,
                  i18n("The server responded: \"%1\"").arg(m_lastError));
        }
        smtp_close();
        return false;
      }

      m_sAuthConfig = QString::null;
      ehlobuf.close();
      ehlobuf.setBuffer(ehloByteArray);

      if (ehlobuf.open(IO_ReadWrite)) 
      {
        while (ehlobuf.readLine(ehlo_line, DEFAULT_EHLO_BUFFER - 1) > 0)
        {
           ParseFeatures(const_cast < const char *>(ehlo_line));
        }
      }
    } 
    else if (metaData("tls") == "on") {
      if (!m_errorSent)
        error(KIO::ERR_COULD_NOT_LOGIN,
              i18n("Your SMTP server does not support TLS. Disable "
                   "TLS, if you want to connect without encryption."));
      smtp_close();
      return false;
    }
  }
  // Now we try and login
  if (!m_sUser.isNull()) {
    if (m_sPass.isNull()) {
      KIO::AuthInfo authInfo;
      authInfo.username = m_sUser;
      authInfo.password = m_sPass;
      authInfo.prompt = i18n("Username and password for your SMTP account:");
      if (!openPassDlg(authInfo)) {
        error(KIO::ERR_COULD_NOT_LOGIN, i18n("When prompted, you ran away."));
        smtp_close();
        return false;
      } 
      else {
        m_sUser = authInfo.username;
        m_sPass = authInfo.password;
      }
    }
    if (!Authenticate()) {
      smtp_close();
      return false;
    }
  }

  m_iOldPort = m_iPort;
  m_sOldServer = m_sServer;
  m_sOldUser = m_sUser;
  m_sOldPass = m_sPass;

  return true;
}

bool SMTPProtocol::Authenticate()
{
  KDESasl SASL(m_sUser, m_sPass, (m_bIsSSL) ? "smtps" : "smtp");
  QString auth_method;

  // Choose available method from what the server has given us in  its greeting
  QStringList sl = QStringList::split(' ', m_sAuthConfig);
  // If the server doesn't support/require authentication, we ignore it
  if (sl.isEmpty())
    return true;
  QStrIList strList;
  if (!metaData("sasl").isEmpty())
    strList.append(metaData("sasl").latin1());
  else
    for (unsigned int i = 0; i < sl.count(); i++)
      strList.append(sl[i].latin1());

  auth_method = SASL.chooseMethod(strList);

  // If none are available, set it up so we can start over again
  if (auth_method == QString::null) 
  {
    //kdDebug() << "kio_smtp: no authentication available" << endl;
    error(KIO::ERR_COULD_NOT_LOGIN,
          i18n("No compatible authentication methods found."));
    return false;
  }
  else 
  {
    char challenge[2049];
    bool ret = false;
    QByteArray ba;
    QString cmd = QString::fromLatin1("AUTH ") + auth_method;

    if (auth_method == "PLAIN")
    {
      KCodecs::base64Encode(SASL.getBinaryResponse(ba, false), ba);
      cmd += ' ' + QCString( ba, ba.size()+1 );
    }

    if (!command(cmd, false, challenge, 2049)) 
    {
      if (!m_errorSent)
      {
        error(KIO::ERR_COULD_NOT_LOGIN,
              i18n("Your SMTP server doesn't support %1.\n"
                   "Choose a different authentication method.")
                   .arg(auth_method));
      }
      return false;
    }

    if (auth_method == "PLAIN")
    {
      ret = true;
    }
    else
    {
      ba.duplicate(challenge, strlen(challenge));
      cmd = SASL.getResponse(ba);

      ret = command(cmd, true, challenge, 2049);
      if (ret && (auth_method == "DIGEST-MD5" || auth_method == "LOGIN"))
      {
        ba.duplicate(challenge, strlen(challenge));
        cmd = SASL.getResponse(ba);
        ret = command(cmd);
      }
    }

    if (!ret && !m_errorSent)
    {
      error(KIO::ERR_COULD_NOT_LOGIN,
            i18n
            ("Authentication failed.\nMost likely the password is wrong.\nThe server responded: \"%1\"").
            arg(m_lastError));
    }

    return ret;
  }
  return false;
}

void SMTPProtocol::ParseFeatures(const char* buf)
{
  // We want it to be between 250 and 259 inclusive, and it needs to be "nnn-blah" or "nnn blah"
  // So sez the SMTP spec..
  if ((buf[0] != '2') || (buf[1] != '5') || (!isdigit(buf[2])) ||
      ((buf[3] != '-') && (buf[3] != ' ')))
    return;                     // We got an invalid line..

  if (qstrnicmp(&buf[4], "AUTH", strlen("AUTH")) == 0) {  // Look for auth stuff
    if (m_sAuthConfig == QString::null)
      m_sAuthConfig = &buf[5 + strlen("AUTH")];
    m_sAuthConfig.replace(QRegExp("[\r\n]"), "");
  } 
  else if (qstrnicmp(&buf[4], "STARTTLS", strlen("STARTTLS")) == 0) {
    m_haveTLS = true;
  }
}

void SMTPProtocol::smtp_close()
{
  if (!m_opened)                  // We're already closed
    return;

  command(QString::fromLatin1("QUIT"));
  closeDescriptor();
  m_sOldServer = QString::null;
  m_sOldUser = QString::null;
  m_sOldPass = QString::null;
  
  m_sAuthConfig = QString::null;
  m_opened = false;
}

void SMTPProtocol::stat(const KURL & url)
{
  QString path = url.path();
  error(KIO::ERR_DOES_NOT_EXIST, url.path());
}

int SMTPProtocol::GetVal(char *buf)
{
  bool ok;
  QCString st(buf, 4);
  int val = st.toInt(&ok);
  return (ok) ? val : -1;
}

