<?php

/*
 * This file is part of SwiftMailer.
 * (c) 2004-2009 Chris Corbyn
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

//@require 'Swift/TransportException.php';
//@require 'Swift/Transport/EsmtpHandler.php';
//@require 'Swift/Transport/SmtpAgent.php';

/**
 * An ESMTP handler for AUTH support.
 * @package Swift
 * @subpackage Transport
 * @author Chris Corbyn
 */
class Swift_Transport_Esmtp_AuthHandler implements Swift_Transport_EsmtpHandler
{
  
  /**
   * Authenticators available to process the request.
   * @var Swift_Transport_Esmtp_Authenticator[]
   * @access private
   */
  private $_authenticators = array();
  
  /**
   * The username for authentication.
   * @var string
   * @access private
   */
  private $_username;
  
  /**
   * The password for authentication.
   * @var string
   * @access private
   */
  private $_password;
  
  /**
   * The auth mode for authentication.
   * @var string
   * @access private
   */
  private $_auth_mode;
  
  /**
   * The ESMTP AUTH parameters available.
   * @var string[]
   * @access private
   */
  private $_esmtpParams = array();
  
  /**
   * Create a new AuthHandler with $authenticators for support.
   * @param Swift_Transport_Esmtp_Authenticator[] $authenticators
   */
  public function __construct(array $authenticators)
  {
    $this->setAuthenticators($authenticators);
  }
  
  /**
   * Set the Authenticators which can process a login request.
   * @param Swift_Transport_Esmtp_Authenticator[] $authenticators
   */
  public function setAuthenticators(array $authenticators)
  {
    $this->_authenticators = $authenticators;
  }
  
  /**
   * Get the Authenticators which can process a login request.
   * @return Swift_Transport_Esmtp_Authenticator[]
   */
  public function getAuthenticators()
  {
    return $this->_authenticators;
  }
  
  /**
   * Set the username to authenticate with.
   * @param string $username
   */
  public function setUsername($username)
  {
    $this->_username = $username;
  }
  
  /**
   * Get the username to authenticate with.
   * @return string
   */
  public function getUsername()
  {
    return $this->_username;
  }
  
  /**
   * Set the password to authenticate with.
   * @param string $password
   */
  public function setPassword($password)
  {
    $this->_password = $password;
  }
  
  /**
   * Get the password to authenticate with.
   * @return string
   */
  public function getPassword()
  {
    return $this->_password;
  }
  
  /**
   * Set the auth mode to use to authenticate.
   * @param string $mode
   */
  public function setAuthMode($mode)
  {
    $this->_auth_mode = $mode;
  }
  
  /**
   * Get the auth mode to use to authenticate.
   * @return string
   */
  public function getAuthMode()
  {
    return $this->_auth_mode;
  }
  
  /**
   * Get the name of the ESMTP extension this handles.
   * @return boolean
   */
  public function getHandledKeyword()
  {
    return 'AUTH';
  }
  
  /**
   * Set the parameters which the EHLO greeting indicated.
   * @param string[] $parameters
   */
  public function setKeywordParams(array $parameters)
  {
    $this->_esmtpParams = $parameters;
  }
  
  /**
   * Runs immediately after a EHLO has been issued.
   * @param Swift_Transport_SmtpAgent $agent to read/write
   */
  public function afterEhlo(Swift_Transport_SmtpAgent $agent)
  {
    if ($this->_username)
    {
      $count = 0;
      foreach ($this->_getAuthenticatorsForAgent() as $authenticator)
      {
        if (in_array(strtolower($authenticator->getAuthKeyword()),
          array_map('strtolower', $this->_esmtpParams)))
        {
          $count++;
          if ($authenticator->authenticate($agent, $this->_username, $this->_password))
          {
            return;
          }
        }
      }
      throw new Swift_TransportException(
        'Failed to authenticate on SMTP server with username "' .
        $this->_username . '" using ' . $count . ' possible authenticators'
        );
    }
  }
  
  /**
   * Not used.
   */
  public function getMailParams()
  {
    return array();
  }
  
  /**
   * Not used.
   */
  public function getRcptParams()
  {
    return array();
  }
  
  /**
   * Not used.
   */
  public function onCommand(Swift_Transport_SmtpAgent $agent,
    $command, $codes = array(), &$failedRecipients = null, &$stop = false)
  {
  }
    
  /**
   * Returns +1, -1 or 0 according to the rules for usort().
   * This method is called to ensure extensions can be execute in an appropriate order.
   * @param string $esmtpKeyword to compare with
   * @return int
   */
  public function getPriorityOver($esmtpKeyword)
  {
    return 0;
  }
  
  /**
   * Returns an array of method names which are exposed to the Esmtp class.
   * @return string[]
   */
  public function exposeMixinMethods()
  {
    return array('setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode');
  }
  
  /**
   * Not used.
   */
  public function resetState()
  {
  }
  
  // -- Protected methods
  
  /**
   * Returns the authenticator list for the given agent.
   * @param  Swift_Transport_SmtpAgent $agent
   * @return array
   * @access protected
   */
  protected function _getAuthenticatorsForAgent()
  {
    if (!$mode = strtolower($this->_auth_mode))
    {
      return $this->_authenticators;
    }

    foreach ($this->_authenticators as $authenticator)
    {
      if (strtolower($authenticator->getAuthKeyword()) == $mode)
      {
        return array($authenticator);
      }
    }

    throw new Swift_TransportException('Auth mode '.$mode.' is invalid');
  }
}
