/***************************************************************************
    smb4kpasswordhandler  -  This class handles the passwords for Smb4K.
                             -------------------
    begin                : So Jan 16 2005
    copyright            : (C) 2005-2007 by Alexander Reinholdt
    email                : dustpuppy@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   General Public License for more details.                              *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,   *
 *   MA  02110-1301 USA                                                    *
 ***************************************************************************/


// TQt includes
#include <tqframe.h>
#include <tqlayout.h>
#include <tqstring.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqdir.h>
#include <tqfile.h>
#include <tqstringlist.h>

// KDE includes
#include <tdelocale.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kcombobox.h>
#include <kdebug.h>
#include <tdeapplication.h>
#include <dcopclient.h>

#ifdef __FreeBSD__
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#endif

// application specific includes
#include "smb4kpasswordhandler.h"
#include "smb4kdefs.h"
#include "smb4kerror.h"
#include "smb4kauthinfo.h"
#include "smb4ksettings.h"


#ifndef __FreeBSD__
Smb4KPasswordHandler::Smb4KPasswordHandler( Smb4KHomesSharesHandler *handler, TQObject *parent, const char *name )
: TQObject( parent, name ), m_handler( handler ), m_wallet_support_disabled( false )
#else
Smb4KPasswordHandler::Smb4KPasswordHandler( Smb4KHomesSharesHandler *s_handler, Smb4KSambaOptionsHandler *o_handler, TQObject *parent, const char *name )
: TQObject( parent, name ), m_handler( s_handler ), m_options_handler( o_handler ),
  m_wallet_support_disabled( false )
#endif
{
  if ( !m_handler )
  {
    kdFatal() << "Smb4KPasswordHandler: No Smb4KHomesSharesHandler object" << endl;
  }

#ifdef __FreeBSD__
  if ( !m_options_handler )
  {
    kdFatal() << "Smb4KPasswordHandler: No Smb4KSambaOptionsHandler object" << endl;
  }
#endif

  m_auth = NULL;
  m_dlg = NULL;
  m_wallet = NULL;
  m_temp_auth = NULL;
}


Smb4KPasswordHandler::~Smb4KPasswordHandler()
{
  for ( TQValueList<Smb4KAuthInfo *>::Iterator it = m_auth_list.begin(); it != m_auth_list.end(); ++it )
  {
    delete *it;
  }

  m_auth_list.clear();

  delete m_wallet;
}


void Smb4KPasswordHandler::open_close_wallet()
{
  if ( Smb4KSettings::useWallet() && !walletSupportIsDisabled() )
  {
    if ( !walletIsOpen() )
    {
      // Start the wallet manager before accessing the wallet. We
      // do not care about the return value, because we do not do
      // error handling here.
      if ( kapp )
      {
        (void) kapp->tdeinitExec( "tdewalletmanager" );
      }
      else
      {
        // Do nothing. --- Good luck!
      }

      m_wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet(), 0, TDEWallet::Wallet::Synchronous );

      if ( m_wallet )
      {
        if ( !m_wallet->hasFolder( "Smb4K" ) )
        {
          m_wallet->createFolder( "Smb4K" );
          m_wallet->setFolder( "Smb4K" );
        }
        else
        {
          m_wallet->setFolder( "Smb4K" );

          convert_old_entries();
        }
      }
      else
      {
        Smb4KError::error( ERROR_OPENING_WALLET_FAILED, TDEWallet::Wallet::NetworkWallet(), TQString() );

        delete m_wallet;
        m_wallet = NULL;

        m_wallet_support_disabled = true;
      }
    }
    else
    {
      convert_old_entries();
    }
  }
  else
  {
    if ( m_wallet )
    {
      delete m_wallet;
      m_wallet = NULL;
    }
  }
}


