cvs: pear /Net_POP3 Net_POP3_example.php POP3.php package.xml
| From: | Damian Alejandro Fernandez Sosa | Date: | Fri, 08 Apr 2005 01:23:09 +0000 |
| Subject: | cvs: pear /Net_POP3 Net_POP3_example.php POP3.php package.xml | ||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-31035@lists.php.net to get a copy of this message | ||
damian Thu Apr 7 21:23:09 2005 EDT
Modified files:
/pear/Net_POP3 Net_POP3_example.php POP3.php package.xml
Log:
RELEASE_1_3_6
http://cvs.php.net/diff.php/pear/Net_POP3/Net_POP3_example.php?r1=1.3&r2=1.4&ty=u Index: pear/Net_POP3/Net_POP3_example.php diff -u pear/Net_POP3/Net_POP3_example.php:1.3 pear/Net_POP3/Net_POP3_example.php:1.4 --- pear/Net_POP3/Net_POP3_example.php:1.3 Sat Jan 4 06:55:51 2003 +++ pear/Net_POP3/Net_POP3_example.php Thu Apr 7 21:23:06 2005 @@ -1,109 +1,157 @@ -<?php -// +-----------------------------------------------------------------------+ -// | Copyright (c) 2002-2003, Richard Heyes | -// | All rights reserved. | -// | | -// | Redistribution and use in source and binary forms, with or without | -// | modification, are permitted provided that the following conditions | -// | are met: | -// | | -// | o Redistributions of source code must retain the above copyright | -// | notice, this list of conditions and the following disclaimer. | -// | o 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.| -// | o The names of the authors may not be used to endorse or promote | -// | products derived from this software without specific prior written | -// | permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | -// | OWNER 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. | -// | | -// +-----------------------------------------------------------------------+ -// | Author: Richard Heyes <richard@phpguru.org> | -// +-----------------------------------------------------------------------+ -// -// $Id: Net_POP3_example.php,v 1.3 2003/01/04 11:55:51 mj Exp $ -?> -<html> -<body> -<?php - -include('Net_POP3.php'); - -/* -* Create the class -*/ -$pop3 =& new Net_POP3(); - -/* -* Connect to localhost on usual port -* If not given, defaults are localhost:110 -*/ -$pop3->connect('localhost', 110); - -/* -* Login using username/password. APOP will -* be tried first if supported, then basic. -*/ -$pop3->login('richard', 'Alien3'); - -/* -* Get the raw headers of message 1 -*/ -echo '<h2>getRawHeaders()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getRawHeaders(1)) . '</pre>'; - -/* -* Get structured headers of message 1 -*/ -echo '<h2>getParsedHeaders()</h2> <pre>'; -print_r($pop3->getParsedHeaders(1)); -echo '</pre>'; - -/* -* Get body of message 1 -*/ -echo '<h2>getBody()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getBody(1)) . '</pre>'; - -/* -* Get number of messages in maildrop -*/ -echo '<h2>getNumMsg</h2>'; -echo '<pre>' . $pop3->numMsg() . '</pre>'; - -/* -* Get entire message -*/ -echo '<h2>getMsg()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getMsg(1)) . '</pre>'; - -/* -* Get listing details of the maildrop -*/ -echo '<h2>getListing()</h2>'; -echo '<pre>'; -print_r($pop3->getListing()); -echo '</pre>'; - -/* -* Get size of maildrop -*/ -echo '<h2>getSize()</h2>'; -echo '<pre>' . $pop3->getSize() . '</pre>'; - -/* -* Disconnect -*/ -$pop3->disconnect(); -?> \ No newline at end of file +<?php +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002, Richard Heyes | +// | All rights reserved. | +// | | +// | Redistribution and use in source and binary forms, with or without | +// | modification, are permitted provided that the following conditions | +// | are met: | +// | | +// | o Redistributions of source code must retain the above copyright | +// | notice, this list of conditions and the following disclaimer. | +// | o 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.| +// | o The names of the authors may not be used to endorse or promote | +// | products derived from this software without specific prior written | +// | permission. | +// | | +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | +// | OWNER 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. | +// | | +// +-----------------------------------------------------------------------+ +// | Author: Richard Heyes <richard@phpguru.org> | +// | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> | +// +-----------------------------------------------------------------------+ +// +// $Id: Net_POP3_example.php,v 1.4 2005/04/08 01:23:06 damian Exp $ +?> +<html> +<body> +<?php + +include('./POP3.php'); + + + + +$user='richard'; +$pass='Alien3'; +$host='localhost'; +$port="110"; + +// you can create a file called passwords.php and store your $user,$pass,$host and $port values in it +// or you can modify this script +@include_once("./passwords.php"); + + + +// Create the class + +$pop3 =& new Net_POP3(); + + + +//$pop3->setDebug(); + +// Connect to localhost on usual port +// If not given, defaults are localhost:110 + +if(PEAR::isError( $ret= $pop3->connect($host , $port ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} + + +// Login using username/password. APOP will +// be tried first if supported, then basic. + +//$pop3->login($user , $pass , 'APOP'); +//$pop3->login($user , $pass , 'CRAM-MD5'); + +if(PEAR::isError( $ret= $pop3->login($user , $pass,'USER' ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} + +/* +if(PEAR::isError( $ret= $pop3->login($user , $pass ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} +*/ +/* +if(PEAR::isError( $ret= $pop3->login($user , $pass , 'CRAM-MD5') )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} +*/ + + +$a=$pop3->getListing(); +echo "\n"; +print_r($a); +//exit(); + + +// Get the raw headers of message 1 + +echo "<h2>getRawHeaders()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getRawHeaders(1)) . "</pre>\n"; + + +// Get structured headers of message 1 + +echo "<h2>getParsedHeaders()</h2> <pre>\n"; +print_r($pop3->getParsedHeaders(1)); +echo "</pre>\n"; + + +// Get body of message 1 + +echo "<h2>getBody()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getBody(1)) . "</pre>\n"; + + +// Get number of messages in maildrop + +echo "<h2>getNumMsg</h2>\n"; +echo "<pre>" . $pop3->numMsg() . "</pre>\n"; + + +// Get entire message + +echo "<h2>getMsg()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getMsg(1)) . "</pre>\n"; + + + + + +// Get listing details of the maildrop + +echo "<h2>getListing()</h2>\n"; +echo "<pre>\n"; +print_r($pop3->getListing()); +echo "</pre>\n"; + + +// Get size of maildrop + +echo "<h2>getSize()</h2>\n"; +echo "<pre>" . $pop3->getSize() . "</pre>\n"; + + +// Disconnect + +$pop3->disconnect(); +?> http://cvs.php.net/diff.php/pear/Net_POP3/POP3.php?r1=1.4&r2=1.5&ty=u Index: pear/Net_POP3/POP3.php diff -u pear/Net_POP3/POP3.php:1.4 pear/Net_POP3/POP3.php:1.5 --- pear/Net_POP3/POP3.php:1.4 Sat Jan 4 06:55:51 2003 +++ pear/Net_POP3/POP3.php Thu Apr 7 21:23:06 2005 @@ -1,647 +1,1226 @@ -<?php -// +-----------------------------------------------------------------------+ -// | Copyright (c) 2002-2003, Richard Heyes | -// | All rights reserved. | -// | | -// | Redistribution and use in source and binary forms, with or without | -// | modification, are permitted provided that the following conditions | -// | are met: | -// | | -// | o Redistributions of source code must retain the above copyright | -// | notice, this list of conditions and the following disclaimer. | -// | o 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.| -// | o The names of the authors may not be used to endorse or promote | -// | products derived from this software without specific prior written | -// | permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | -// | OWNER 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. | -// | | -// +-----------------------------------------------------------------------+ -// | Author: Richard Heyes <richard@phpguru.org> | -// +-----------------------------------------------------------------------+ -// -// $Id: POP3.php,v 1.4 2003/01/04 11:55:51 mj Exp $ - -require_once('Net/Socket.php'); - -/** -* +----------------------------- IMPORTANT ------------------------------+ -* | Usage of this class compared to native php extensions such as IMAP | -* | is slow and may be feature deficient. If available you are STRONGLY | -* | recommended to use the php extensions. | -* +----------------------------------------------------------------------+ -* -* POP3 Access Class -* -* For usage see the example script -*/ - -define('NET_POP3_STATE_DISCONNECTED', 1, true); -define('NET_POP3_STATE_AUTHORISATION', 2, true); -define('NET_POP3_STATE_TRANSACTION', 4, true); - -class Net_POP3 { - - /* - * Some basic information about the mail drop - * garnered from the STAT command - * - * @var array - */ - var $_maildrop; - - /* - * Used for APOP to store the timestamp - * - * @var string - */ - var $_timestamp; - - /* - * Timeout that is passed to the socket object - * - * @var integer - */ - var $_timeout; - - /* - * Socket object - * - * @var object - */ - var $_socket; - - /* - * Current state of the connection. Used with the - * constants defined above. - * - * @var integer - */ - var $_state; - - /* - * Hostname to connect to - * - * @var string - */ - var $_host; - - /* - * Port to connect to - * - * @var integer - */ - var $_port; - - /* - * Constructor. Sets up the object variables, and instantiates - * the socket object. - * - */ - function Net_POP3() - { - $this->_timestamp = ''; // Used for APOP - $this->_maildrop = array(); - $this->_timeout = 3; - $this->_state = NET_POP3_STATE_DISCONNECTED; - $this->_socket =& new Net_Socket(); - } - - /* - * Connects to the given host on the given port. - * Also looks for the timestamp in the greeting - * needed for APOP authentication - * - * @param $host Hostname/IP address to connect to - * @param $port Port to use to connect to on host - * @return bool Success/Failure - */ - function connect($host = 'localhost', $port = 110) - { - $this->_host = $host; - $this->_port = $port; - - $result = $this->_socket->connect($host, $port, false, $this->_timeout); - if ($result === true) { - $data = $this->_socket->readLine(); - if (@substr($data, 0, 3) == '+OK') { - // Check for string matching apop timestamp - if (preg_match('/<.+@.+>/U', $data, $matches)) { - $this->_timestamp = $matches[0]; - } - $this->_maildrop = array(); - $this->_state = NET_POP3_STATE_AUTHORISATION; - return true; - } - } - - $this->_socket->disconnect(); - return false; - } - - /* - * Disconnect function. Sends the QUIT command - * and closes the socket. - * - * @return bool Success/Failure - */ - function disconnect() - { - return $this->_cmdQuit(); - } - - /* - * Performs the login procedure. If there is a timestamp - * stored, APOP will be tried first, then basic USER/PASS. - * - * @param $user Username to use - * @param $pass Password to use - * @param $apop Whether to try APOP first - * @return bool Success/Failure - */ - function login($user, $pass, $apop = true) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - // Try APOP authentication first - if ($apop AND $this->_cmdApop($user, $pass)) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - - // APOP failed or not desired, use basic authentication - if ($this->_cmdUser($user) AND $this->_cmdPass($pass)) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - } - - return false; - } - - /* - * Returns the raw headers of the specified message. - * - * @param $msg_id Message number - * @return mixed Either raw headers or false on error - */ - function getRawHeaders($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdTop($msg_id, 0); - } - - return false; - } - - /* - * Returns the headers of the specified message in an - * associative array. Array keys are the header names, array - * values are the header values. In the case of multiple headers - * having the same names, eg Received:, the array value will be - * an indexed array of all the header values. - * - * @param $msg_id Message number - * @return mixed Either array of headers or false on error - */ - function getParsedHeaders($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $raw_headers = rtrim($this->getRawHeaders($msg_id)); - $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers - $raw_headers = explode("\r\n", $raw_headers); - foreach ($raw_headers as $value) { - $name = substr($value, 0, $pos = strpos($value, ':')); - $value = ltrim(substr($value, $pos + 1)); - if (isset($headers[$name]) AND is_array($headers[$name])) { - $headers[$name][] = $value; - } elseif (isset($headers[$name])) { - $headers[$name] = array($headers[$name], $value); - } else { - $headers[$name] = $value; - } - } - - return $headers; - } - - return false; - } - - /* - * Returns the body of the message with given message number. - * - * @param $msg_id Message number - * @return mixed Either message body or false on error - */ - function getBody($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $msg = $this->_cmdRetr($msg_id); - return substr($msg, strpos($msg, "\r\n\r\n")+4); - } - - return false; - } - - /* - * Returns the entire message with given message number. - * - * @param $msg_id Message number - * @return mixed Either entire message or false on error - */ - function getMsg($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdRetr($msg_id); - } - - return false; - } - - /* - * Returns the size of the maildrop - * - * @return mixed Either size of maildrop or false on error - */ - function getSize() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (isset($this->_maildrop['size'])) { - return $this->_maildrop['size']; - } else { - list(, $size) = $this->_cmdStat(); - return $size; - } - } - - return false; - } - - /* - * Returns number of messages in this maildrop - * - * @return mixed Either number of messages or false on error - */ - function numMsg() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (isset($this->_maildrop['num_msg'])) { - return $this->_maildrop['num_msg']; - } else { - list($num_msg, ) = $this->_cmdStat(); - return $num_msg; - } - } - - return false; - } - - /* - * Marks a message for deletion. Only will be deleted if the - * disconnect() method is called. - * - * @param $msg_id Message to delete - * @return bool Success/Failure - */ - function deleteMsg($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdDele($msg_id); - } - - return false; - } - - /* - * Combination of LIST/UIDL commands, returns an array - * of data - * - * @param $msg_id Optional message number - * @return mixed Array of data or false on error - */ - function getListing($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (!isset($msg_id)){ - if ($list = $this->_cmdList()) { - if ($uidl = $this->_cmdUidl()) { - foreach ($uidl as $i => $value) { - $list[$i]['uidl'] = $value['uidl']; - } - } - - return $list; - } - } else { - if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) { - return array_merge($list, $uidl); - } - } - } - - return false; - } - - /* - * Sends the USER command - * - * @param $user Username to send - * @return bool Success/Failure - */ - function _cmdUser($user) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - return (bool)$this->_sendCmd('USER ' . $user); - } - - return false; - } - - - /* - * Sends the PASS command - * - * @param $pass Password to send - * @return bool Success/Failure - */ - function _cmdPass($pass) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - return (bool)$this->_sendCmd('PASS ' . $pass); - } - - return false; - } - - - /* - * Sends the STAT command - * - * @return mixed Indexed array of number of messages and - * maildrop size, or false on error. - */ - function _cmdStat() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('STAT'); - if ($data) { - sscanf($data, '+OK %d %d', $msg_num, $size); - $this->_maildrop['num_msg'] = $msg_num; - $this->_maildrop['size'] = $size; - - return array($msg_num, $size); - } - } - - return false; - } - - - /* - * Sends the LIST command - * - * @param $msg_id Optional message number - * @return mixed Indexed array of msg_id/msg size or - * false on error - */ - function _cmdList($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (!isset($msg_id)) { - $data = $this->_sendCmd('LIST'); - if ($data) { - $data = $this->_getMultiline(); - $data = explode("\r\n", $data); - foreach ($data as $line) { - sscanf($line, '%s %s', $msg_id, $size); - $return[] = array('msg_id' => $msg_id, 'size' => $size); - } - return $return; - } - } else { - $data = $this->_sendCmd('LIST ' . $msg_id); - if ($data) { - sscanf($data, '+OK %d %d', $msg_id, $size); - return array('msg_id' => $msg_id, 'size' => $size); - } - } - } - - return false; - } - - - /* - * Sends the RETR command - * - * @param $msg_id The message number to retrieve - * @return mixed The message or false on error - */ - function _cmdRetr($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('RETR ' . $msg_id); - if ($data) { - $data = $this->_getMultiline(); - return $data; - } - } - - return false; - } - - - /* - * Sends the DELE command - * - * @param $msg_id Message number to mark as deleted - * @return bool Success/Failure - */ - function _cmdDele($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return (bool)$this->_sendCmd('DELE ' . $msg_id); - } - - return false; - } - - - /* - * Sends the NOOP command - * - * @return bool Success/Failure - */ - function _cmdNoop() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('NOOP'); - if ($data) { - return true; - } - } - - return false; - } - - /* - * Sends the RSET command - * - * @return bool Success/Failure - */ - function _cmdRset() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('RSET'); - if ($data) { - return true; - } - } - - return false; - } - - /* - * Sends the QUIT command - * - * @return bool Success/Failure - */ - function _cmdQuit() - { - $data = $this->_sendCmd('QUIT'); - $this->_state = NET_POP3_STATE_DISCONNECTED; - $this->_socket->disconnect(); - - return (bool)$data; - } - - - /* - * Sends the TOP command - * - * @param $msg_id Message number - * @param $num_lines Number of lines to retrieve - * @return mixed Message data or false on error - */ - function _cmdTop($msg_id, $num_lines) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - - $data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines); - if ($data) { - return $this->_getMultiline(); - } - } - - return false; - } - - /* - * Sends the UIDL command - * - * @param $msg_id Message number - * @return mixed indexed array of msg_id/uidl or false on error - */ - function _cmdUidl($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - - if (!isset($msg_id)) { - $data = $this->_sendCmd('UIDL'); - if ($data) { - $data = $this->_getMultiline(); - $data = explode("\r\n", $data); - foreach ($data as $line) { - sscanf($line, '%d %s', $msg_id, $uidl); - $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl); - } - - return $return; - } - } else { - - $data = $this->_sendCmd('UIDL ' . $msg_id); - sscanf($data, '+OK %d %s', $msg_id, $uidl); - return array('msg_id' => $msg_id, 'uidl' => $uidl); - } - } - - return false; - } - - /* - * Sends the APOP command - * - * @param $user Username to send - * @param $pass Password to send - * @return bool Success/Failure - */ - function _cmdApop($user, $pass) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - - if (!empty($this->_timestamp)) { - $data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)); - if ($data) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - } - } - - return false; - } - - /* - * Sends a command, checks the reponse, and - * if good returns the reponse, other wise - * returns false. - * - * @param $cmd Command to send (\r\n will be appended) - * @return mixed First line of response if successful, otherwise false - */ - function _sendCmd($cmd) - { - $result = $this->_socket->writeLine($cmd); - if (!PEAR::isError($result) AND $result) { - $data = $this->_socket->readLine(); - if (!PEAR::isError($data) AND substr($data, 0, 3) == '+OK') { - return $data; - } - } - - return false; - } - - /* - * Reads a multiline reponse and returns the data - * - * @return string The reponse. - */ - function _getMultiline() - { - $data = ''; - while(($tmp = $this->_socket->readLine()) != '.') { - if (substr($tmp, 0, 2) == '..') { - $tmp = substr($tmp, 1); - } - $data .= $tmp . "\r\n"; - } - - return substr($data, 0, -2); - } -} - -?> +<?php +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002, Richard Heyes | +// | All rights reserved. | +// | | +// | Redistribution and use in source and binary forms, with or without | +// | modification, are permitted provided that the following conditions | +// | are met: | +// | | +// | o Redistributions of source code must retain the above copyright | +// | notice, this list of conditions and the following disclaimer. | +// | o 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.| +// | o The names of the authors may not be used to endorse or promote | +// | products derived from this software without specific prior written | +// | permission. | +// | | +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | +// | OWNER 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. | +// | | +// +-----------------------------------------------------------------------+ +// | Author: Richard Heyes <richard@phpguru.org> | +// | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> | +// +-----------------------------------------------------------------------+ +// +// $Id: POP3.php,v 1.5 2005/04/08 01:23:06 damian Exp $ + +require_once('Net/Socket.php'); + + + +/** +* +----------------------------- IMPORTANT ------------------------------+ +* | Usage of this class compared to native php extensions such as IMAP | +* | is slow and may be feature deficient. If available you are STRONGLY | +* | recommended to use the php extensions. | +* +----------------------------------------------------------------------+ +* +* POP3 Access Class +* +* For usage see the example script +*/ + +define('NET_POP3_STATE_DISCONNECTED', 1, true); +define('NET_POP3_STATE_AUTHORISATION', 2, true); +define('NET_POP3_STATE_TRANSACTION', 4, true); + +class Net_POP3 { + + /* + * Some basic information about the mail drop + * garnered from the STAT command + * + * @var array + */ + var $_maildrop; + + /* + * Used for APOP to store the timestamp + * + * @var string + */ + var $_timestamp; + + /* + * Timeout that is passed to the socket object + * + * @var integer + */ + var $_timeout; + + /* + * Socket object + * + * @var object + */ + var $_socket; + + /* + * Current state of the connection. Used with the + * constants defined above. + * + * @var integer + */ + var $_state; + + /* + * Hostname to connect to + * + * @var string + */ + var $_host; + + /* + * Port to connect to + * + * @var integer + */ + var $_port; + + /** + * To allow class debuging + * @var boolean + */ + var $_debug = false; + + + /** + * The auth methods this class support + * @var array + */ + //var $supportedAuthMethods=array('DIGEST-MD5', 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); + //Disabling DIGEST-MD5 for now + var $supportedAuthMethods=array( 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); + //var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN'); + //var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN'); + + + /** + * The auth methods this class support + * @var array + */ + var $supportedSASLAuthMethods=array('DIGEST-MD5', 'CRAM-MD5'); + + + /** + * The capability response + * @var array + */ + var $_capability; + + /* + * Constructor. Sets up the object variables, and instantiates + * the socket object. + * + */ + + + function Net_POP3() + { + $this->_timestamp = ''; // Used for APOP + $this->_maildrop = array(); + $this->_timeout = 3; + $this->_state = NET_POP3_STATE_DISCONNECTED; + $this->_socket =& new Net_Socket(); + /* + * Include the Auth_SASL package. If the package is not available, + * we disable the authentication methods that depend upon it. + */ + if ((@include_once 'Auth/SASL.php') == false) { + if($this->_debug){ + echo "AUTH_SASL NOT PRESENT!\n"; + } + foreach($this->supportedSASLAuthMethods as $SASLMethod){ + $pos = array_search( $SASLMethod, $this->supportedAuthMethods ); + if($this->_debug){ + echo "DISABLING METHOD $SASLMethod\n"; + } + unset($this->supportedAuthMethods[$pos]); + } + } + + + + } + + + /** + * Handles the errors the class can find + * on the server + * + * @access private + * @return PEAR_Error + */ + + function _raiseError($msg, $code =-1) + { + include_once 'PEAR.php'; + return PEAR::raiseError($msg, $code); + } + + + + /* + * Connects to the given host on the given port. + * Also looks for the timestamp in the greeting + * needed for APOP authentication + * + * @param string $host Hostname/IP address to connect to + * @param string $port Port to use to connect to on host + * @return bool Success/Failure + */ + function connect($host = 'localhost', $port = 110) + { + $this->_host = $host; + $this->_port = $port; + + $result = $this->_socket->connect($host, $port, false, $this->_timeout); + if ($result === true) { + $data = $this->_recvLn(); + + if( $this->_checkResponse($data) ){ + // if the response begins with '+OK' ... +// if (@substr(strtoupper($data), 0, 3) == '+OK') { + // Check for string matching apop timestamp + if (preg_match('/<.+@.+>/U', $data, $matches)) { + $this->_timestamp = $matches[0]; + } + $this->_maildrop = array(); + $this->_state = NET_POP3_STATE_AUTHORISATION; + + return true; + } + } + + $this->_socket->disconnect(); + return false; + } + + /* + * Disconnect function. Sends the QUIT command + * and closes the socket. + * + * @return bool Success/Failure + */ + function disconnect() + { + return $this->_cmdQuit(); + } + + /* + * Performs the login procedure. If there is a timestamp + * stored, APOP will be tried first, then basic USER/PASS. + * + * @param string $user Username to use + * @param string $pass Password to use + * @param mixed $apop Whether to try APOP first, if used as string you can select the auth methd to use ( $pop3->login('validlogin', 'validpass', "CRAM-MD5"); + * Valid methods are: 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER' + * @return mixed true on Success/ PEAR_ERROR on error + */ + function login($user, $pass, $apop = true) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + + if(PEAR::isError($ret= $this->_cmdAuthenticate($user , $pass , $apop ) ) ){ + return $ret; + } + if( ! PEAR::isError($ret)){ + $this->_state = NET_POP3_STATE_TRANSACTION; + return true; + } + + } + return $this->_raiseError('Generic login error' , 1); + } + + + + /** + * Parses the response from the capability command. Stores + * the result in $this->_capability + * + * @access private + */ + function _parseCapability() + { + + if(!PEAR::isError($data = $this->_sendCmd('CAPA'))){ + $data = $this->_getMultiline(); + }else { + // CAPA command not supported, reset data var + // to avoid Notice errors of preg_split on an object + $data = ''; + } + $data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY); + + for ($i = 0; $i < count($data); $i++) { + + $capa=''; + if (preg_match('/^([a-z,\-]+)( ((.*))|$)$/i', $data[$i], $matches)) { + + $capa=strtolower($matches[1]); + switch ($capa) { + case 'implementation': + $this->_capability['implementation'] = $matches[3]; + break; + case 'sasl': + $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); + break; + default : + $this->_capability[$capa] = $matches[2]; + break; + } + } + } + } + + + + + /** + * Returns the name of the best authentication method that the server + * has advertised. + * + * @param string if !=null,authenticate with this method ($userMethod). + * + * @return mixed Returns a string containing the name of the best + * supported authentication method or a PEAR_Error object + * if a failure condition is encountered. + * @access private + * @since 1.0 + */ + function _getBestAuthMethod($userMethod = null) + { + +/* + return 'USER'; + return 'APOP'; + return 'DIGEST-MD5'; + return 'CRAM-MD5'; +*/ + + + $this->_parseCapability(); + + //unset($this->_capability['sasl']); + + if( isset($this->_capability['sasl']) ){ + $serverMethods=$this->_capability['sasl']; + }else{ + $serverMethods=array('USER'); + // Check for timestamp before attempting APOP + if ($this->_timestamp != null) + { + $serverMethods[] = 'APOP'; + } + } + + if($userMethod !== null && $userMethod !== true ){ + $methods = array(); + $methods[] = $userMethod; + return $userMethod; + }else{ + $methods = $this->supportedAuthMethods; + } + + if( ($methods != null) && ($serverMethods != null)){ + + foreach ( $methods as $method ) { + + if ( in_array( $method , $serverMethods ) ) { + return $method; + } + } + $serverMethods=implode(',' , $serverMethods ); + $myMethods=implode(',' ,$this->supportedAuthMethods); + return $this->_raiseError("$method NOT supported authentication method!. This server " . + "supports these methods: $serverMethods, but I support $myMethods"); + }else{ + return $this->_raiseError("This server don't support any Auth methods"); + } + } + + + + + + + /* Handles the authentication using any known method + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) ) + * + * @return mixed string or PEAR_Error + * + * @access private + * @since 1.0 + */ + function _cmdAuthenticate($uid , $pwd , $userMethod = null ) + { + + + if ( PEAR::isError( $method = $this->_getBestAuthMethod($userMethod) ) ) { + return $method; + } + + switch ($method) { + case 'DIGEST-MD5': + $result = $this->_authDigest_MD5( $uid , $pwd ); + break; + case 'CRAM-MD5': + $result = $this->_authCRAM_MD5( $uid , $pwd ); + break; + case 'LOGIN': + $result = $this->_authLOGIN( $uid , $pwd ); + break; + case 'PLAIN': + $result = $this->_authPLAIN( $uid , $pwd ); + break; + case 'APOP': + $result = $this->_cmdApop( $uid , $pwd ); + // if APOP fails fallback to USER auth + if( PEAR::isError( $result ) ){ + //echo "APOP FAILED!!!\n"; + $result=$this->_authUSER( $uid , $pwd ); + } + break; + case 'USER': + $result = $this->_authUSER( $uid , $pwd ); + break; + + + default : + $result = $this->_raiseError( "$method is not a supported authentication method" ); + break; + } + return $result; + } + + + + + /* Authenticates the user using the USER-PASS method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed true on success or PEAR_Error on failure + * + * @access private + * @since 1.0 + */ + function _authUSER($user, $pass ) + { + if ( PEAR::isError($ret=$this->_cmdUser($user) ) ){ + return $ret; + } + if ( PEAR::isError($ret=$this->_cmdPass($pass) ) ){ + return $ret; + } + return true; + } + + + + + + + + + /* Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authPLAIN($user, $pass ) + { + $cmd=sprintf('AUTH PLAIN %s', base64_encode( chr(0) . $user . chr(0) . $pass ) ); + + if ( PEAR::isError( $ret = $this->_send($cmd) ) ) { + return $ret; + } + if ( PEAR::isError( $challenge = $this->_recvLn() ) ){ + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + return true; + } + + + + /* Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authLOGIN($user, $pass ) + { + $this->_send('AUTH LOGIN'); + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + + if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($user))) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($pass))) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + return $this->_checkResponse($challenge); + } + + + + + + /* Authenticates the user using the CRAM-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authCRAM_MD5($uid, $pwd ) + { + if ( PEAR::isError( $ret = $this->_send( 'AUTH CRAM-MD5' ) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + // remove '+ ' + + $challenge=substr($challenge,2); + + $challenge = base64_decode( $challenge ); + + $cram = &Auth_SASL::factory('crammd5'); + $auth_str = base64_encode( $cram->getResponse( $uid , $pwd , $challenge ) ); + + + if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) { + return $error; + } + if ( PEAR::isError( $ret = $this->_recvLn() ) ) { + return $ret; + } + //echo "RET:$ret\n"; + return $this->_checkResponse($ret); + } + + + + /* Authenticates the user using the DIGEST-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The efective user + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authDigest_MD5($uid, $pwd) + { + if ( PEAR::isError( $ret = $this->_send( 'AUTH DIGEST-MD5' ) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + // remove '+ ' + $challenge=substr($challenge,2); + + $challenge = base64_decode( $challenge ); + $digest = &Auth_SASL::factory('digestmd5'); + $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3" )); + + if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) { + return $error; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + /* + * We don't use the protocol's third step because POP3 doesn't allow + * subsequent authentication, so we just silently ignore it. + */ + + if ( PEAR::isError( $challenge = $this->_send("\r\n") ) ) { + return $challenge ; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + + return $this->_checkResponse($challenge); + + + } + + + + + + + + + + + /* + * Sends the APOP command + * + * @param $user Username to send + * @param $pass Password to send + * @return bool Success/Failure + */ + function _cmdApop($user, $pass) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + + if (!empty($this->_timestamp)) { + if(PEAR::isError($data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)) ) ){ + return $data; + } + $this->_state = NET_POP3_STATE_TRANSACTION; + return true; + } + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State1'); + } + + + + + + + + + + + + + + + + /* + * Returns the raw headers of the specified message. + * + * @param integer $msg_id Message number + * @return mixed Either raw headers or false on error + */ + function getRawHeaders($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdTop($msg_id, 0); + } + + return false; + } + + /* + * Returns the headers of the specified message in an + * associative array. Array keys are the header names, array + * values are the header values. In the case of multiple headers + * having the same names, eg Received:, the array value will be + * an indexed array of all the header values. + * + * @param integer $msg_id Message number + * @return mixed Either array of headers or false on error + */ + function getParsedHeaders($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + $raw_headers = rtrim($this->getRawHeaders($msg_id)); + + $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers + $raw_headers = explode("\r\n", $raw_headers); + foreach ($raw_headers as $value) { + $name = substr($value, 0, $pos = strpos($value, ':')); + $value = ltrim(substr($value, $pos + 1)); + if (isset($headers[$name]) AND is_array($headers[$name])) { + $headers[$name][] = $value; + } elseif (isset($headers[$name])) { + $headers[$name] = array($headers[$name], $value); + } else { + $headers[$name] = $value; + } + } + + return $headers; + } + + return false; + } + + /* + * Returns the body of the message with given message number. + * + * @param integer $msg_id Message number + * @return mixed Either message body or false on error + */ + function getBody($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + $msg = $this->_cmdRetr($msg_id); + return substr($msg, strpos($msg, "\r\n\r\n")+4); + } + + return false; + } + + /* + * Returns the entire message with given message number. + * + * @param integer $msg_id Message number + * @return mixed Either entire message or false on error + */ + function getMsg($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdRetr($msg_id); + } + + return false; + } + + /* + * Returns the size of the maildrop + * + * @return mixed Either size of maildrop or false on error + */ + function getSize() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (isset($this->_maildrop['size'])) { + return $this->_maildrop['size']; + } else { + list(, $size) = $this->_cmdStat(); + return $size; + } + } + + return false; + } + + /* + * Returns number of messages in this maildrop + * + * @return mixed Either number of messages or false on error + */ + function numMsg() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (isset($this->_maildrop['num_msg'])) { + return $this->_maildrop['num_msg']; + } else { + list($num_msg, ) = $this->_cmdStat(); + return $num_msg; + } + } + + return false; + } + + /* + * Marks a message for deletion. Only will be deleted if the + * disconnect() method is called. + * + * @param integer $msg_id Message to delete + * @return bool Success/Failure + */ + function deleteMsg($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdDele($msg_id); + } + + return false; + } + + /* + * Combination of LIST/UIDL commands, returns an array + * of data + * + * @param integer $msg_id Optional message number + * @return mixed Array of data or false on error + */ + function getListing($msg_id = null) + { + + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (!isset($msg_id)){ + + $list=array(); + if ($list = $this->_cmdList()) { + if ($uidl = $this->_cmdUidl()) { + foreach ($uidl as $i => $value) { + $list[$i]['uidl'] = $value['uidl']; + } + } + return $list; + }else{ + return array(); + } + } else { + if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) { + return array_merge($list, $uidl); + } + } + } + + return false; + } + + /* + * Sends the USER command + * + * @param string $user Username to send + * @return bool Success/Failure + */ + function _cmdUser($user) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + return $this->_sendCmd('USER ' . $user); + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); + } + + + /* + * Sends the PASS command + * + * @param string $pass Password to send + * @return bool Success/Failure + */ + function _cmdPass($pass) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + return $this->_sendCmd('PASS ' . $pass); + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); + } + + + /* + * Sends the STAT command + * + * @return mixed Indexed array of number of messages and + * maildrop size, or false on error. + */ + function _cmdStat() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('STAT'))){ + sscanf($data, '+OK %d %d', $msg_num, $size); + $this->_maildrop['num_msg'] = $msg_num; + $this->_maildrop['size'] = $size; + + return array($msg_num, $size); + } + } + return false; + } + + + /* + * Sends the LIST command + * + * @param integer $msg_id Optional message number + * @return mixed Indexed array of msg_id/msg size or + * false on error + */ + function _cmdList($msg_id = null) + { + $return=array(); + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (!isset($msg_id)) { + if(!PEAR::isError($data = $this->_sendCmd('LIST') )){ + $data = $this->_getMultiline(); + $data = explode("\r\n", $data); + foreach ($data as $line) { + if($line !=''){ + sscanf($line, '%s %s', $msg_id, $size); + $return[] = array('msg_id' => $msg_id, 'size' => $size); + } + } + return $return; + } + } else { + if(!PEAR::isError($data = $this->_sendCmd('LIST ' . $msg_id))){ + if($data!=''){ + sscanf($data, '+OK %d %d', $msg_id, $size); + return array('msg_id' => $msg_id, 'size' => $size); + } + return array(); + } + } + } + + + return false; + } + + + /* + * Sends the RETR command + * + * @param integer $msg_id The message number to retrieve + * @return mixed The message or false on error + */ + function _cmdRetr($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('RETR ' . $msg_id) )){ + $data = $this->_getMultiline(); + return $data; + } + } + + return false; + } + + + /* + * Sends the DELE command + * + * @param integer $msg_id Message number to mark as deleted + * @return bool Success/Failure + */ + function _cmdDele($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_sendCmd('DELE ' . $msg_id); + } + + return false; + } + + + /* + * Sends the NOOP command + * + * @return bool Success/Failure + */ + function _cmdNoop() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('NOOP'))){ + return true; + } + } + + return false; + } + + /* + * Sends the RSET command + * + * @return bool Success/Failure + */ + function _cmdRset() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('RSET'))){ + return true; + } + } + + return false; + } + + /* + * Sends the QUIT command + * + * @return bool Success/Failure + */ + function _cmdQuit() + { + $data = $this->_sendCmd('QUIT'); + $this->_state = NET_POP3_STATE_DISCONNECTED; + $this->_socket->disconnect(); + + return (bool)$data; + } + + + /* + * Sends the TOP command + * + * @param integer $msg_id Message number + * @param integer $num_lines Number of lines to retrieve + * @return mixed Message data or false on error + */ + function _cmdTop($msg_id, $num_lines) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + if(!PEAR::isError($data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines))){ + return $this->_getMultiline(); + } + } + + return false; + } + + /* + * Sends the UIDL command + * + * @param integer $msg_id Message number + * @return mixed indexed array of msg_id/uidl or false on error + */ + function _cmdUidl($msg_id = null) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + if (!isset($msg_id)) { + if(!PEAR::isError($data = $this->_sendCmd('UIDL') )){ + $data = $this->_getMultiline(); + $data = explode("\r\n", $data); + foreach ($data as $line) { + sscanf($line, '%d %s', $msg_id, $uidl); + $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl); + } + + return $return; + } + } else { + + $data = $this->_sendCmd('UIDL ' . $msg_id); + sscanf($data, '+OK %d %s', $msg_id, $uidl); + return array('msg_id' => $msg_id, 'uidl' => $uidl); + } + } + + return false; + } + + + + + + + + + + /* + * Sends a command, checks the reponse, and + * if good returns the reponse, other wise + * returns false. + * + * @param string $cmd Command to send (\r\n will be appended) + * @return mixed First line of response if successful, otherwise false + */ + function _sendCmd($cmd) + { + if (PEAR::isError($result = $this->_send($cmd) )){ + return $result ; + } + + if (PEAR::isError($data = $this->_recvLn() )){ + return $data; + } + + if ( strtoupper(substr($data, 0, 3)) == '+OK') { + return $data; + } + + + return $this->_raiseError($data); + } + + /* + * Reads a multiline reponse and returns the data + * + * @return string The reponse. + */ + function _getMultiline() + { + $data = ''; + while(!PEAR::isError($tmp = $this->_recvLn() ) ) { + if($tmp == '.'){ + return substr($data, 0, -2); + } + if (substr($tmp, 0, 2) == '..') { + $tmp = substr($tmp, 1); + } + $data .= $tmp . "\r\n"; + } + return substr($data, 0, -2); + } + + + /** + * Sets the bebug state + * + * @param bool $debug + * @access public + * @return void + */ + function setDebug($debug=true) + { + $this->_debug=$debug; + } + + + + + + /** + * Send the given string of data to the server. + * + * @param string $data The string of data to send. + * + * @return mixed True on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.0 + */ + function _send($data) + { + if ($this->_debug) { + echo "C: $data\n"; + } + + if (PEAR::isError($error = $this->_socket->writeLine($data))) { + return $this->_raiseError('Failed to write to socket: ' . $error->getMessage()); + } + return true; + } + + + + /** + * Receive the given string of data from the server. + * + * @return mixed a line of response on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.0 + */ + function _recvLn() + { + if (PEAR::isError( $lastline = $this->_socket->readLine( 8192 ) ) ) { + return $this->_raiseError('Failed to write to socket: ' . $this->lastline->getMessage() ); + } + if($this->_debug){ + // S: means this data was sent by the POP3 Server + echo "S:$lastline\n" ; + } + return $lastline; + } + + /** + * Checks de server Response + * + * @param string $response the response + * @return mixed true on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.3.3 + */ + + function _checkResponse($response) + { + if (@substr(strtoupper($response), 0, 3) == '+OK') { + return true; + }else{ + if (@substr(strtoupper($response), 0, 4) == '-ERR') { + return $this->_raiseError($response); + }else{ + if (@substr(strtoupper($response), 0, 2) == '+ ') { + return true; + } + } + + } + return $this->_raiseError("Unknown Response ($response)"); + } + + + +} + +?> http://cvs.php.net/diff.php/pear/Net_POP3/package.xml?r1=1.11&r2=1.12&ty=u Index: pear/Net_POP3/package.xml diff -u pear/Net_POP3/package.xml:1.11 pear/Net_POP3/package.xml:1.12 --- pear/Net_POP3/package.xml:1.11 Sat Jul 12 04:02:02 2003 +++ pear/Net_POP3/package.xml Thu Apr 7 21:23:06 2005 @@ -1,56 +1,235 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> -<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> -<package version="1.0"> - - <name>Net_POP3</name> - <summary>Provides a POP3 class to access POP3 server.</summary> - <description> - Provides a POP3 class to access POP3 server. Support all POP3 commands - including UIDL listings and APOP authentication. - </description> - - <maintainers> - <maintainer> - <user>richard</user> - <name>Richard Heyes</name> - <email>richard@php.net</email> - <role>lead</role> - </maintainer> - </maintainers> - - <release> - <version>1.2</version> - <date>2002-07-27</date> - <state>stable</state> - <license>BSD</license> - <notes> - License change - </notes> - <filelist> - <dir name="/" baseinstalldir="Net"> - <file role="php">POP3.php</file> - <file role="php">Net_POP3_example.php</file> - </dir> - </filelist> - <deps> - <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> - </deps> - </release> - - <changelog> - - <release> - <version>1.1</version> - <date>2002-02-13</date> - <state>stable</state> - <notes> - Renamed file to POP3.php - </notes> - <deps> - <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> - </deps> - </release> - - </changelog> - -</package> +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> +<package version="1.0"> + + <name>Net_POP3</name> + <summary>Provides a POP3 class to access POP3 server.</summary> + <description> + Provides a POP3 class to access POP3 server. Support all POP3 commands + including UIDL listings, APOP authentication,DIGEST-MD5 and CRAM-MD5 using optional Auth_SASL package + </description> + + <maintainers> + <maintainer> + <user>richard</user> + <name>Richard Heyes</name> + <email>richard@php.net</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>damian</user> + <name>Damian Fernandez Sosa</name> + <email>damlists@cnba.uba.ar</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>gschlossnagle</user> + <name>George Schlossnagle</name> + <email>george@omniti.com</email> + <role>lead</role> + </maintainer> + </maintainers> + + + <release> + <version>1.3.6</version> + <date>2005-04-04</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #3551 Bug #2663 not fixed yet. +* Fixed Bug #3410 Error handling in _sendCmd +* Fixed Bug #1942 wrong parameter-type specification in Net_POP3::login +* Fixed Bug #239 Missing phpdoc tag. + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + +<changelog> + + + + + <release> + <version>1.3.5</version> + <date>2005-02-02</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #3141 $pop3->getListing() returns empty fields. thanks to culmat at gmx dot net + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + <release> + <version>1.3.4</version> + <date>2004-12-05</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #2440 thanks to erickoh at jobsfactory dot com +* Fixed Bug #2453 :Mistake in PEAR Doc for Net_POP3 example. thanks to erickoh at jobsfactory dot com +* Removed double quotes in _authLogin() fixes Bug #2454 :AUTH LOGIN user and pass need to be enclosed in double quotes?. thanks to erickoh at jobsfactory dot com +* Fixed Bug #2523 : Unable to login to Qmail servers. thanks to johann dot hoehn at ecommerce dot com +* Fixed Bug #2646 :APOP attempted when not supported. thanks to osdave at nospam_davepar dot com + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + +<release> + <version>1.3.3</version> + <date>2004-09-15</date> + <state>stable</state> + <license>BSD</license> + <notes> +* _sendCmd now return PEAR_Error on error instead of false making error check easy +* Fixes bug #2175 login() which uses DIGEST-MD5 always returns true. +* All the Login methods now uses PEAR_Error instead of 'false' finding the error cause is now easy +* Disabling DIGEST-MD5 until I can make work whit saslv2 (saslv2 and saslv1 responses are different ) + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + <release> + <version>1.3.2</version> + <date>2004-06-26</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixes bug #1505 + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + <release> + <version>1.3.1</version> + <date>2004-03-18</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Solves a bug in the auth code when the AUTH method is set to APOP but the server fall back to user and pass + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + <release> + <version>1.3</version> + <date>2004-03-03</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Added debug capabilities +* Added _recvLn() and _send($data) to support debug and better check socket errors +* Added SASL AUTH capabilities +* if installed automatically uses Auth_SASL +* Added LOGIN,PLAIN,DIGEST-MD5 and CRAM-MD5 +* Modified APOP and USER auths +* Now the class automagically selects the best auth method + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + <release> + <version>1.2</version> + <date>2002-07-27</date> + <state>stable</state> + <license>BSD</license> + <notes> + License change + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="php">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + <release> + <version>1.1</version> + <date>2002-02-13</date> + <state>stable</state> + <notes> + Renamed file to POP3.php + </notes> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + +</changelog> + +</package>
http://cvs.php.net/diff.php/pear/Net_POP3/Net_POP3_example.php?r1=1.3&r2=1.4&ty=u Index: pear/Net_POP3/Net_POP3_example.php diff -u pear/Net_POP3/Net_POP3_example.php:1.3 pear/Net_POP3/Net_POP3_example.php:1.4 --- pear/Net_POP3/Net_POP3_example.php:1.3 Sat Jan 4 06:55:51 2003 +++ pear/Net_POP3/Net_POP3_example.php Thu Apr 7 21:23:06 2005 @@ -1,109 +1,157 @@ -<?php -// +-----------------------------------------------------------------------+ -// | Copyright (c) 2002-2003, Richard Heyes | -// | All rights reserved. | -// | | -// | Redistribution and use in source and binary forms, with or without | -// | modification, are permitted provided that the following conditions | -// | are met: | -// | | -// | o Redistributions of source code must retain the above copyright | -// | notice, this list of conditions and the following disclaimer. | -// | o 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.| -// | o The names of the authors may not be used to endorse or promote | -// | products derived from this software without specific prior written | -// | permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | -// | OWNER 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. | -// | | -// +-----------------------------------------------------------------------+ -// | Author: Richard Heyes <richard@phpguru.org> | -// +-----------------------------------------------------------------------+ -// -// $Id: Net_POP3_example.php,v 1.3 2003/01/04 11:55:51 mj Exp $ -?> -<html> -<body> -<?php - -include('Net_POP3.php'); - -/* -* Create the class -*/ -$pop3 =& new Net_POP3(); - -/* -* Connect to localhost on usual port -* If not given, defaults are localhost:110 -*/ -$pop3->connect('localhost', 110); - -/* -* Login using username/password. APOP will -* be tried first if supported, then basic. -*/ -$pop3->login('richard', 'Alien3'); - -/* -* Get the raw headers of message 1 -*/ -echo '<h2>getRawHeaders()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getRawHeaders(1)) . '</pre>'; - -/* -* Get structured headers of message 1 -*/ -echo '<h2>getParsedHeaders()</h2> <pre>'; -print_r($pop3->getParsedHeaders(1)); -echo '</pre>'; - -/* -* Get body of message 1 -*/ -echo '<h2>getBody()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getBody(1)) . '</pre>'; - -/* -* Get number of messages in maildrop -*/ -echo '<h2>getNumMsg</h2>'; -echo '<pre>' . $pop3->numMsg() . '</pre>'; - -/* -* Get entire message -*/ -echo '<h2>getMsg()</h2>'; -echo '<pre>' . htmlspecialchars($pop3->getMsg(1)) . '</pre>'; - -/* -* Get listing details of the maildrop -*/ -echo '<h2>getListing()</h2>'; -echo '<pre>'; -print_r($pop3->getListing()); -echo '</pre>'; - -/* -* Get size of maildrop -*/ -echo '<h2>getSize()</h2>'; -echo '<pre>' . $pop3->getSize() . '</pre>'; - -/* -* Disconnect -*/ -$pop3->disconnect(); -?> \ No newline at end of file +<?php +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002, Richard Heyes | +// | All rights reserved. | +// | | +// | Redistribution and use in source and binary forms, with or without | +// | modification, are permitted provided that the following conditions | +// | are met: | +// | | +// | o Redistributions of source code must retain the above copyright | +// | notice, this list of conditions and the following disclaimer. | +// | o 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.| +// | o The names of the authors may not be used to endorse or promote | +// | products derived from this software without specific prior written | +// | permission. | +// | | +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | +// | OWNER 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. | +// | | +// +-----------------------------------------------------------------------+ +// | Author: Richard Heyes <richard@phpguru.org> | +// | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> | +// +-----------------------------------------------------------------------+ +// +// $Id: Net_POP3_example.php,v 1.4 2005/04/08 01:23:06 damian Exp $ +?> +<html> +<body> +<?php + +include('./POP3.php'); + + + + +$user='richard'; +$pass='Alien3'; +$host='localhost'; +$port="110"; + +// you can create a file called passwords.php and store your $user,$pass,$host and $port values in it +// or you can modify this script +@include_once("./passwords.php"); + + + +// Create the class + +$pop3 =& new Net_POP3(); + + + +//$pop3->setDebug(); + +// Connect to localhost on usual port +// If not given, defaults are localhost:110 + +if(PEAR::isError( $ret= $pop3->connect($host , $port ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} + + +// Login using username/password. APOP will +// be tried first if supported, then basic. + +//$pop3->login($user , $pass , 'APOP'); +//$pop3->login($user , $pass , 'CRAM-MD5'); + +if(PEAR::isError( $ret= $pop3->login($user , $pass,'USER' ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} + +/* +if(PEAR::isError( $ret= $pop3->login($user , $pass ) )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} +*/ +/* +if(PEAR::isError( $ret= $pop3->login($user , $pass , 'CRAM-MD5') )){ + echo "ERROR: " . $ret->getMessage() . "\n"; + exit(); +} +*/ + + +$a=$pop3->getListing(); +echo "\n"; +print_r($a); +//exit(); + + +// Get the raw headers of message 1 + +echo "<h2>getRawHeaders()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getRawHeaders(1)) . "</pre>\n"; + + +// Get structured headers of message 1 + +echo "<h2>getParsedHeaders()</h2> <pre>\n"; +print_r($pop3->getParsedHeaders(1)); +echo "</pre>\n"; + + +// Get body of message 1 + +echo "<h2>getBody()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getBody(1)) . "</pre>\n"; + + +// Get number of messages in maildrop + +echo "<h2>getNumMsg</h2>\n"; +echo "<pre>" . $pop3->numMsg() . "</pre>\n"; + + +// Get entire message + +echo "<h2>getMsg()</h2>\n"; +echo "<pre>" . htmlspecialchars($pop3->getMsg(1)) . "</pre>\n"; + + + + + +// Get listing details of the maildrop + +echo "<h2>getListing()</h2>\n"; +echo "<pre>\n"; +print_r($pop3->getListing()); +echo "</pre>\n"; + + +// Get size of maildrop + +echo "<h2>getSize()</h2>\n"; +echo "<pre>" . $pop3->getSize() . "</pre>\n"; + + +// Disconnect + +$pop3->disconnect(); +?> http://cvs.php.net/diff.php/pear/Net_POP3/POP3.php?r1=1.4&r2=1.5&ty=u Index: pear/Net_POP3/POP3.php diff -u pear/Net_POP3/POP3.php:1.4 pear/Net_POP3/POP3.php:1.5 --- pear/Net_POP3/POP3.php:1.4 Sat Jan 4 06:55:51 2003 +++ pear/Net_POP3/POP3.php Thu Apr 7 21:23:06 2005 @@ -1,647 +1,1226 @@ -<?php -// +-----------------------------------------------------------------------+ -// | Copyright (c) 2002-2003, Richard Heyes | -// | All rights reserved. | -// | | -// | Redistribution and use in source and binary forms, with or without | -// | modification, are permitted provided that the following conditions | -// | are met: | -// | | -// | o Redistributions of source code must retain the above copyright | -// | notice, this list of conditions and the following disclaimer. | -// | o 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.| -// | o The names of the authors may not be used to endorse or promote | -// | products derived from this software without specific prior written | -// | permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | -// | OWNER 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. | -// | | -// +-----------------------------------------------------------------------+ -// | Author: Richard Heyes <richard@phpguru.org> | -// +-----------------------------------------------------------------------+ -// -// $Id: POP3.php,v 1.4 2003/01/04 11:55:51 mj Exp $ - -require_once('Net/Socket.php'); - -/** -* +----------------------------- IMPORTANT ------------------------------+ -* | Usage of this class compared to native php extensions such as IMAP | -* | is slow and may be feature deficient. If available you are STRONGLY | -* | recommended to use the php extensions. | -* +----------------------------------------------------------------------+ -* -* POP3 Access Class -* -* For usage see the example script -*/ - -define('NET_POP3_STATE_DISCONNECTED', 1, true); -define('NET_POP3_STATE_AUTHORISATION', 2, true); -define('NET_POP3_STATE_TRANSACTION', 4, true); - -class Net_POP3 { - - /* - * Some basic information about the mail drop - * garnered from the STAT command - * - * @var array - */ - var $_maildrop; - - /* - * Used for APOP to store the timestamp - * - * @var string - */ - var $_timestamp; - - /* - * Timeout that is passed to the socket object - * - * @var integer - */ - var $_timeout; - - /* - * Socket object - * - * @var object - */ - var $_socket; - - /* - * Current state of the connection. Used with the - * constants defined above. - * - * @var integer - */ - var $_state; - - /* - * Hostname to connect to - * - * @var string - */ - var $_host; - - /* - * Port to connect to - * - * @var integer - */ - var $_port; - - /* - * Constructor. Sets up the object variables, and instantiates - * the socket object. - * - */ - function Net_POP3() - { - $this->_timestamp = ''; // Used for APOP - $this->_maildrop = array(); - $this->_timeout = 3; - $this->_state = NET_POP3_STATE_DISCONNECTED; - $this->_socket =& new Net_Socket(); - } - - /* - * Connects to the given host on the given port. - * Also looks for the timestamp in the greeting - * needed for APOP authentication - * - * @param $host Hostname/IP address to connect to - * @param $port Port to use to connect to on host - * @return bool Success/Failure - */ - function connect($host = 'localhost', $port = 110) - { - $this->_host = $host; - $this->_port = $port; - - $result = $this->_socket->connect($host, $port, false, $this->_timeout); - if ($result === true) { - $data = $this->_socket->readLine(); - if (@substr($data, 0, 3) == '+OK') { - // Check for string matching apop timestamp - if (preg_match('/<.+@.+>/U', $data, $matches)) { - $this->_timestamp = $matches[0]; - } - $this->_maildrop = array(); - $this->_state = NET_POP3_STATE_AUTHORISATION; - return true; - } - } - - $this->_socket->disconnect(); - return false; - } - - /* - * Disconnect function. Sends the QUIT command - * and closes the socket. - * - * @return bool Success/Failure - */ - function disconnect() - { - return $this->_cmdQuit(); - } - - /* - * Performs the login procedure. If there is a timestamp - * stored, APOP will be tried first, then basic USER/PASS. - * - * @param $user Username to use - * @param $pass Password to use - * @param $apop Whether to try APOP first - * @return bool Success/Failure - */ - function login($user, $pass, $apop = true) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - // Try APOP authentication first - if ($apop AND $this->_cmdApop($user, $pass)) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - - // APOP failed or not desired, use basic authentication - if ($this->_cmdUser($user) AND $this->_cmdPass($pass)) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - } - - return false; - } - - /* - * Returns the raw headers of the specified message. - * - * @param $msg_id Message number - * @return mixed Either raw headers or false on error - */ - function getRawHeaders($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdTop($msg_id, 0); - } - - return false; - } - - /* - * Returns the headers of the specified message in an - * associative array. Array keys are the header names, array - * values are the header values. In the case of multiple headers - * having the same names, eg Received:, the array value will be - * an indexed array of all the header values. - * - * @param $msg_id Message number - * @return mixed Either array of headers or false on error - */ - function getParsedHeaders($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $raw_headers = rtrim($this->getRawHeaders($msg_id)); - $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers - $raw_headers = explode("\r\n", $raw_headers); - foreach ($raw_headers as $value) { - $name = substr($value, 0, $pos = strpos($value, ':')); - $value = ltrim(substr($value, $pos + 1)); - if (isset($headers[$name]) AND is_array($headers[$name])) { - $headers[$name][] = $value; - } elseif (isset($headers[$name])) { - $headers[$name] = array($headers[$name], $value); - } else { - $headers[$name] = $value; - } - } - - return $headers; - } - - return false; - } - - /* - * Returns the body of the message with given message number. - * - * @param $msg_id Message number - * @return mixed Either message body or false on error - */ - function getBody($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $msg = $this->_cmdRetr($msg_id); - return substr($msg, strpos($msg, "\r\n\r\n")+4); - } - - return false; - } - - /* - * Returns the entire message with given message number. - * - * @param $msg_id Message number - * @return mixed Either entire message or false on error - */ - function getMsg($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdRetr($msg_id); - } - - return false; - } - - /* - * Returns the size of the maildrop - * - * @return mixed Either size of maildrop or false on error - */ - function getSize() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (isset($this->_maildrop['size'])) { - return $this->_maildrop['size']; - } else { - list(, $size) = $this->_cmdStat(); - return $size; - } - } - - return false; - } - - /* - * Returns number of messages in this maildrop - * - * @return mixed Either number of messages or false on error - */ - function numMsg() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (isset($this->_maildrop['num_msg'])) { - return $this->_maildrop['num_msg']; - } else { - list($num_msg, ) = $this->_cmdStat(); - return $num_msg; - } - } - - return false; - } - - /* - * Marks a message for deletion. Only will be deleted if the - * disconnect() method is called. - * - * @param $msg_id Message to delete - * @return bool Success/Failure - */ - function deleteMsg($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return $this->_cmdDele($msg_id); - } - - return false; - } - - /* - * Combination of LIST/UIDL commands, returns an array - * of data - * - * @param $msg_id Optional message number - * @return mixed Array of data or false on error - */ - function getListing($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (!isset($msg_id)){ - if ($list = $this->_cmdList()) { - if ($uidl = $this->_cmdUidl()) { - foreach ($uidl as $i => $value) { - $list[$i]['uidl'] = $value['uidl']; - } - } - - return $list; - } - } else { - if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) { - return array_merge($list, $uidl); - } - } - } - - return false; - } - - /* - * Sends the USER command - * - * @param $user Username to send - * @return bool Success/Failure - */ - function _cmdUser($user) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - return (bool)$this->_sendCmd('USER ' . $user); - } - - return false; - } - - - /* - * Sends the PASS command - * - * @param $pass Password to send - * @return bool Success/Failure - */ - function _cmdPass($pass) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - return (bool)$this->_sendCmd('PASS ' . $pass); - } - - return false; - } - - - /* - * Sends the STAT command - * - * @return mixed Indexed array of number of messages and - * maildrop size, or false on error. - */ - function _cmdStat() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('STAT'); - if ($data) { - sscanf($data, '+OK %d %d', $msg_num, $size); - $this->_maildrop['num_msg'] = $msg_num; - $this->_maildrop['size'] = $size; - - return array($msg_num, $size); - } - } - - return false; - } - - - /* - * Sends the LIST command - * - * @param $msg_id Optional message number - * @return mixed Indexed array of msg_id/msg size or - * false on error - */ - function _cmdList($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - if (!isset($msg_id)) { - $data = $this->_sendCmd('LIST'); - if ($data) { - $data = $this->_getMultiline(); - $data = explode("\r\n", $data); - foreach ($data as $line) { - sscanf($line, '%s %s', $msg_id, $size); - $return[] = array('msg_id' => $msg_id, 'size' => $size); - } - return $return; - } - } else { - $data = $this->_sendCmd('LIST ' . $msg_id); - if ($data) { - sscanf($data, '+OK %d %d', $msg_id, $size); - return array('msg_id' => $msg_id, 'size' => $size); - } - } - } - - return false; - } - - - /* - * Sends the RETR command - * - * @param $msg_id The message number to retrieve - * @return mixed The message or false on error - */ - function _cmdRetr($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('RETR ' . $msg_id); - if ($data) { - $data = $this->_getMultiline(); - return $data; - } - } - - return false; - } - - - /* - * Sends the DELE command - * - * @param $msg_id Message number to mark as deleted - * @return bool Success/Failure - */ - function _cmdDele($msg_id) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - return (bool)$this->_sendCmd('DELE ' . $msg_id); - } - - return false; - } - - - /* - * Sends the NOOP command - * - * @return bool Success/Failure - */ - function _cmdNoop() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('NOOP'); - if ($data) { - return true; - } - } - - return false; - } - - /* - * Sends the RSET command - * - * @return bool Success/Failure - */ - function _cmdRset() - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - $data = $this->_sendCmd('RSET'); - if ($data) { - return true; - } - } - - return false; - } - - /* - * Sends the QUIT command - * - * @return bool Success/Failure - */ - function _cmdQuit() - { - $data = $this->_sendCmd('QUIT'); - $this->_state = NET_POP3_STATE_DISCONNECTED; - $this->_socket->disconnect(); - - return (bool)$data; - } - - - /* - * Sends the TOP command - * - * @param $msg_id Message number - * @param $num_lines Number of lines to retrieve - * @return mixed Message data or false on error - */ - function _cmdTop($msg_id, $num_lines) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - - $data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines); - if ($data) { - return $this->_getMultiline(); - } - } - - return false; - } - - /* - * Sends the UIDL command - * - * @param $msg_id Message number - * @return mixed indexed array of msg_id/uidl or false on error - */ - function _cmdUidl($msg_id = null) - { - if ($this->_state == NET_POP3_STATE_TRANSACTION) { - - if (!isset($msg_id)) { - $data = $this->_sendCmd('UIDL'); - if ($data) { - $data = $this->_getMultiline(); - $data = explode("\r\n", $data); - foreach ($data as $line) { - sscanf($line, '%d %s', $msg_id, $uidl); - $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl); - } - - return $return; - } - } else { - - $data = $this->_sendCmd('UIDL ' . $msg_id); - sscanf($data, '+OK %d %s', $msg_id, $uidl); - return array('msg_id' => $msg_id, 'uidl' => $uidl); - } - } - - return false; - } - - /* - * Sends the APOP command - * - * @param $user Username to send - * @param $pass Password to send - * @return bool Success/Failure - */ - function _cmdApop($user, $pass) - { - if ($this->_state == NET_POP3_STATE_AUTHORISATION) { - - if (!empty($this->_timestamp)) { - $data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)); - if ($data) { - $this->_state = NET_POP3_STATE_TRANSACTION; - return true; - } - } - } - - return false; - } - - /* - * Sends a command, checks the reponse, and - * if good returns the reponse, other wise - * returns false. - * - * @param $cmd Command to send (\r\n will be appended) - * @return mixed First line of response if successful, otherwise false - */ - function _sendCmd($cmd) - { - $result = $this->_socket->writeLine($cmd); - if (!PEAR::isError($result) AND $result) { - $data = $this->_socket->readLine(); - if (!PEAR::isError($data) AND substr($data, 0, 3) == '+OK') { - return $data; - } - } - - return false; - } - - /* - * Reads a multiline reponse and returns the data - * - * @return string The reponse. - */ - function _getMultiline() - { - $data = ''; - while(($tmp = $this->_socket->readLine()) != '.') { - if (substr($tmp, 0, 2) == '..') { - $tmp = substr($tmp, 1); - } - $data .= $tmp . "\r\n"; - } - - return substr($data, 0, -2); - } -} - -?> +<?php +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002, Richard Heyes | +// | All rights reserved. | +// | | +// | Redistribution and use in source and binary forms, with or without | +// | modification, are permitted provided that the following conditions | +// | are met: | +// | | +// | o Redistributions of source code must retain the above copyright | +// | notice, this list of conditions and the following disclaimer. | +// | o 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.| +// | o The names of the authors may not be used to endorse or promote | +// | products derived from this software without specific prior written | +// | permission. | +// | | +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | +// | OWNER 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. | +// | | +// +-----------------------------------------------------------------------+ +// | Author: Richard Heyes <richard@phpguru.org> | +// | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> | +// +-----------------------------------------------------------------------+ +// +// $Id: POP3.php,v 1.5 2005/04/08 01:23:06 damian Exp $ + +require_once('Net/Socket.php'); + + + +/** +* +----------------------------- IMPORTANT ------------------------------+ +* | Usage of this class compared to native php extensions such as IMAP | +* | is slow and may be feature deficient. If available you are STRONGLY | +* | recommended to use the php extensions. | +* +----------------------------------------------------------------------+ +* +* POP3 Access Class +* +* For usage see the example script +*/ + +define('NET_POP3_STATE_DISCONNECTED', 1, true); +define('NET_POP3_STATE_AUTHORISATION', 2, true); +define('NET_POP3_STATE_TRANSACTION', 4, true); + +class Net_POP3 { + + /* + * Some basic information about the mail drop + * garnered from the STAT command + * + * @var array + */ + var $_maildrop; + + /* + * Used for APOP to store the timestamp + * + * @var string + */ + var $_timestamp; + + /* + * Timeout that is passed to the socket object + * + * @var integer + */ + var $_timeout; + + /* + * Socket object + * + * @var object + */ + var $_socket; + + /* + * Current state of the connection. Used with the + * constants defined above. + * + * @var integer + */ + var $_state; + + /* + * Hostname to connect to + * + * @var string + */ + var $_host; + + /* + * Port to connect to + * + * @var integer + */ + var $_port; + + /** + * To allow class debuging + * @var boolean + */ + var $_debug = false; + + + /** + * The auth methods this class support + * @var array + */ + //var $supportedAuthMethods=array('DIGEST-MD5', 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); + //Disabling DIGEST-MD5 for now + var $supportedAuthMethods=array( 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); + //var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN'); + //var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN'); + + + /** + * The auth methods this class support + * @var array + */ + var $supportedSASLAuthMethods=array('DIGEST-MD5', 'CRAM-MD5'); + + + /** + * The capability response + * @var array + */ + var $_capability; + + /* + * Constructor. Sets up the object variables, and instantiates + * the socket object. + * + */ + + + function Net_POP3() + { + $this->_timestamp = ''; // Used for APOP + $this->_maildrop = array(); + $this->_timeout = 3; + $this->_state = NET_POP3_STATE_DISCONNECTED; + $this->_socket =& new Net_Socket(); + /* + * Include the Auth_SASL package. If the package is not available, + * we disable the authentication methods that depend upon it. + */ + if ((@include_once 'Auth/SASL.php') == false) { + if($this->_debug){ + echo "AUTH_SASL NOT PRESENT!\n"; + } + foreach($this->supportedSASLAuthMethods as $SASLMethod){ + $pos = array_search( $SASLMethod, $this->supportedAuthMethods ); + if($this->_debug){ + echo "DISABLING METHOD $SASLMethod\n"; + } + unset($this->supportedAuthMethods[$pos]); + } + } + + + + } + + + /** + * Handles the errors the class can find + * on the server + * + * @access private + * @return PEAR_Error + */ + + function _raiseError($msg, $code =-1) + { + include_once 'PEAR.php'; + return PEAR::raiseError($msg, $code); + } + + + + /* + * Connects to the given host on the given port. + * Also looks for the timestamp in the greeting + * needed for APOP authentication + * + * @param string $host Hostname/IP address to connect to + * @param string $port Port to use to connect to on host + * @return bool Success/Failure + */ + function connect($host = 'localhost', $port = 110) + { + $this->_host = $host; + $this->_port = $port; + + $result = $this->_socket->connect($host, $port, false, $this->_timeout); + if ($result === true) { + $data = $this->_recvLn(); + + if( $this->_checkResponse($data) ){ + // if the response begins with '+OK' ... +// if (@substr(strtoupper($data), 0, 3) == '+OK') { + // Check for string matching apop timestamp + if (preg_match('/<.+@.+>/U', $data, $matches)) { + $this->_timestamp = $matches[0]; + } + $this->_maildrop = array(); + $this->_state = NET_POP3_STATE_AUTHORISATION; + + return true; + } + } + + $this->_socket->disconnect(); + return false; + } + + /* + * Disconnect function. Sends the QUIT command + * and closes the socket. + * + * @return bool Success/Failure + */ + function disconnect() + { + return $this->_cmdQuit(); + } + + /* + * Performs the login procedure. If there is a timestamp + * stored, APOP will be tried first, then basic USER/PASS. + * + * @param string $user Username to use + * @param string $pass Password to use + * @param mixed $apop Whether to try APOP first, if used as string you can select the auth methd to use ( $pop3->login('validlogin', 'validpass', "CRAM-MD5"); + * Valid methods are: 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER' + * @return mixed true on Success/ PEAR_ERROR on error + */ + function login($user, $pass, $apop = true) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + + if(PEAR::isError($ret= $this->_cmdAuthenticate($user , $pass , $apop ) ) ){ + return $ret; + } + if( ! PEAR::isError($ret)){ + $this->_state = NET_POP3_STATE_TRANSACTION; + return true; + } + + } + return $this->_raiseError('Generic login error' , 1); + } + + + + /** + * Parses the response from the capability command. Stores + * the result in $this->_capability + * + * @access private + */ + function _parseCapability() + { + + if(!PEAR::isError($data = $this->_sendCmd('CAPA'))){ + $data = $this->_getMultiline(); + }else { + // CAPA command not supported, reset data var + // to avoid Notice errors of preg_split on an object + $data = ''; + } + $data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY); + + for ($i = 0; $i < count($data); $i++) { + + $capa=''; + if (preg_match('/^([a-z,\-]+)( ((.*))|$)$/i', $data[$i], $matches)) { + + $capa=strtolower($matches[1]); + switch ($capa) { + case 'implementation': + $this->_capability['implementation'] = $matches[3]; + break; + case 'sasl': + $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); + break; + default : + $this->_capability[$capa] = $matches[2]; + break; + } + } + } + } + + + + + /** + * Returns the name of the best authentication method that the server + * has advertised. + * + * @param string if !=null,authenticate with this method ($userMethod). + * + * @return mixed Returns a string containing the name of the best + * supported authentication method or a PEAR_Error object + * if a failure condition is encountered. + * @access private + * @since 1.0 + */ + function _getBestAuthMethod($userMethod = null) + { + +/* + return 'USER'; + return 'APOP'; + return 'DIGEST-MD5'; + return 'CRAM-MD5'; +*/ + + + $this->_parseCapability(); + + //unset($this->_capability['sasl']); + + if( isset($this->_capability['sasl']) ){ + $serverMethods=$this->_capability['sasl']; + }else{ + $serverMethods=array('USER'); + // Check for timestamp before attempting APOP + if ($this->_timestamp != null) + { + $serverMethods[] = 'APOP'; + } + } + + if($userMethod !== null && $userMethod !== true ){ + $methods = array(); + $methods[] = $userMethod; + return $userMethod; + }else{ + $methods = $this->supportedAuthMethods; + } + + if( ($methods != null) && ($serverMethods != null)){ + + foreach ( $methods as $method ) { + + if ( in_array( $method , $serverMethods ) ) { + return $method; + } + } + $serverMethods=implode(',' , $serverMethods ); + $myMethods=implode(',' ,$this->supportedAuthMethods); + return $this->_raiseError("$method NOT supported authentication method!. This server " . + "supports these methods: $serverMethods, but I support $myMethods"); + }else{ + return $this->_raiseError("This server don't support any Auth methods"); + } + } + + + + + + + /* Handles the authentication using any known method + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) ) + * + * @return mixed string or PEAR_Error + * + * @access private + * @since 1.0 + */ + function _cmdAuthenticate($uid , $pwd , $userMethod = null ) + { + + + if ( PEAR::isError( $method = $this->_getBestAuthMethod($userMethod) ) ) { + return $method; + } + + switch ($method) { + case 'DIGEST-MD5': + $result = $this->_authDigest_MD5( $uid , $pwd ); + break; + case 'CRAM-MD5': + $result = $this->_authCRAM_MD5( $uid , $pwd ); + break; + case 'LOGIN': + $result = $this->_authLOGIN( $uid , $pwd ); + break; + case 'PLAIN': + $result = $this->_authPLAIN( $uid , $pwd ); + break; + case 'APOP': + $result = $this->_cmdApop( $uid , $pwd ); + // if APOP fails fallback to USER auth + if( PEAR::isError( $result ) ){ + //echo "APOP FAILED!!!\n"; + $result=$this->_authUSER( $uid , $pwd ); + } + break; + case 'USER': + $result = $this->_authUSER( $uid , $pwd ); + break; + + + default : + $result = $this->_raiseError( "$method is not a supported authentication method" ); + break; + } + return $result; + } + + + + + /* Authenticates the user using the USER-PASS method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed true on success or PEAR_Error on failure + * + * @access private + * @since 1.0 + */ + function _authUSER($user, $pass ) + { + if ( PEAR::isError($ret=$this->_cmdUser($user) ) ){ + return $ret; + } + if ( PEAR::isError($ret=$this->_cmdPass($pass) ) ){ + return $ret; + } + return true; + } + + + + + + + + + /* Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authPLAIN($user, $pass ) + { + $cmd=sprintf('AUTH PLAIN %s', base64_encode( chr(0) . $user . chr(0) . $pass ) ); + + if ( PEAR::isError( $ret = $this->_send($cmd) ) ) { + return $ret; + } + if ( PEAR::isError( $challenge = $this->_recvLn() ) ){ + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + return true; + } + + + + /* Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authLOGIN($user, $pass ) + { + $this->_send('AUTH LOGIN'); + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + + if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($user))) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($pass))) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + return $this->_checkResponse($challenge); + } + + + + + + /* Authenticates the user using the CRAM-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authCRAM_MD5($uid, $pwd ) + { + if ( PEAR::isError( $ret = $this->_send( 'AUTH CRAM-MD5' ) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + // remove '+ ' + + $challenge=substr($challenge,2); + + $challenge = base64_decode( $challenge ); + + $cram = &Auth_SASL::factory('crammd5'); + $auth_str = base64_encode( $cram->getResponse( $uid , $pwd , $challenge ) ); + + + if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) { + return $error; + } + if ( PEAR::isError( $ret = $this->_recvLn() ) ) { + return $ret; + } + //echo "RET:$ret\n"; + return $this->_checkResponse($ret); + } + + + + /* Authenticates the user using the DIGEST-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The efective user + * + * @return array Returns an array containing the response + * + * @access private + * @since 1.0 + */ + function _authDigest_MD5($uid, $pwd) + { + if ( PEAR::isError( $ret = $this->_send( 'AUTH DIGEST-MD5' ) ) ) { + return $ret; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + + // remove '+ ' + $challenge=substr($challenge,2); + + $challenge = base64_decode( $challenge ); + $digest = &Auth_SASL::factory('digestmd5'); + $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3" )); + + if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) { + return $error; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + if( PEAR::isError($ret=$this->_checkResponse($challenge) )){ + return $ret; + } + /* + * We don't use the protocol's third step because POP3 doesn't allow + * subsequent authentication, so we just silently ignore it. + */ + + if ( PEAR::isError( $challenge = $this->_send("\r\n") ) ) { + return $challenge ; + } + + if ( PEAR::isError( $challenge = $this->_recvLn() ) ) { + return $challenge; + } + + return $this->_checkResponse($challenge); + + + } + + + + + + + + + + + /* + * Sends the APOP command + * + * @param $user Username to send + * @param $pass Password to send + * @return bool Success/Failure + */ + function _cmdApop($user, $pass) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + + if (!empty($this->_timestamp)) { + if(PEAR::isError($data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)) ) ){ + return $data; + } + $this->_state = NET_POP3_STATE_TRANSACTION; + return true; + } + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State1'); + } + + + + + + + + + + + + + + + + /* + * Returns the raw headers of the specified message. + * + * @param integer $msg_id Message number + * @return mixed Either raw headers or false on error + */ + function getRawHeaders($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdTop($msg_id, 0); + } + + return false; + } + + /* + * Returns the headers of the specified message in an + * associative array. Array keys are the header names, array + * values are the header values. In the case of multiple headers + * having the same names, eg Received:, the array value will be + * an indexed array of all the header values. + * + * @param integer $msg_id Message number + * @return mixed Either array of headers or false on error + */ + function getParsedHeaders($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + $raw_headers = rtrim($this->getRawHeaders($msg_id)); + + $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers + $raw_headers = explode("\r\n", $raw_headers); + foreach ($raw_headers as $value) { + $name = substr($value, 0, $pos = strpos($value, ':')); + $value = ltrim(substr($value, $pos + 1)); + if (isset($headers[$name]) AND is_array($headers[$name])) { + $headers[$name][] = $value; + } elseif (isset($headers[$name])) { + $headers[$name] = array($headers[$name], $value); + } else { + $headers[$name] = $value; + } + } + + return $headers; + } + + return false; + } + + /* + * Returns the body of the message with given message number. + * + * @param integer $msg_id Message number + * @return mixed Either message body or false on error + */ + function getBody($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + $msg = $this->_cmdRetr($msg_id); + return substr($msg, strpos($msg, "\r\n\r\n")+4); + } + + return false; + } + + /* + * Returns the entire message with given message number. + * + * @param integer $msg_id Message number + * @return mixed Either entire message or false on error + */ + function getMsg($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdRetr($msg_id); + } + + return false; + } + + /* + * Returns the size of the maildrop + * + * @return mixed Either size of maildrop or false on error + */ + function getSize() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (isset($this->_maildrop['size'])) { + return $this->_maildrop['size']; + } else { + list(, $size) = $this->_cmdStat(); + return $size; + } + } + + return false; + } + + /* + * Returns number of messages in this maildrop + * + * @return mixed Either number of messages or false on error + */ + function numMsg() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (isset($this->_maildrop['num_msg'])) { + return $this->_maildrop['num_msg']; + } else { + list($num_msg, ) = $this->_cmdStat(); + return $num_msg; + } + } + + return false; + } + + /* + * Marks a message for deletion. Only will be deleted if the + * disconnect() method is called. + * + * @param integer $msg_id Message to delete + * @return bool Success/Failure + */ + function deleteMsg($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_cmdDele($msg_id); + } + + return false; + } + + /* + * Combination of LIST/UIDL commands, returns an array + * of data + * + * @param integer $msg_id Optional message number + * @return mixed Array of data or false on error + */ + function getListing($msg_id = null) + { + + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (!isset($msg_id)){ + + $list=array(); + if ($list = $this->_cmdList()) { + if ($uidl = $this->_cmdUidl()) { + foreach ($uidl as $i => $value) { + $list[$i]['uidl'] = $value['uidl']; + } + } + return $list; + }else{ + return array(); + } + } else { + if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) { + return array_merge($list, $uidl); + } + } + } + + return false; + } + + /* + * Sends the USER command + * + * @param string $user Username to send + * @return bool Success/Failure + */ + function _cmdUser($user) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + return $this->_sendCmd('USER ' . $user); + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); + } + + + /* + * Sends the PASS command + * + * @param string $pass Password to send + * @return bool Success/Failure + */ + function _cmdPass($pass) + { + if ($this->_state == NET_POP3_STATE_AUTHORISATION) { + return $this->_sendCmd('PASS ' . $pass); + } + return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); + } + + + /* + * Sends the STAT command + * + * @return mixed Indexed array of number of messages and + * maildrop size, or false on error. + */ + function _cmdStat() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('STAT'))){ + sscanf($data, '+OK %d %d', $msg_num, $size); + $this->_maildrop['num_msg'] = $msg_num; + $this->_maildrop['size'] = $size; + + return array($msg_num, $size); + } + } + return false; + } + + + /* + * Sends the LIST command + * + * @param integer $msg_id Optional message number + * @return mixed Indexed array of msg_id/msg size or + * false on error + */ + function _cmdList($msg_id = null) + { + $return=array(); + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if (!isset($msg_id)) { + if(!PEAR::isError($data = $this->_sendCmd('LIST') )){ + $data = $this->_getMultiline(); + $data = explode("\r\n", $data); + foreach ($data as $line) { + if($line !=''){ + sscanf($line, '%s %s', $msg_id, $size); + $return[] = array('msg_id' => $msg_id, 'size' => $size); + } + } + return $return; + } + } else { + if(!PEAR::isError($data = $this->_sendCmd('LIST ' . $msg_id))){ + if($data!=''){ + sscanf($data, '+OK %d %d', $msg_id, $size); + return array('msg_id' => $msg_id, 'size' => $size); + } + return array(); + } + } + } + + + return false; + } + + + /* + * Sends the RETR command + * + * @param integer $msg_id The message number to retrieve + * @return mixed The message or false on error + */ + function _cmdRetr($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('RETR ' . $msg_id) )){ + $data = $this->_getMultiline(); + return $data; + } + } + + return false; + } + + + /* + * Sends the DELE command + * + * @param integer $msg_id Message number to mark as deleted + * @return bool Success/Failure + */ + function _cmdDele($msg_id) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + return $this->_sendCmd('DELE ' . $msg_id); + } + + return false; + } + + + /* + * Sends the NOOP command + * + * @return bool Success/Failure + */ + function _cmdNoop() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('NOOP'))){ + return true; + } + } + + return false; + } + + /* + * Sends the RSET command + * + * @return bool Success/Failure + */ + function _cmdRset() + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + if(!PEAR::isError($data = $this->_sendCmd('RSET'))){ + return true; + } + } + + return false; + } + + /* + * Sends the QUIT command + * + * @return bool Success/Failure + */ + function _cmdQuit() + { + $data = $this->_sendCmd('QUIT'); + $this->_state = NET_POP3_STATE_DISCONNECTED; + $this->_socket->disconnect(); + + return (bool)$data; + } + + + /* + * Sends the TOP command + * + * @param integer $msg_id Message number + * @param integer $num_lines Number of lines to retrieve + * @return mixed Message data or false on error + */ + function _cmdTop($msg_id, $num_lines) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + if(!PEAR::isError($data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines))){ + return $this->_getMultiline(); + } + } + + return false; + } + + /* + * Sends the UIDL command + * + * @param integer $msg_id Message number + * @return mixed indexed array of msg_id/uidl or false on error + */ + function _cmdUidl($msg_id = null) + { + if ($this->_state == NET_POP3_STATE_TRANSACTION) { + + if (!isset($msg_id)) { + if(!PEAR::isError($data = $this->_sendCmd('UIDL') )){ + $data = $this->_getMultiline(); + $data = explode("\r\n", $data); + foreach ($data as $line) { + sscanf($line, '%d %s', $msg_id, $uidl); + $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl); + } + + return $return; + } + } else { + + $data = $this->_sendCmd('UIDL ' . $msg_id); + sscanf($data, '+OK %d %s', $msg_id, $uidl); + return array('msg_id' => $msg_id, 'uidl' => $uidl); + } + } + + return false; + } + + + + + + + + + + /* + * Sends a command, checks the reponse, and + * if good returns the reponse, other wise + * returns false. + * + * @param string $cmd Command to send (\r\n will be appended) + * @return mixed First line of response if successful, otherwise false + */ + function _sendCmd($cmd) + { + if (PEAR::isError($result = $this->_send($cmd) )){ + return $result ; + } + + if (PEAR::isError($data = $this->_recvLn() )){ + return $data; + } + + if ( strtoupper(substr($data, 0, 3)) == '+OK') { + return $data; + } + + + return $this->_raiseError($data); + } + + /* + * Reads a multiline reponse and returns the data + * + * @return string The reponse. + */ + function _getMultiline() + { + $data = ''; + while(!PEAR::isError($tmp = $this->_recvLn() ) ) { + if($tmp == '.'){ + return substr($data, 0, -2); + } + if (substr($tmp, 0, 2) == '..') { + $tmp = substr($tmp, 1); + } + $data .= $tmp . "\r\n"; + } + return substr($data, 0, -2); + } + + + /** + * Sets the bebug state + * + * @param bool $debug + * @access public + * @return void + */ + function setDebug($debug=true) + { + $this->_debug=$debug; + } + + + + + + /** + * Send the given string of data to the server. + * + * @param string $data The string of data to send. + * + * @return mixed True on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.0 + */ + function _send($data) + { + if ($this->_debug) { + echo "C: $data\n"; + } + + if (PEAR::isError($error = $this->_socket->writeLine($data))) { + return $this->_raiseError('Failed to write to socket: ' . $error->getMessage()); + } + return true; + } + + + + /** + * Receive the given string of data from the server. + * + * @return mixed a line of response on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.0 + */ + function _recvLn() + { + if (PEAR::isError( $lastline = $this->_socket->readLine( 8192 ) ) ) { + return $this->_raiseError('Failed to write to socket: ' . $this->lastline->getMessage() ); + } + if($this->_debug){ + // S: means this data was sent by the POP3 Server + echo "S:$lastline\n" ; + } + return $lastline; + } + + /** + * Checks de server Response + * + * @param string $response the response + * @return mixed true on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.3.3 + */ + + function _checkResponse($response) + { + if (@substr(strtoupper($response), 0, 3) == '+OK') { + return true; + }else{ + if (@substr(strtoupper($response), 0, 4) == '-ERR') { + return $this->_raiseError($response); + }else{ + if (@substr(strtoupper($response), 0, 2) == '+ ') { + return true; + } + } + + } + return $this->_raiseError("Unknown Response ($response)"); + } + + + +} + +?> http://cvs.php.net/diff.php/pear/Net_POP3/package.xml?r1=1.11&r2=1.12&ty=u Index: pear/Net_POP3/package.xml diff -u pear/Net_POP3/package.xml:1.11 pear/Net_POP3/package.xml:1.12 --- pear/Net_POP3/package.xml:1.11 Sat Jul 12 04:02:02 2003 +++ pear/Net_POP3/package.xml Thu Apr 7 21:23:06 2005 @@ -1,56 +1,235 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> -<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> -<package version="1.0"> - - <name>Net_POP3</name> - <summary>Provides a POP3 class to access POP3 server.</summary> - <description> - Provides a POP3 class to access POP3 server. Support all POP3 commands - including UIDL listings and APOP authentication. - </description> - - <maintainers> - <maintainer> - <user>richard</user> - <name>Richard Heyes</name> - <email>richard@php.net</email> - <role>lead</role> - </maintainer> - </maintainers> - - <release> - <version>1.2</version> - <date>2002-07-27</date> - <state>stable</state> - <license>BSD</license> - <notes> - License change - </notes> - <filelist> - <dir name="/" baseinstalldir="Net"> - <file role="php">POP3.php</file> - <file role="php">Net_POP3_example.php</file> - </dir> - </filelist> - <deps> - <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> - </deps> - </release> - - <changelog> - - <release> - <version>1.1</version> - <date>2002-02-13</date> - <state>stable</state> - <notes> - Renamed file to POP3.php - </notes> - <deps> - <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> - </deps> - </release> - - </changelog> - -</package> +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> +<package version="1.0"> + + <name>Net_POP3</name> + <summary>Provides a POP3 class to access POP3 server.</summary> + <description> + Provides a POP3 class to access POP3 server. Support all POP3 commands + including UIDL listings, APOP authentication,DIGEST-MD5 and CRAM-MD5 using optional Auth_SASL package + </description> + + <maintainers> + <maintainer> + <user>richard</user> + <name>Richard Heyes</name> + <email>richard@php.net</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>damian</user> + <name>Damian Fernandez Sosa</name> + <email>damlists@cnba.uba.ar</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>gschlossnagle</user> + <name>George Schlossnagle</name> + <email>george@omniti.com</email> + <role>lead</role> + </maintainer> + </maintainers> + + + <release> + <version>1.3.6</version> + <date>2005-04-04</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #3551 Bug #2663 not fixed yet. +* Fixed Bug #3410 Error handling in _sendCmd +* Fixed Bug #1942 wrong parameter-type specification in Net_POP3::login +* Fixed Bug #239 Missing phpdoc tag. + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + +<changelog> + + + + + <release> + <version>1.3.5</version> + <date>2005-02-02</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #3141 $pop3->getListing() returns empty fields. thanks to culmat at gmx dot net + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + <release> + <version>1.3.4</version> + <date>2004-12-05</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixed Bug #2440 thanks to erickoh at jobsfactory dot com +* Fixed Bug #2453 :Mistake in PEAR Doc for Net_POP3 example. thanks to erickoh at jobsfactory dot com +* Removed double quotes in _authLogin() fixes Bug #2454 :AUTH LOGIN user and pass need to be enclosed in double quotes?. thanks to erickoh at jobsfactory dot com +* Fixed Bug #2523 : Unable to login to Qmail servers. thanks to johann dot hoehn at ecommerce dot com +* Fixed Bug #2646 :APOP attempted when not supported. thanks to osdave at nospam_davepar dot com + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + +<release> + <version>1.3.3</version> + <date>2004-09-15</date> + <state>stable</state> + <license>BSD</license> + <notes> +* _sendCmd now return PEAR_Error on error instead of false making error check easy +* Fixes bug #2175 login() which uses DIGEST-MD5 always returns true. +* All the Login methods now uses PEAR_Error instead of 'false' finding the error cause is now easy +* Disabling DIGEST-MD5 until I can make work whit saslv2 (saslv2 and saslv1 responses are different ) + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + <release> + <version>1.3.2</version> + <date>2004-06-26</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Fixes bug #1505 + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + <release> + <version>1.3.1</version> + <date>2004-03-18</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Solves a bug in the auth code when the AUTH method is set to APOP but the server fall back to user and pass + + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + + <release> + <version>1.3</version> + <date>2004-03-03</date> + <state>stable</state> + <license>BSD</license> + <notes> +* Added debug capabilities +* Added _recvLn() and _send($data) to support debug and better check socket errors +* Added SASL AUTH capabilities +* if installed automatically uses Auth_SASL +* Added LOGIN,PLAIN,DIGEST-MD5 and CRAM-MD5 +* Modified APOP and USER auths +* Now the class automagically selects the best auth method + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="test">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + <release> + <version>1.2</version> + <date>2002-07-27</date> + <state>stable</state> + <license>BSD</license> + <notes> + License change + </notes> + <filelist> + <dir name="/" baseinstalldir="Net"> + <file role="php">POP3.php</file> + <file role="php">Net_POP3_example.php</file> + </dir> + </filelist> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + + + <release> + <version>1.1</version> + <date>2002-02-13</date> + <state>stable</state> + <notes> + Renamed file to POP3.php + </notes> + <deps> + <dep type="pkg" rel="ge" version="1.0">Net_Socket</dep> + </deps> + </release> + +</changelog> + +</package>