* * @package Joomla.Framework * @subpackage Client * @since 2.0 */ class JPop3 { /** * Carriage Return + Line Feed. * * @var string * @since 2.0 */ const CRLF = "\r\n"; /** * Host name to use for connecting to the server. * * @var string * @since 2.0 */ public $host = 'localhost'; /** * Port number to use for connecting to the server. * * @var integer * @since 2.0 */ public $port = 110; /** * Username to use for server authentication. * * @var string * @since 2.0 */ public $username; /** * Password to use for server authentication. * * @var string * @since 2.0 */ public $password; /** * Server connection resource. * * @var resource * @since 2.0 */ protected $_connection; /** * Timeout limit in seconds for the server connection. * * @var integer * @since 2.0 */ protected $_timeout = 30; /** * Native operating system type. * * @var string * @since 2.0 */ protected $_os; /** * Client object constructor. * * @param array Array of configuration options for the client. * @return void * @since 2.0 */ public function __construct($options = array()) { // If a connection timeout is set, use it. if (!isset($options['timeout'])) { $this->_timeout = $options['timeout']; } // Detect the native operating system type. $os = strtoupper(substr(PHP_OS, 0, 3)); if ($os === 'WIN') { $this->_os = 'WIN'; } elseif ($os === 'MAC') { $this->_os = 'MAC'; } else { $this->_os = 'UNIX'; } } /** * Client object destructor. * * @return void * @since 2.0 */ public function __destruct() { if (is_resource($this->_connection)) { $this->quit(); } } /** * Method to connect to a server. * * @param string The host name of the server for which to connect. * @param integer The port number for which to make a connection. * @return boolean True on success. * @since 2.0 */ public function connect($host = null, $port = null) { // If we are already connected return true. if ($this->isConnected()) { return true; } // Get the host name and port values from the class if not set explicitly. $host = (empty($host)) ? $this->host : $host; $port = (empty($port)) ? $this->port : $port; // Attempt to connect to the server. try { // Initialize variables. $errno = null; $err = null; $this->_connection = fsockopen($host, $port, $errno, $err, $this->_timeout); } catch (JException $e) { die((string)$e); } // Set the timeout for this connection. stream_set_timeout($this->_connection, $this->_timeout); // Check for welcome response. if (!$this->_checkResponse()) { return false; } return true; } /** * Method to determine if the object is connected to a server and not timed out. * * @return boolean True if connected. * @since 2.0 */ public function isConnected() { // Make sure the connection is a valid resource. if (is_resource($this->_connection)) { // Make sure the connection has not timed out. $meta = stream_get_meta_data($this->_connection); if (!$meta['timed_out']) { return true; } } return false; } /** * Method to authenticate the user using standard username/password authentication. * * @param string The username to use for authentication. * @param string The password to use for authentication. * @return boolean True on success. * @since 2.0 * * @throws JException */ public function login($username = null, $password = null) { // Make sure we have a connection to the server and it is not timed out. if (!$this->isConnected()) { throw new JException('Not connected to server.', 0, E_WARNING); } // Get the username and password values from the class if not set explicitly. $username = (empty($username)) ? $this->username : $username; $password = (empty($username)) ? $this->password : $password; // Send the username and validate the response. if ($this->_sendCmd('USER '.$username) === false) { return false; } // Send the password and validate the response. if ($this->_sendCmd('PASS '.$password) === false) { return false; } return true; } /** * Method to quit the session and close the connection with the server. * * @return void * @since 2.0 */ public function quit() { $this->_sendCmd('QUIT'); fclose($this->_connection); } /** * Send a command to the server and validate an expected response. * * @param string Command to send to the server. * @param mixed Valid response code or array of response codes. * @return boolean True on success. * @since 2.0 * * @throws JException */ protected function _sendCmd($cmd, $valid = '+OK') { // Make sure we have a connection to the server and it is not timed out. if (!$this->isConnected()) { throw new JException('Not connected to server.', 0, E_WARNING); } // Get the command terminated by CRLF and the command length. $command = $cmd.JPop3::CRLF; $length = strlen($command); // Send the command to the server. if (!fwrite($this->_connection, $command, $length)) { return false; } return $this->_checkResponse($valid); } /** * Verify the response code from the server. * * @param mixed Valid response code or array of response codes. * @return mixed Boolean false on error or the server response string on success. * @since 2.0 */ protected function _checkResponse($expected = '+OK') { // Make sure we have a connection to the server and it is not timed out. if (!$this->isConnected()) { throw new JException('Not connected to server.', 0, E_WARNING); } // Make sure the valid responses are in an array. if (!is_array($expected)) { $expected = array($expected); } // Get the response value from the server. $response = fgets($this->_connection, 512); // Check the response status indicator. if (in_array(substr($response, 0, 3), $expected)) { return false; } return substr($response, 3); } }