void Smb4KPasswordHandler::convert_old_entries()
{
  // Convert old entries (Smb4K 0.9.2 and earlier) to the
  // new map based format.
  if ( !m_wallet->entryList().isEmpty() )
  {
    TQStringList entries = m_wallet->entryList();

    // Since in the old format the keys contained a string like
    // this: HOST:USER, we only need to test whether the first
    // key contains a ":". If that's the case, we need to convert
    // the entries, otherwise we don't.
    if ( entries.first().contains( ":" ) != 0 )
    {
      for ( TQStringList::Iterator it = entries.begin(); it != entries.end(); ++it )
      {
        // Get the password.
        TQString pass;
        m_wallet->readPassword( *it, pass );

        if ( (*it).startsWith( "DEFAULT:" ) )
        {
          // Convert the data to the new format.
          TQMap<TQString,TQString> map;
          map["Login"]     = (*it).section( ":", 1, 1 );
          map["Password"]  = pass;

          m_wallet->writeMap( "DEFAULT_LOGIN", map );
        }
        else
        {
          // Convert the data to the new format.
          TQMap<TQString,TQString> map;
          map["Login"]     = (*it).section( ":", 3, 3 );
          map["Password"]  = pass;

          if ( TQString::compare( (*it).section( ":", 0, 0 ), "*" ) != 0 )
          {
            map["Workgroup"] = (*it).section( ":", 0, 0 ).upper();
          }

          if ( TQString::compare( (*it).section( ":", 2, 2 ), "*" ) == 0 )
          {
            m_wallet->writeMap( (*it).section( ":", 1, 1 ).upper(), map );
          }
          else
          {
            m_wallet->writeMap( "//"+(*it).section( ":", 1, 1 ).upper()+
                                "/"+(*it).section( ":", 2, 2 ).upper(), map );
          }
        }

        // Delete the old entry.
        m_wallet->removeEntry( *it );
      }
    }
    else
    {
      // Do nothing.
    }
  }
  else
  {
    // Do nothing
  }
}


bool Smb4KPasswordHandler::askpass( const TQString &workgroup, const TQString &host, const TQString &share, int desc, TQWidget *parent, const char *name )
{
  // m_auth is NULL:
  m_auth = readAuth( new Smb4KAuthInfo( workgroup, host, share ) );

  // Set up the askpass dialog:
  m_dlg = new KDialogBase( KDialogBase::Plain, i18n( "Authentication" ), KDialogBase::Ok|KDialogBase::Cancel,
                           KDialogBase::Ok, parent, name, true, true );

  TQFrame *frame = m_dlg->plainPage();
  TQGridLayout *layout = new TQGridLayout( frame );
  layout->setSpacing( 5 );
  layout->setMargin( 0 );

  TQLabel *pixmap_label = new TQLabel( frame );
  pixmap_label->setPixmap( DesktopIcon( "identity" ) );
  pixmap_label->adjustSize();

  layout->addWidget( pixmap_label, 0, 0, TQt::AlignCenter );

  TQString message;

  switch ( desc )
  {
    case NewData:
      break;
    case AccessDenied:
      message = i18n( "The access was denied. " );
      break;
    case BadPassword:
      message = i18n( "The password is not correct. " );
      break;
    case PermDenied:
      message = i18n( "The permission was denied. " );
      break;
    case AuthError:
      message = i18n( "An authentication error occurred. " );
      break;
    case LogonFailure:
      message = i18n( "The logon failed. " );
      break;
    default:
      break;
  }

  if ( m_auth->share().stripWhiteSpace().isEmpty() )
  {
    message.append( i18n( "Please enter authentication data for server %1." ).arg( m_auth->host() ) );
  }
  else
  {
    message.append( i18n( "Please enter authentication data for share %1." ).arg( "//"+m_auth->host()+"/"+m_auth->share() ) );
  }

  TQLabel *message_label = new TQLabel( frame );
  message_label->setText( message.stripWhiteSpace() );
  message_label->setTextFormat( TQt::RichText );

  layout->addWidget( message_label, 0, 1, 0 );

  TQLabel *user_label = new TQLabel( i18n( "User:" ), frame );
  layout->addWidget( user_label, 1, 0, 0 );

  KLineEdit *user_edit = NULL;
  KComboBox *user_combo = NULL;

  if ( TQString::compare( m_auth->share(), "homes" ) != 0 )
  {
    user_edit = new KLineEdit( frame, "AskPassUserEdit" );
    user_edit->setMinimumWidth( 200 );
    layout->addWidget( user_edit, 1, 1, 0 );
  }
  else
  {
    user_combo = new KComboBox( frame, "AskPassUserCombo" );
    user_combo->setEditable( true );
    user_combo->setMinimumWidth( 200 );
    layout->addWidget( user_combo, 1, 1, 0 );
  }

  TQLabel *password_label = new TQLabel( i18n( "Password:" ), frame );
  layout->addWidget( password_label, 2, 0, 0 );

  KLineEdit *pass_edit = new KLineEdit( frame, "AskPassPasswordEdit" );
  pass_edit->setEchoMode( KLineEdit::Password );
  layout->addWidget( pass_edit, 2, 1, 0 );

  m_dlg->setMainWidget( frame );
  m_dlg->setFixedSize( 350, m_dlg->sizeHint().height() );
  m_dlg->enableButtonOK( false );

  // Since we have to allow empty passwords, we will only connect
  // the edit line for the user to enable/disable the OK button.
  if ( user_edit )
  {
    connect( user_edit, TQ_SIGNAL( textChanged( const TQString & ) ),
             this,      TQ_SLOT( slotEnableOKButton( const TQString& ) ) );
  }
  else
  {
    connect( user_combo, TQ_SIGNAL( textChanged( const TQString & ) ),
             this,       TQ_SLOT( slotEnableOKButton( const TQString& ) ) );
  }

  // Process the authentication data:

  if ( TQString::compare( share, "homes" ) != 0 )
  {
    user_edit->setText( m_auth->user() );
    pass_edit->setText( m_auth->password() );

    if ( m_auth->user().isEmpty() )
    {
      user_edit->setFocus();
    }
    else
    {
      pass_edit->setFocus();
    }
  }
  else
  {
    TQStringList list = m_handler->homesUsers( host );

    user_combo->insertStringList( list );
    user_combo->setCurrentText( TQString() );

    connect( user_combo, TQ_SIGNAL( activated( const TQString & ) ),
             this,       TQ_SLOT( slotGetPassword( const TQString & ) ) );

    user_combo->setFocus();
  }

  bool ok = false;

  if ( m_dlg->exec() == KDialogBase::Accepted )
  {
    if ( TQString::compare( share, "homes" ) != 0 )
    {
      TQString user = user_edit->text();
      TQString pass = pass_edit->text();

      m_auth->setUser( user );
      m_auth->setPassword( pass );

      writeAuth( m_auth );
    }
    else
    {
      TQString user = user_combo->currentText();
      TQString pass = pass_edit->text();

      m_auth->setUser( user );
      m_auth->setPassword( pass );

      writeAuth( m_auth );
    }

    ok = true;
  }

  // Clean up:

  delete m_dlg;
  m_dlg = NULL;

  delete m_auth;
  m_auth = NULL;

  return ok;
}


Smb4KAuthInfo *Smb4KPasswordHandler::readAuth( Smb4KAuthInfo *authInfo )
{
  // Do nothing, if authInfo is NULL:
  if ( !authInfo )
  {
    return authInfo;
  }

  open_close_wallet();

  if ( walletIsOpen() )
  {
    // Get the authentication information from the wallet.
    // Always prefer either the exact match or the information
    // that was provided for the host.
    TQMap<TQString,TQString> map;

    if ( !authInfo->share().isEmpty() )
    {
      m_wallet->readMap( "//"+authInfo->host().upper()+"/"+authInfo->share().upper(), map );

      if ( map.isEmpty() )
      {
        m_wallet->readMap( authInfo->host().upper(), map );

        if ( map.isEmpty() )
        {
          if ( Smb4KSettings::useDefaultLogin() )
          {
            m_wallet->readMap( "DEFAULT_LOGIN", map );

            if ( map.isEmpty() )
            {
              return authInfo;
            }
            else
            {
              // We have authentication information.
              // So, do nothing here.
            }
          }
          else
          {
            return authInfo;
          }
        }
        else
        {
          // Check that the workgroup is correct.
          if ( map.contains( "Workgroup" ) && !authInfo->workgroup().isEmpty() )
          {
            if ( TQString::compare( map["Workgroup"].upper(), authInfo->workgroup().upper() ) != 0 )
            {
              return authInfo;
            }
            else
            {
              // Everything is OK. Do nothing.
            }
          }
          else
          {
            // We cannot check if the workgroup is OK. So, just return
            // the authentication information we just collected. If it
            // should be wrong, the user will be asked to provide the
            // correct data anyway.
          }
        }
      }
      else
      {
        // Check that the workgroup is correct.
        if ( map.contains( "Workgroup" ) && !authInfo->workgroup().isEmpty() )
        {
          if ( TQString::compare( map["Workgroup"].upper(), authInfo->workgroup().upper() ) != 0 )
          {
            return authInfo;
          }
          else
          {
            // Everything is OK. Do nothing.
          }
        }
        else
        {
          // We cannot check if the workgroup is OK. So, just process
          // the authentication information we just collected. If it
          // should be wrong, the user will be asked to provide the
          // correct data anyway.
        }
      }
    }
    else
    {
      m_wallet->readMap( authInfo->host().upper(), map );

      if ( map.isEmpty() )
      {
        if ( Smb4KSettings::useDefaultLogin() )
        {
          m_wallet->readMap( "DEFAULT_LOGIN", map );

          if ( map.isEmpty() )
          {
            return authInfo;
          }
        }
        else
        {
          return authInfo;
        }
      }
      else
      {
        // Check that the workgroup is correct.
        if ( map.contains( "Workgroup" ) && !authInfo->workgroup().isEmpty() )
        {
          if ( TQString::compare( map["Workgroup"].upper(), authInfo->workgroup().upper() ) != 0 )
          {
            return authInfo;
          }
          else
          {
            // Everything is OK. Do nothing.
          }
        }
        else
        {
          // We cannot check if the workgroup is OK. So, just process
          // the authentication information we just collected. If it
          // should be wrong, the user will be asked to provide the
          // correct data anyway.
        }
      }
    }

    // We have authentication information. Put the data into the
    // Smb4KAuthInfo object.
    authInfo->setUser( map["Login"] );
    authInfo->setPassword( map["Password"] );
  }
  else
  {
    // Either the opening of the wallet failed or the user does
    // not want to use a wallet.
    // Let's see if we can get the authentication information from
    // the temporary list.
    if ( Smb4KSettings::rememberPasswords() )
    {
      if ( !m_auth_list.isEmpty() )
      {
        for ( TQValueList<Smb4KAuthInfo *>::Iterator it = m_auth_list.begin(); it != m_auth_list.end(); ++it )
        {
          if ( !authInfo->share().isEmpty() )
          {
            if ( TQString::compare( authInfo->host().upper(), (*it)->host().upper() ) == 0 &&
                 TQString::compare( authInfo->share().upper(), (*it)->share().upper() ) == 0 )
            {
              if ( TQString::compare( authInfo->workgroup().upper(), (*it)->workgroup().upper() ) == 0 ||
                   (*it)->workgroup().isEmpty() )
              {
                // Either the workgroup is OK, or we cannot check if it is OK.
                // In both cases we process the data at hand.
                authInfo->setUser( (*it)->user() );
                authInfo->setPassword( (*it)->password() );

                // Exact match. Stop here.
                break;
              }
              else
              {
                continue;
              }
            }
            else if ( TQString::compare( authInfo->host().upper(), (*it)->host().upper() ) == 0 )
            {
              if ( TQString::compare( authInfo->workgroup().upper(), (*it)->workgroup().upper() ) == 0 ||
                   (*it)->workgroup().isEmpty() )
              {
                // Either the workgroup is OK, or we cannot check if it is OK.
                // In both cases we process the data at hand.
                authInfo->setUser( (*it)->user() );
                authInfo->setPassword( (*it)->password() );

                // Because we always prefer the exact match, we keep
                // on searching.
                continue;
              }
              else
              {
                continue;
              }
            }
            else
            {
              continue;
            }
          }
          else
          {
            if ( TQString::compare( authInfo->host().upper(), (*it)->host().upper() ) == 0 )
            {
              if ( TQString::compare( authInfo->workgroup().upper(), (*it)->workgroup().upper() ) == 0 ||
                   (*it)->workgroup().isEmpty() )
              {
                // Either the workgroup is OK, or we cannot check if it is OK.
                // In both cases we process the data at hand.
                authInfo->setUser( (*it)->user() );
                authInfo->setPassword( (*it)->password() );

                break;
              }
              else
              {
                continue;
              }
            }
            else
            {
              continue;
            }
          }
        }
      }
      else
      {
        // Do nothing
      }
    }
    else
    {
      if ( m_temp_auth )
      {
        authInfo->setUser( m_temp_auth->user() );
        authInfo->setPassword( m_temp_auth->password() );

        delete m_temp_auth;
        m_temp_auth = NULL;
      }
    }
  }

#ifdef __FreeBSD__

  writeToSMBConfFile( authInfo );

#endif

  return authInfo;
}


void Smb4KPasswordHandler::writeAuth( Smb4KAuthInfo *authInfo )
{
  open_close_wallet();

  if ( walletIsOpen() )
  {
    TQMap<TQString,TQString> map;
    map["Login"]       = authInfo->user();
    map["Password"]    = authInfo->password();

    if ( !authInfo->workgroup().isEmpty() )
    {
      map["Workgroup"] = authInfo->workgroup().upper();
    }

    if ( !authInfo->share().isEmpty() )
    {
      m_wallet->writeMap( "//"+authInfo->host().upper()+"/"+authInfo->share().upper(), map );
    }
    else
    {
      m_wallet->writeMap( authInfo->host().upper(), map );
    }

    m_wallet->sync();
  }
  else
  {
    if ( Smb4KSettings::rememberPasswords() )
    {
      Smb4KAuthInfo *tmp = NULL;

      for ( TQValueList<Smb4KAuthInfo *>::Iterator it = m_auth_list.begin(); it != m_auth_list.end(); ++it )
      {
        if ( ((*it)->workgroup().isEmpty() ||
             TQString::compare( (*it)->workgroup().upper(), authInfo->workgroup().upper() ) == 0) &&
             TQString::compare( (*it)->host().upper(), authInfo->host().upper() ) == 0 &&
             TQString::compare( (*it)->host().upper(), authInfo->share().upper() ) == 0 )
        {
          tmp = *it;

          break;
        }
        else
        {
          continue;
        }
      }

      if ( tmp )
      {
        delete tmp;
      }

      m_auth_list.append( new Smb4KAuthInfo( *authInfo ) );
    }
    else
    {
      if ( !m_temp_auth )
      {
        m_temp_auth = new Smb4KAuthInfo( *authInfo );
      }
    }
  }

#ifdef __FreeBSD__

  writeToSMBConfFile( authInfo );

#endif
}


Smb4KAuthInfo *Smb4KPasswordHandler::readDefaultAuth( Smb4KAuthInfo *authInfo )
{
  if ( !authInfo )
  {
    return authInfo;
  }

  open_close_wallet();

  if ( walletIsOpen() )
  {
    // Read the default authentication information.
    TQMap<TQString,TQString> map;

    m_wallet->readMap( "DEFAULT_LOGIN", map );

    if ( !map.isEmpty() )
    {
      authInfo->setUser( map["Login"] );
      authInfo->setPassword( map["Password"] );
    }
    else
    {
      // Do nothing
    }
  }
  else
  {
    // Nothing to do.
  }

  return authInfo;
}


void Smb4KPasswordHandler::writeDefaultAuth( Smb4KAuthInfo *authInfo )
{
  open_close_wallet();

  if ( walletIsOpen() )
  {
    TQMap<TQString,TQString> map;
    map["Login"]    = authInfo->user();
    map["Password"] = authInfo->password();

    m_wallet->writeMap( "DEFAULT_LOGIN", map );
    m_wallet->sync();
  }
}


#ifdef __FreeBSD__

void Smb4KPasswordHandler::writeToSMBConfFile( Smb4KAuthInfo *authInfo )
{
  m_nsmbrc_auth = *authInfo;

  TDEProcess *p = new TDEProcess();
  p->setUseShell( true );

  connect( p,    TQ_SIGNAL( receivedStdout( TDEProcess *, char *, int ) ),
           this, TQ_SLOT( slotReceivePassword( TDEProcess *, char *, int ) ) );
  connect( p,    TQ_SIGNAL( processExited( TDEProcess * ) ),
           this, TQ_SLOT( slotWritePassword( TDEProcess * ) ) );

  *p << TQString( "smbutil crypt %1" ).arg( m_nsmbrc_auth.password() );

  p->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
}

#endif


/////////////////////////////////////////////////////////////////////////////
//  SLOT IMPLEMENTATIONS
/////////////////////////////////////////////////////////////////////////////


void Smb4KPasswordHandler::slotGetPassword( const TQString &username )
{
  if ( m_dlg && m_auth )
  {
    // We need to re-read the auth data here, because
    // of the homes shares:
    Smb4KAuthInfo *auth = readAuth( new Smb4KAuthInfo( m_auth->workgroup().upper(), m_auth->host().upper(), username ) );

    KLineEdit *lineEdit = static_cast<KLineEdit *>(  m_dlg->child( "AskPassPasswordEdit", "KLineEdit", true ) );
    lineEdit->setText( auth->password() );

    delete auth;

    m_auth->setShare( username );
  }
}


void Smb4KPasswordHandler::slotEnableOKButton( const TQString &text )
{
  if ( m_dlg )
  {
    m_dlg->enableButtonOK( !text.isEmpty() );
  }
}

#ifdef __FreeBSD__
void Smb4KPasswordHandler::slotReceivePassword( TDEProcess *, char *buffer, int buflen )
{
  m_buffer.append( TQString::fromLocal8Bit( buffer, buflen ) );
#else
void Smb4KPasswordHandler::slotReceivePassword( TDEProcess *, char *, int )
{
#endif
}


void Smb4KPasswordHandler::slotWritePassword( TDEProcess *proc )
{

  delete proc;

#ifdef __FreeBSD__

  TQString pass = m_buffer.remove( "\n" ).stripWhiteSpace();
  m_buffer = TQString();

  TQDir::setCurrent( TQDir::homeDirPath() );

  TQFile file( ".nsmbrc" );

  TQStringList contents;

  if ( file.exists() )
  {
    if ( file.open( IO_ReadOnly ) )
    {
      TQTextStream ts( &file );
      ts.setEncoding( TQTextStream::Locale );

      while ( !ts.atEnd() )
      {
        contents.append( ts.readLine().stripWhiteSpace() );
      }

      file.close();
    }
  }

  // Check if the [default] section is present.
  if ( contents.find( "[default]" ) == contents.end() &&
       contents.find( "[DEFAULT]" ) == contents.end() )
  {
    TQMap<TQString,TQString> map = m_options_handler->globalSambaOptions();
    TQString workgroup = map["workgroup"];
    TQString wins = m_options_handler->winsServer();

    TQStringList::Iterator it = contents.prepend( "[default]" );
    it++;

    if ( !workgroup.isEmpty() )
    {
      it = contents.insert( it, "workgroup="+workgroup );
    }

    if ( !wins.isEmpty() )
    {
      it = contents.insert( it, "nbns="+wins );
    }

    // FIXME: Should we write the charsets here, too??
  }

  TQString section;

  if ( m_nsmbrc_auth.share().isEmpty() )
  {
    section.append( TQString( "[%1:%2]" ).arg( m_nsmbrc_auth.host().upper(), m_nsmbrc_auth.user().isEmpty() ? "GUEST" : m_nsmbrc_auth.user().upper() ) );
  }
  else
  {
    section.append( TQString( "[%1:%2:%3]" ).arg( m_nsmbrc_auth.host().upper(), m_nsmbrc_auth.user().isEmpty() ? "GUEST" : m_nsmbrc_auth.user().upper(), m_nsmbrc_auth.share().upper() ) );
  }

  TQStringList::Iterator it = contents.find( section );

  if ( it == contents.end() )
  {
    if ( contents.last() != TQString() )
    {
      contents.append( TQString() );
    }

    contents.append( section );
    contents.append( "password="+pass );

    if ( !m_nsmbrc_auth.workgroup().isEmpty() )
    {
      contents.append( "workgroup="+m_nsmbrc_auth.workgroup() );
    }
  }
  else
  {
    for ( TQStringList::Iterator i = ++it; i != contents.end(); ++i )
    {
      if ( (*i).contains( "password=" ) )
      {
        TQString old_pass = (*i).section( "password=", 1, 1 ).stripWhiteSpace();

        if ( TQString::compare( pass, old_pass ) == 0 )
        {
          // The passwords are identical, so stop here.
          return;
        }
        else
        {
          *i = "password="+pass;
          break;
        }
      }
      else if ( (*i).startsWith( "[" ) )
      {
        break;
      }
      else
      {
        continue;
      }
    }
  }

  TQDir::setCurrent( TQDir::homeDirPath() );

  if ( file.open( IO_WriteOnly ) )
  {
    TQTextStream ts( &file );
    ts.setEncoding( TQTextStream::Locale );

    for ( TQStringList::ConstIterator it = contents.begin(); it != contents.end(); ++it )
    {
      ts << *it << endl;
    }

    file.close();
  }
  else
  {
    Smb4KError::error( ERROR_WRITING_FILE, "~/.nsmbrc", TQString() );

    return;
  }

  // Get minimal security: Fix permissions.
  TQString path = TQDir::homeDirPath()+"/"+file.name();

  int fd;

  if ( (fd = open( path.ascii(), O_WRONLY )) == -1 )
  {
    int err_no = errno;
    Smb4KError::error( ERROR_OPENING_FILE, path, strerror( err_no ) );

    return;
  }
  else
  {
    if ( fchmod( fd, 00600 ) == -1 )
    {
      // FIXME: Do we need to emit an error here at all?
    }
  }
#endif
}

#include "smb4kpasswordhandler.moc"
