mirror of
https://github.com/ACSPRI/queXS
synced 2024-04-02 12:12:16 +00:00
Import from DCARF SVN
This commit is contained in:
943
include/pear/Net/NNTP.php
Normal file
943
include/pear/Net/NNTP.php
Normal file
@@ -0,0 +1,943 @@
|
||||
<?php
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
|
||||
// +----------------------------------------------------------------------+
|
||||
// | PHP Version 4 |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Copyright (c) 1997-2003 The PHP Group |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | This source file is subject to version 2.0 of the PHP license, |
|
||||
// | that is bundled with this package in the file LICENSE, and is |
|
||||
// | available at through the world-wide-web at |
|
||||
// | http://www.php.net/license/2_02.txt. |
|
||||
// | If you did not receive a copy of the PHP license and are unable to |
|
||||
// | obtain it through the world-wide-web, please send a note to |
|
||||
// | license@php.net so we can mail you a copy immediately. |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Authors: Martin Kaltoft <martin@nitro.dk> |
|
||||
// | Tomas V.V.Cox <cox@idecnet.com> |
|
||||
// | Heino H. Gehlsen <heino@gehlsen.dk> |
|
||||
// +----------------------------------------------------------------------+
|
||||
// $Id: NNTP.php,v 1.30.2.4 2005/01/19 08:39:11 heino Exp $
|
||||
|
||||
require_once 'Net/NNTP/Protocol/Client.php';
|
||||
|
||||
// {{{ constants
|
||||
|
||||
/* NNTP Authentication modes */
|
||||
define('NET_NNTP_AUTHORIGINAL', 'original');
|
||||
define('NET_NNTP_AUTHSIMPLE', 'simple');
|
||||
define('NET_NNTP_AUTHGENERIC', 'generic');
|
||||
|
||||
// Deprecated due to naming
|
||||
define('PEAR_NNTP_AUTHORIGINAL', NET_NNTP_AUTHORIGINAL);
|
||||
define('PEAR_NNTP_AUTHSIMPLE', NET_NNTP_AUTHSIMPLE);
|
||||
define('PEAR_NNTP_AUTHGENERIC', NET_NNTP_AUTHGENERIC);
|
||||
|
||||
// }}}
|
||||
// {{{ Net_NNTP
|
||||
|
||||
/**
|
||||
* The Net_NNTP class is an almost 100 % backward compatible
|
||||
* frontend class to the Net_NNTP_Protocol_Client class.
|
||||
*
|
||||
* ATTENTION!!!
|
||||
* This class should NOT be used in new projects. It is meant
|
||||
* as a drop in replacement to the outdated v0.2, and uses
|
||||
* excatly the same protocol implementation as the new
|
||||
* Net_NNTP_Client class, but has a lot of deprecated
|
||||
* methods etc.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_NNTP
|
||||
* @author Martin Kaltoft <martin@nitro.dk>
|
||||
* @author Tomas V.V.Cox <cox@idecnet.com>
|
||||
* @author Heino H. Gehlsen <heino@gehlsen.dk>
|
||||
* @version $Id: NNTP.php,v 1.30.2.4 2005/01/19 08:39:11 heino Exp $
|
||||
* @access public
|
||||
* @see Net_NNTP_Client
|
||||
* @since Class available since Release 0.1.0
|
||||
* @deprecated Class deprecated in Release 0.10.0
|
||||
*/
|
||||
class Net_NNTP extends Net_NNTP_Protocol_Client
|
||||
{
|
||||
// {{{ properties
|
||||
|
||||
/**
|
||||
* File pointer of the nntp-connection
|
||||
*
|
||||
* @var
|
||||
* @access public
|
||||
*/
|
||||
var $fp = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @access public
|
||||
* @deprecated use last() instead
|
||||
*/
|
||||
var $max;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @access public
|
||||
* @deprecated use last() instead
|
||||
*/
|
||||
var $min;
|
||||
|
||||
/**
|
||||
* Used for storing information about the currently selected group
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
* @since 0.3
|
||||
*/
|
||||
var $_currentGroup = null;
|
||||
|
||||
// }}}
|
||||
// {{{ constructor
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function Net_NNTP()
|
||||
{
|
||||
parent::Net_NNTP_Protocol_Client();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ connect()
|
||||
|
||||
/**
|
||||
* Connect to the newsserver.
|
||||
*
|
||||
* The function currently allows automatic authentication via the three last parameters,
|
||||
* but this feature is to be considered depresated (use connectAuthenticated instead)
|
||||
*
|
||||
* In the future, this function will just be inherrited from the parent,
|
||||
* and thus the last three parameters will no longer be used to authenticate.
|
||||
*
|
||||
* @param optional string $host The adress of the NNTP-server to connect to.
|
||||
* @param optional int $port The port to connect to.
|
||||
* @param optional string $user Deprecated!
|
||||
* @param optional string $pass Deprecated!
|
||||
* @param optional string $authmode Deprecated!
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP::quit()
|
||||
* @see Net_NNTP::connectAuthenticated()
|
||||
* @see Net_NNTP::authenticate()
|
||||
*/
|
||||
function connect($host = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_HOST,
|
||||
$port = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT,
|
||||
$user = null,
|
||||
$pass = null,
|
||||
$authmode = NET_NNTP_AUTHORIGINAL)
|
||||
{
|
||||
// Currently this function just 'forwards' to connectAuthenticated().
|
||||
$R = $this->connectAuthenticated($user, $pass, $host, $port, $authmode);
|
||||
|
||||
if (PEAR::isError($R)) {
|
||||
return $R;
|
||||
}
|
||||
|
||||
$this->fp = $this->_socket->fp;
|
||||
|
||||
return $R;
|
||||
}
|
||||
|
||||
|
||||
// }}}
|
||||
// {{{ connectAuthenticated()
|
||||
|
||||
/**
|
||||
* Connect to the newsserver, and authenticate. If no user/pass is specified, just connect.
|
||||
*
|
||||
* @param optional string $user The user name to authenticate with
|
||||
* @param optional string $pass The password
|
||||
* @param optional string $host The adress of the NNTP-server to connect to.
|
||||
* @param optional int $port The port to connect to.
|
||||
* @param optional string $authmode The authentication mode
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::connect()
|
||||
* @see Net_NNTP::authenticate()
|
||||
* @see Net_NNTP::quit()
|
||||
* @deprecated use connect() and authenticate() instead
|
||||
*/
|
||||
function connectAuthenticated($user = null,
|
||||
$pass = null,
|
||||
$host = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_HOST,
|
||||
$port = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT,
|
||||
$authmode = NET_NNTP_AUTHORIGINAL)
|
||||
{
|
||||
// Until connect() is changed, connect() is called directly from the parent...
|
||||
$R = parent::connect($host, $port);
|
||||
if (PEAR::isError($R)) {
|
||||
return $R;
|
||||
}
|
||||
|
||||
// Authenticate if username is given
|
||||
if ($user != null) {
|
||||
$R = $this->authenticate($user, $pass, $authmode);
|
||||
if (PEAR::isError($R)) {
|
||||
return $R;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ quit()
|
||||
|
||||
/**
|
||||
* Close connection to the newsserver
|
||||
*
|
||||
* @access public
|
||||
* @see Net_NNTP::connect()
|
||||
*/
|
||||
function quit()
|
||||
{
|
||||
return $this->cmdQuit();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ prepareConnection()
|
||||
|
||||
/**
|
||||
* Connect to the newsserver, and issue a GROUP command
|
||||
* Once connection is prepared, we can only fetch articles from one group
|
||||
* at a time, to fetch from another group, a new connection has to be made.
|
||||
*
|
||||
* This is to avoid the GROUP command for every article, as it is very
|
||||
* ressource intensive on the newsserver especially when used for
|
||||
* groups with many articles.
|
||||
*
|
||||
* @param string $host The adress of the NNTP-server to connect to.
|
||||
* @param optional int $port the port-number to connect to, defaults to 119.
|
||||
* @param string $newsgroup The name of the newsgroup to use.
|
||||
* @param optional string $user The user name to authenticate with
|
||||
* @param optional string $pass The password
|
||||
* @param optional string $authmode The authentication mode
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*
|
||||
* @deprecated Use connect() or connectAuthenticated() instead
|
||||
*/
|
||||
function prepareConnection($host,
|
||||
$port = 119,
|
||||
$newsgroup,
|
||||
$user = null,
|
||||
$pass = null,
|
||||
$authmode = NET_NNTP_AUTHORIGINAL)
|
||||
{
|
||||
/* connect to the server */
|
||||
$R = $this->connect($host, $port, $user, $pass, $authmode);
|
||||
if (PEAR::isError($R)) {
|
||||
return $R;
|
||||
}
|
||||
|
||||
/* issue a GROUP command */
|
||||
$R = $this->selectGroup($newsgroup);
|
||||
if (PEAR::isError($R)) {
|
||||
return $R;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function prepare_connection($nntpserver,
|
||||
$port = 119,
|
||||
$newsgroup,
|
||||
$user = null,
|
||||
$pass = null,
|
||||
$authmode = NET_NNTP_AUTHORIGINAL)
|
||||
{
|
||||
return $this->prepareConnection($nntpserver, $port, $newsgroup, $user, $pass, $authmode);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ authenticate()
|
||||
|
||||
/**
|
||||
* Auth process (not yet standarized but used any way)
|
||||
* http://www.mibsoftware.com/userkt/nntpext/index.html
|
||||
*
|
||||
* @param string $user The user name
|
||||
* @param optional string $pass The password if needed
|
||||
* @param optional string $mode Authinfo type: original, simple, generic
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::connect()
|
||||
*/
|
||||
function authenticate($user, $pass, $mode = NET_NNTP_AUTHORIGINAL)
|
||||
{
|
||||
// Username is a must...
|
||||
if ($user == null) {
|
||||
return PEAR::throwError('No username supplied', null);
|
||||
}
|
||||
|
||||
// Use selected authentication method
|
||||
switch ($mode) {
|
||||
case NET_NNTP_AUTHORIGINAL:
|
||||
return $this->cmdAuthinfo($user, $pass);
|
||||
break;
|
||||
case NET_NNTP_AUTHSIMPLE:
|
||||
return $this->cmdAuthinfoSimple($user, $pass);
|
||||
break;
|
||||
case NET_NNTP_AUTHGENERIC:
|
||||
return $this->cmdAuthinfoGeneric($user, $pass);
|
||||
break;
|
||||
default:
|
||||
return PEAR::throwError("The auth mode: '$mode' is unknown", null);
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ isConnected()
|
||||
|
||||
/**
|
||||
* Test whether we are connected or not.
|
||||
*
|
||||
* @return bool true or false
|
||||
* @access public
|
||||
* @see Net_NNTP::connect()
|
||||
* @see Net_NNTP::quit()
|
||||
*/
|
||||
function isConnected()
|
||||
{
|
||||
return parent::isConnected();
|
||||
}
|
||||
|
||||
function is_connected()
|
||||
{
|
||||
return $this->isConnected();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ selectGroup()
|
||||
|
||||
/**
|
||||
* Selects a news group (issue a GROUP command to the server)
|
||||
*
|
||||
* @param string $newsgroup The newsgroup name
|
||||
*
|
||||
* @return mixed (array) Groups info on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see group()
|
||||
* @see count()
|
||||
* @see first()
|
||||
* @see last()
|
||||
*/
|
||||
function selectGroup($newsgroup)
|
||||
{
|
||||
$response_arr = $this->cmdGroup($newsgroup);
|
||||
if (PEAR::isError($response_arr)) {
|
||||
return $response_arr;
|
||||
}
|
||||
|
||||
$this->_currentGroup = $response_arr;
|
||||
|
||||
// Deprecated / historical
|
||||
$response_arr['min'] =& $response_arr['first'];
|
||||
$response_arr['max'] =& $response_arr['last'];
|
||||
$this->min =& $response_arr['min'];
|
||||
$this->max =& $response_arr['max'];
|
||||
|
||||
return $response_arr;
|
||||
}
|
||||
|
||||
function select_group($newsgroup)
|
||||
{
|
||||
return $this->selectGroup($newsgroup);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getGroups()
|
||||
|
||||
/**
|
||||
* Fetches a list of all avaible newsgroups
|
||||
*
|
||||
* @return mixed (array) nested array with informations about existing newsgroups on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*/
|
||||
function getGroups()
|
||||
{
|
||||
// Get groups
|
||||
$groups = $this->cmdList();
|
||||
if (PEAR::isError($groups)) {
|
||||
return $groups;
|
||||
}
|
||||
|
||||
// Deprecated / historical
|
||||
foreach (array_keys($groups) as $k) {
|
||||
$groups[$k]['posting_allowed'] =& $groups[$k]['posting'];
|
||||
}
|
||||
|
||||
// Get group descriptions
|
||||
$descriptions = $this->cmdListNewsgroups();
|
||||
if (PEAR::isError($descriptions)) {
|
||||
return $descriptions;
|
||||
}
|
||||
|
||||
// Set known descriptions for groups
|
||||
if (count($descriptions) > 0) {
|
||||
foreach ($descriptions as $k=>$v) {
|
||||
$groups[$k]['desc'] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
function get_groups()
|
||||
{
|
||||
return $this->getGroups();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getOverview()
|
||||
|
||||
/**
|
||||
* Fetch message header from message number $first to $last
|
||||
*
|
||||
* The format of the returned array is:
|
||||
* $messages[message_id][header_name]
|
||||
*
|
||||
* @param integer $first first article to fetch
|
||||
* @param integer $last last article to fetch
|
||||
*
|
||||
* @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP::getOverviewFormat()
|
||||
* @see Net_NNTP::getReferencesOverview()
|
||||
*/
|
||||
function getOverview($first, $last)
|
||||
{
|
||||
$overview = $this->cmdXOver($first.'-'.$last);
|
||||
if (PEAR::isError($overview)) {
|
||||
return $overview;
|
||||
}
|
||||
|
||||
return $overview;
|
||||
}
|
||||
|
||||
function get_overview($first, $last)
|
||||
{
|
||||
$this->getOverview($first, $last);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getOverviewFormat()
|
||||
|
||||
/**
|
||||
* Returns a list of avaible headers which are send from newsserver to client for every news message
|
||||
*
|
||||
* @return mixed (array) header names on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP::getOverview()
|
||||
*/
|
||||
function getOverviewFormat()
|
||||
{
|
||||
return $this->cmdListOverviewFMT();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getOverviewFmt()
|
||||
|
||||
/**
|
||||
* Returns a list of avaible headers which are send from newsserver to client for every news message
|
||||
*
|
||||
* @return mixed (array) header names on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @deprecated use getOverviewFormat() instead
|
||||
*/
|
||||
function getOverviewFmt()
|
||||
{
|
||||
return $this->getOverviewFormat();
|
||||
}
|
||||
|
||||
function get_overview_fmt()
|
||||
{
|
||||
$this->getOverviewFmt();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getReferencesOverview()
|
||||
|
||||
/**
|
||||
* Fetch a list of each message's reference header.
|
||||
*
|
||||
* @param integer $first first article to fetch
|
||||
* @param integer $last last article to fetch
|
||||
*
|
||||
* @return mixed (array) nested array of references on success or (object) pear_error on failure
|
||||
*
|
||||
* @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP::getOverview()
|
||||
*/
|
||||
function getReferencesOverview($first, $last)
|
||||
{
|
||||
$overview = $this->cmdXROver($first.'-'.$last);
|
||||
if (PEAR::isError($overview)) {
|
||||
return $overview;
|
||||
}
|
||||
|
||||
return $overview;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ post()
|
||||
|
||||
/**
|
||||
* Post an article to a number of newsgroups.
|
||||
*
|
||||
* (Among the aditional headers you might think of adding could be:
|
||||
* "NNTP-Posting-Host: <ip-of-author>", which should contain the IP-adress
|
||||
* of the author of the post, so the message can be traced back to him.
|
||||
* Or "Organization: <org>" which contain the name of the organization
|
||||
* the post originates from)
|
||||
*
|
||||
* @param string $subject The subject of the post.
|
||||
* @param string $newsgroup The newsgroup to post to.
|
||||
* @param string $from Name + email-adress of sender.
|
||||
* @param string $body The body of the post itself.
|
||||
* @param optional string $aditional Aditional headers to send.
|
||||
*
|
||||
* @return mixed (string) server response on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*/
|
||||
function post($subject, $newsgroup, $from, $body, $aditional = '')
|
||||
{
|
||||
return $this->cmdPost($newsgroup, $subject, $body, $from, $aditional);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getArticleRaw()
|
||||
|
||||
/**
|
||||
* Get an article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
* @param bool $implode When true the result array is imploded to a string, defaults to true.
|
||||
*
|
||||
* @return mixed (array/string) The headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see getHeaderRaw()
|
||||
* @see getBodyRaw()
|
||||
*/
|
||||
function getArticleRaw($article, $implode = true)
|
||||
{
|
||||
$data = $this->cmdArticle($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getArticle()
|
||||
|
||||
/**
|
||||
* Get an article (deprecated)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
*
|
||||
* @return mixed (string) The headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @deprecated Use getArticleRaw() instead
|
||||
*/
|
||||
function getArticle($article)
|
||||
{
|
||||
return $this->getArticleRaw($article);
|
||||
}
|
||||
|
||||
function get_article($article)
|
||||
{
|
||||
return $this->getArticle($article);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getHeaderRaw()
|
||||
|
||||
/**
|
||||
* Get the headers of an article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the (string) message-id or the (int) message-number on the server of the article to fetch.
|
||||
* @param bool $implode When true the result array is imploded to a string, defaults to true.
|
||||
*
|
||||
* @return mixed (array/string) headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see getArticleRaw()
|
||||
* @see getBodyRaw()
|
||||
*/
|
||||
function getHeaderRaw($article, $implode = true)
|
||||
{
|
||||
$data = $this->cmdHead($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getHeaders()
|
||||
|
||||
/**
|
||||
* Get the headers of an article (deprecated)
|
||||
*
|
||||
* @param mixed $article Either the (string) message-id or the (int) message-number on the server of the article to fetch.
|
||||
*
|
||||
* @return mixed (string) headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @deprecated Use getHeaderRaw() instead
|
||||
*/
|
||||
function getHeaders($article)
|
||||
{
|
||||
return $this->getHeaderRaw($article);
|
||||
}
|
||||
|
||||
function get_headers($article)
|
||||
{
|
||||
return $this->getHeaders($article);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getBodyRaw()
|
||||
|
||||
/**
|
||||
* Get the body of an article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
* @param bool $implode When true the result array is imploded to a string, defaults to true.
|
||||
*
|
||||
* @return mixed (array/string) headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see getHeaderRaw()
|
||||
* @see getArticleRaw()
|
||||
*/
|
||||
function getBodyRaw($article, $implode = true)
|
||||
{
|
||||
$data = $this->cmdBody($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getBody()
|
||||
|
||||
/**
|
||||
* Get the body of an article (deprecated)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
*
|
||||
* @return mixed (string) headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @deprecated Use getBodyRaw() instead
|
||||
*/
|
||||
function getBody($article)
|
||||
{
|
||||
return $this->getBodyRaw($article);
|
||||
}
|
||||
|
||||
function get_body($article)
|
||||
{
|
||||
return $this->getBody($article);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getDate()
|
||||
|
||||
/**
|
||||
* Get the NNTP-server's internal date
|
||||
*
|
||||
* Get the date from the newsserver format of returned date:
|
||||
*
|
||||
* @param optional int $format
|
||||
* - 0: $date - timestamp
|
||||
* - 1: $date['y'] - year
|
||||
* $date['m'] - month
|
||||
* $date['d'] - day
|
||||
*
|
||||
* @return mixed (mixed) date on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
*/
|
||||
function getDate($format = 1)
|
||||
{
|
||||
$date = $this->cmdDate();
|
||||
if (PEAR::isError($date)) {
|
||||
return $date;
|
||||
}
|
||||
|
||||
switch ($format) {
|
||||
case 1:
|
||||
return array('y' => substr($date, 0, 4), 'm' => substr($date, 4, 2), 'd' => substr($date, 6, 2));
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
return $date;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ date()
|
||||
|
||||
/**
|
||||
* @return mixed (array) date on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*
|
||||
* @deprecated Use getDate() instead
|
||||
*/
|
||||
function date()
|
||||
{
|
||||
return $this->getDate();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ count()
|
||||
|
||||
/**
|
||||
* Number of articles in currently selected group
|
||||
*
|
||||
* @return integer count
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::selectGroup()
|
||||
* @see Net_NNTP::group()
|
||||
* @see Net_NNTP::first()
|
||||
* @see Net_NNTP::last()
|
||||
*/
|
||||
function count()
|
||||
{
|
||||
return $this->_currentGroup['count'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ last()
|
||||
|
||||
/**
|
||||
* Maximum article number in current group
|
||||
*
|
||||
* @return integer maximum
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::selectGroup()
|
||||
* @see Net_NNTP::group()
|
||||
* @see Net_NNTP::first()
|
||||
* @see Net_NNTP::count()
|
||||
*/
|
||||
function last()
|
||||
{
|
||||
return $this->_currentGroup['last'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ max()
|
||||
|
||||
/**
|
||||
* @return integer maximum
|
||||
* @access public
|
||||
*
|
||||
* @deprecated Use last() instead
|
||||
*/
|
||||
function max()
|
||||
{
|
||||
return $this->last();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ first()
|
||||
|
||||
/**
|
||||
* Minimum article number in current group
|
||||
*
|
||||
* @return integer minimum
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::selectGroup()
|
||||
* @see Net_NNTP::group()
|
||||
* @see Net_NNTP::last()
|
||||
* @see Net_NNTP::count()
|
||||
*/
|
||||
function first()
|
||||
{
|
||||
return $this->_currentGroup['first'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ min()
|
||||
|
||||
/**
|
||||
* @return integer minimum
|
||||
* @access public
|
||||
*
|
||||
* @deprecated Use first() instead
|
||||
*/
|
||||
function min()
|
||||
{
|
||||
return $this->first();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ group()
|
||||
|
||||
/**
|
||||
* Currently selected group
|
||||
*
|
||||
* @return string group
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP::selectGroup()
|
||||
* @see Net_NNTP::first()
|
||||
* @see Net_NNTP::last()
|
||||
* @see Net_NNTP::count()
|
||||
*/
|
||||
function group()
|
||||
{
|
||||
return $this->_currentGroup['group'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ splitHeaders()
|
||||
|
||||
/**
|
||||
* Get the headers of an article from the currently open connection, and parse them into a keyed array.
|
||||
*
|
||||
* @param mixed $article Either the (string) message-id or the (int) message-number on the server of the article to fetch.
|
||||
*
|
||||
* @return mixed (array) Assoc array with headers names as key on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*/
|
||||
function splitHeaders($article)
|
||||
{
|
||||
// Retrieve headers
|
||||
$headers = $this->getHeaderRaw($article, false);
|
||||
if (PEAR::isError($headers)) {
|
||||
return PEAR::throwError($headers);
|
||||
}
|
||||
|
||||
$return = array();
|
||||
|
||||
// Loop through all header field lines
|
||||
foreach ($headers as $field) {
|
||||
// Separate header name and value
|
||||
if (!preg_match('/([\S]+)\:\s*(.*)\s*/', $field, $matches)) {
|
||||
// Fail...
|
||||
}
|
||||
$name = $matches[1];
|
||||
$value = $matches[2];
|
||||
unset($matches);
|
||||
|
||||
// Add header to $return array
|
||||
if (isset($return[$name]) AND is_array($return[$name])) {
|
||||
// The header name has already been used at least two times.
|
||||
$return[$name][] = $value;
|
||||
} elseif (isset($return[$name])) {
|
||||
// The header name has already been used one time -> change to nedted values.
|
||||
$return[$name] = array($return[$name], $value);
|
||||
} else {
|
||||
// The header name has not used until now.
|
||||
$return[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
function split_headers($article)
|
||||
{
|
||||
return $this->splitHeaders($article);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ responseCode()
|
||||
|
||||
/**
|
||||
* returns the response code of a newsserver command
|
||||
*
|
||||
* @param string $response newsserver answer
|
||||
*
|
||||
* @return integer response code
|
||||
* @access public
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
function responseCode($response)
|
||||
{
|
||||
$parts = explode(' ', ltrim($response), 2);
|
||||
return (int) $parts[0];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ _getData()
|
||||
|
||||
/**
|
||||
* Get data until a line with only a '.' in it is read and return data.
|
||||
*
|
||||
* @return mixed (string) data on success or (object) pear_error on failure
|
||||
* @access private
|
||||
*
|
||||
* @deprecated Use _getTextResponse() instead
|
||||
*/
|
||||
function _getData()
|
||||
{
|
||||
return $this->_getTextResponse();
|
||||
}
|
||||
|
||||
function get_data()
|
||||
{
|
||||
return $this->_getData();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ command()
|
||||
|
||||
/**
|
||||
* Issue a command to the NNTP server
|
||||
*
|
||||
* @param string $cmd The command to launch, ie: "ARTICLE 1004853"
|
||||
*
|
||||
* @return mixed (int) response code on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*/
|
||||
function command($cmd)
|
||||
{
|
||||
$code = $this->_sendCommand($cmd);
|
||||
if (PEAR::isError($code)) {
|
||||
return PEAR::throwError($code);
|
||||
}
|
||||
|
||||
return $code.' '.$this->currentStatusResponse()."\r\n";
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
?>
|
||||
553
include/pear/Net/NNTP/Client.php
Normal file
553
include/pear/Net/NNTP/Client.php
Normal file
@@ -0,0 +1,553 @@
|
||||
<?php
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | |
|
||||
// | Copyright © 2003 Heino H. Gehlsen. All Rights Reserved. |
|
||||
// | http://www.heino.gehlsen.dk/software/license |
|
||||
// | |
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | |
|
||||
// | This work (including software, documents, or other related items) is |
|
||||
// | being provided by the copyright holders under the following license. |
|
||||
// | By obtaining, using and/or copying this work, you (the licensee) |
|
||||
// | agree that you have read, understood, and will comply with the |
|
||||
// | following terms and conditions: |
|
||||
// | |
|
||||
// | Permission to use, copy, modify, and distribute this software and |
|
||||
// | its documentation, with or without modification, for any purpose and |
|
||||
// | without fee or royalty is hereby granted, provided that you include |
|
||||
// | the following on ALL copies of the software and documentation or |
|
||||
// | portions thereof, including modifications, that you make: |
|
||||
// | |
|
||||
// | 1. The full text of this NOTICE in a location viewable to users of |
|
||||
// | the redistributed or derivative work. |
|
||||
// | |
|
||||
// | 2. Any pre-existing intellectual property disclaimers, notices, or |
|
||||
// | terms and conditions. If none exist, a short notice of the |
|
||||
// | following form (hypertext is preferred, text is permitted) should |
|
||||
// | be used within the body of any redistributed or derivative code: |
|
||||
// | "Copyright © 2003 Heino H. Gehlsen. All Rights Reserved. |
|
||||
// | http://www.heino.gehlsen.dk/software/license" |
|
||||
// | |
|
||||
// | 3. Notice of any changes or modifications to the files, including |
|
||||
// | the date changes were made. (We recommend you provide URIs to |
|
||||
// | the location from which the code is derived.) |
|
||||
// | |
|
||||
// | THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT |
|
||||
// | HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, |
|
||||
// | INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR |
|
||||
// | FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE |
|
||||
// | OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, |
|
||||
// | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. |
|
||||
// | |
|
||||
// | COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
||||
// | SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE |
|
||||
// | SOFTWARE OR DOCUMENTATION. |
|
||||
// | |
|
||||
// | The name and trademarks of copyright holders may NOT be used in |
|
||||
// | advertising or publicity pertaining to the software without specific, |
|
||||
// | written prior permission. Title to copyright in this software and any |
|
||||
// | associated documentation will at all times remain with copyright |
|
||||
// | holders. |
|
||||
// | |
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | |
|
||||
// | This license is based on the "W3C® SOFTWARE NOTICE AND LICENSE". |
|
||||
// | No changes have been made to the "W3C® SOFTWARE NOTICE AND LICENSE", |
|
||||
// | except for the references to the copyright holder, which has either |
|
||||
// | been changes or removed. |
|
||||
// | |
|
||||
// +-----------------------------------------------------------------------+
|
||||
// $Id: Client.php,v 1.2.2.2 2005/01/14 20:03:22 heino Exp $
|
||||
|
||||
require_once 'Net/NNTP/Protocol/Client.php';
|
||||
|
||||
|
||||
// {{{ constants
|
||||
|
||||
/* NNTP Authentication modes */
|
||||
define('NET_NNTP_CLIENT_AUTH_ORIGINAL', 'original');
|
||||
define('NET_NNTP_CLIENT_AUTH_SIMPLE', 'simple');
|
||||
define('NET_NNTP_CLIENT_AUTH_GENERIC', 'generic');
|
||||
|
||||
// }}}
|
||||
// {{{ Net_NNTP_Client
|
||||
|
||||
/**
|
||||
* Implementation of the client side of NNTP (Network News Transfer Protocol)
|
||||
*
|
||||
* The Net_NNTP_Client class is a frontend class to the Net_NNTP_Protocol_Client class.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_NNTP
|
||||
* @author Heino H. Gehlsen <heino@gehlsen.dk>
|
||||
* @version $Id: Client.php,v 1.2.2.2 2005/01/14 20:03:22 heino Exp $
|
||||
* @access public
|
||||
* @see Net_NNTP_Protocol_Client
|
||||
* @since Class available since Release 0.11.0
|
||||
*/
|
||||
class Net_NNTP_Client extends Net_NNTP_Protocol_Client
|
||||
{
|
||||
// {{{ properties
|
||||
|
||||
/**
|
||||
* Used for storing information about the currently selected group
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
* @since 0.3
|
||||
*/
|
||||
var $_currentGroup = null;
|
||||
|
||||
// }}}
|
||||
// {{{ constructor
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Net_NNTP_Client()
|
||||
{
|
||||
parent::Net_NNTP_Protocol_Client();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ connect()
|
||||
|
||||
/**
|
||||
* Connect to the NNTP-server.
|
||||
*
|
||||
* @param optional string $host The adress of the NNTP-server to connect to.
|
||||
* @param optional int $port The port to connect to.
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::quit()
|
||||
* @see Net_NNTP_Client::authenticate()
|
||||
* @see Net_NNTP_Client::connectAuthenticated()
|
||||
*/
|
||||
function connect($host = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_HOST,
|
||||
$port = NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT)
|
||||
{
|
||||
return parent::connect($host, $port);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ quit()
|
||||
|
||||
/**
|
||||
* Close connection to the newsserver
|
||||
*
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::connect()
|
||||
*/
|
||||
function quit()
|
||||
{
|
||||
return $this->cmdQuit();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ authenticate()
|
||||
|
||||
/**
|
||||
* Authenticate
|
||||
*
|
||||
* Auth process (not yet standarized but used any way)
|
||||
* http://www.mibsoftware.com/userkt/nntpext/index.html
|
||||
*
|
||||
* @param string $user The username
|
||||
* @param optional string $pass The password
|
||||
* @param optional string $mode The authentication mode (original, simple, generic).
|
||||
*
|
||||
* @return mixed (bool) true on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::connect()
|
||||
* @see Net_NNTP_Client::connectAuthenticated()
|
||||
*/
|
||||
function authenticate($user, $pass, $mode = NET_NNTP_CLIENT_AUTH_ORIGINAL)
|
||||
{
|
||||
// Username is a must...
|
||||
if ($user == null) {
|
||||
return PEAR::throwError('No username supplied', null);
|
||||
}
|
||||
|
||||
// Use selected authentication method
|
||||
switch ($mode) {
|
||||
case NET_NNTP_CLIENT_AUTH_ORIGINAL:
|
||||
return $this->cmdAuthinfo($user, $pass);
|
||||
break;
|
||||
case NET_NNTP_CLIENT_AUTH_SIMPLE:
|
||||
return $this->cmdAuthinfoSimple($user, $pass);
|
||||
break;
|
||||
case NET_NNTP_CLIENT_AUTH_GENERIC:
|
||||
return $this->cmdAuthinfoGeneric($user, $pass);
|
||||
break;
|
||||
default:
|
||||
return PEAR::throwError("The auth mode: '$mode' is unknown", null);
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ isConnected()
|
||||
|
||||
/**
|
||||
* Test whether a connection is currently open.
|
||||
*
|
||||
* @return bool true or false
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::connect()
|
||||
* @see Net_NNTP_Client::quit()
|
||||
*/
|
||||
function isConnected()
|
||||
{
|
||||
return parent::isConnected();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ selectGroup()
|
||||
|
||||
/**
|
||||
* Selects a newsgroup
|
||||
*
|
||||
* @param string $newsgroup Newsgroup name
|
||||
*
|
||||
* @return mixed (array) Info about the newsgroup on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::group()
|
||||
* @see Net_NNTP_Client::first()
|
||||
* @see Net_NNTP_Client::last()
|
||||
* @see Net_NNTP_Client::count()
|
||||
* @see Net_NNTP_Client::getGroups()
|
||||
*/
|
||||
function selectGroup($newsgroup)
|
||||
{
|
||||
$response_arr = $this->cmdGroup($newsgroup);
|
||||
if (PEAR::isError($response_arr)) {
|
||||
return $response_arr;
|
||||
}
|
||||
|
||||
// Store group info in the object
|
||||
$this->_currentGroup = $response_arr;
|
||||
|
||||
return $response_arr;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getGroups()
|
||||
|
||||
/**
|
||||
* Fetches a list of all avaible newsgroups
|
||||
*
|
||||
* @return mixed (array) nested array with informations about existing newsgroups on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::selectGroup()
|
||||
* @see Net_NNTP_Client::getDescriptions()
|
||||
*/
|
||||
function getGroups()
|
||||
{
|
||||
// Get groups
|
||||
$groups = $this->cmdList();
|
||||
if (PEAR::isError($groups)) {
|
||||
return $groups;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getDescriptions()
|
||||
|
||||
/**
|
||||
* Fetches a list of all avaible newsgroup descriptions.
|
||||
*
|
||||
* @return mixed (array) nested array with description of existing newsgroups on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getGroups()
|
||||
*/
|
||||
function getDescriptions()
|
||||
{
|
||||
// Get group descriptions
|
||||
$descriptions = $this->cmdListNewsgroups();
|
||||
if (PEAR::isError($descriptions)) {
|
||||
return $descriptions;
|
||||
}
|
||||
|
||||
return $descriptions;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getOverview()
|
||||
|
||||
/**
|
||||
* Fetch message header fields from message number $first to $last
|
||||
*
|
||||
* The format of the returned array is:
|
||||
* $messages[message_id][header_name]
|
||||
*
|
||||
* @param integer $first first article to fetch
|
||||
* @param integer $last last article to fetch
|
||||
*
|
||||
* @return mixed (array) nested array of message and their headers on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getOverviewFormat()
|
||||
* @see Net_NNTP_Client::getReferencesOverview()
|
||||
*/
|
||||
function getOverview($first, $last)
|
||||
{
|
||||
$overview = $this->cmdXOver($first.'-'.$last);
|
||||
if (PEAR::isError($overview)) {
|
||||
return $overview;
|
||||
}
|
||||
|
||||
return $overview;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getOverviewFmt()
|
||||
|
||||
/**
|
||||
* Returns a list of avaible headers which are send from NNTP-server to the client for every news message
|
||||
*
|
||||
* @return mixed (array) header names on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getOverview()
|
||||
*/
|
||||
function getOverviewFormat()
|
||||
{
|
||||
return $this->cmdListOverviewFmt();
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ post()
|
||||
|
||||
/**
|
||||
* Post an article to a number of newsgroups.
|
||||
*
|
||||
* (Among the aditional headers you might think of adding could be:
|
||||
* "NNTP-Posting-Host: <ip-of-author>", which should contain the IP-address
|
||||
* of the author of the post, so the message can be traced back to him.
|
||||
* Or "Organization: <org>" which contain the name of the organization
|
||||
* the post originates from)
|
||||
*
|
||||
* @param string $newsgroups The newsgroup to post to.
|
||||
* @param string $subject The subject of the post.
|
||||
* @param string $body The body of the post itself.
|
||||
* @param string $from Name + email-adress of sender.
|
||||
* @param optional string $aditional Aditional headers to send.
|
||||
*
|
||||
* @return mixed (string) server response on success or (object) pear_error on failure
|
||||
* @access public
|
||||
*/
|
||||
function post($newsgroups, $subject, $body, $from, $aditional = null)
|
||||
{
|
||||
return $this->cmdPost($newsgroups, $subject, $body, $from, $aditional);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getArticleRaw()
|
||||
|
||||
/**
|
||||
* Get a article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
* @param optional bool $implode When true the result array is imploded to a string, defaults to false.
|
||||
*
|
||||
* @return mixed (array/string) The article on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getArticle()
|
||||
* @see Net_NNTP_Client::getHeaderRaw()
|
||||
* @see Net_NNTP_Client::getBodyRaw()
|
||||
*/
|
||||
function getArticleRaw($article, $implode = false)
|
||||
{
|
||||
$data = $this->cmdArticle($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getHeaderRaw()
|
||||
|
||||
/**
|
||||
* Get the header of an article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the (string) message-id or the (int) message-number on the server of the article to fetch.
|
||||
* @param optional bool $implode When true the result array is imploded to a string, defaults to false.
|
||||
*
|
||||
* @return mixed (array/string) header fields on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getHeader()
|
||||
* @see Net_NNTP_Client::getArticleRaw()
|
||||
* @see Net_NNTP_Client::getBodyRaw()
|
||||
*/
|
||||
function getHeaderRaw($article, $implode = false)
|
||||
{
|
||||
$data = $this->cmdHead($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getBodyRaw()
|
||||
|
||||
/**
|
||||
* Get the body of an article (raw data)
|
||||
*
|
||||
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch.
|
||||
* @param optional bool $implode When true the result array is imploded to a string, defaults to false.
|
||||
*
|
||||
* @return mixed (array/string) body on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @see Net_NNTP_Client::getBody()
|
||||
* @see Net_NNTP_Client::getHeaderRaw()
|
||||
* @see Net_NNTP_Client::getArticleRaw()
|
||||
*/
|
||||
function getBodyRaw($article, $implode = false)
|
||||
{
|
||||
$data = $this->cmdBody($article);
|
||||
if (PEAR::isError($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($implode == true) {
|
||||
$data = implode("\r\n", $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ getDate()
|
||||
|
||||
/**
|
||||
* Get the NNTP-server's internal date
|
||||
*
|
||||
* Get the date from the newsserver format of returned date:
|
||||
*
|
||||
* @param optional int $format
|
||||
* - 0: $date - timestamp
|
||||
* - 1: $date['y'] - year
|
||||
* $date['m'] - month
|
||||
* $date['d'] - day
|
||||
*
|
||||
* @return mixed (mixed) date on success or (object) pear_error on failure
|
||||
* @access public
|
||||
* @since 0.3
|
||||
*/
|
||||
function getDate($format = 1)
|
||||
{
|
||||
$date = $this->cmdDate();
|
||||
if (PEAR::isError($date)) {
|
||||
return $date;
|
||||
}
|
||||
|
||||
switch ($format) {
|
||||
case 1:
|
||||
return array('y' => substr($date, 0, 4), 'm' => substr($date, 4, 2), 'd' => substr($date, 6, 2));
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
return $date;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ count()
|
||||
|
||||
/**
|
||||
* Number of articles in currently selected group
|
||||
*
|
||||
* @return integer number of article in group
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP_Client::group()
|
||||
* @see Net_NNTP_Client::first()
|
||||
* @see Net_NNTP_Client::last()
|
||||
* @see Net_NNTP_Client::selectGroup()
|
||||
*/
|
||||
function count()
|
||||
{
|
||||
return $this->_currentGroup['count'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ last()
|
||||
|
||||
/**
|
||||
* Maximum article number in currently selected group
|
||||
*
|
||||
* @return integer number of last article
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP_Client::first()
|
||||
* @see Net_NNTP_Client::group()
|
||||
* @see Net_NNTP_Client::count()
|
||||
* @see Net_NNTP_Client::selectGroup()
|
||||
*/
|
||||
function last()
|
||||
{
|
||||
return $this->_currentGroup['last'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ first()
|
||||
|
||||
/**
|
||||
* Minimum article number in currently selected group
|
||||
*
|
||||
* @return integer number of first article
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP_Client::last()
|
||||
* @see Net_NNTP_Client::group()
|
||||
* @see Net_NNTP_Client::count()
|
||||
* @see Net_NNTP_Client::selectGroup()
|
||||
*/
|
||||
function first()
|
||||
{
|
||||
return $this->_currentGroup['first'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ group()
|
||||
|
||||
/**
|
||||
* Currently selected group
|
||||
*
|
||||
* @return string group name
|
||||
* @access public
|
||||
* @since 0.3
|
||||
* @see Net_NNTP_Client::first()
|
||||
* @see Net_NNTP_Client::last()
|
||||
* @see Net_NNTP_Client::count()
|
||||
* @see Net_NNTP_Client::selectGroup()
|
||||
*/
|
||||
function group()
|
||||
{
|
||||
return $this->_currentGroup['group'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
?>
|
||||
1170
include/pear/Net/NNTP/Protocol/Client.php
Normal file
1170
include/pear/Net/NNTP/Protocol/Client.php
Normal file
File diff suppressed because it is too large
Load Diff
970
include/pear/Net/SMTP.php
Normal file
970
include/pear/Net/SMTP.php
Normal file
@@ -0,0 +1,970 @@
|
||||
<?php
|
||||
/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
|
||||
// +----------------------------------------------------------------------+
|
||||
// | PHP Version 4 |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Copyright (c) 1997-2003 The PHP Group |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | This source file is subject to version 2.02 of the PHP license, |
|
||||
// | that is bundled with this package in the file LICENSE, and is |
|
||||
// | available at through the world-wide-web at |
|
||||
// | http://www.php.net/license/2_02.txt. |
|
||||
// | If you did not receive a copy of the PHP license and are unable to |
|
||||
// | obtain it through the world-wide-web, please send a note to |
|
||||
// | license@php.net so we can mail you a copy immediately. |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Authors: Chuck Hagenbuch <chuck@horde.org> |
|
||||
// | Jon Parise <jon@php.net> |
|
||||
// | Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar> |
|
||||
// +----------------------------------------------------------------------+
|
||||
|
||||
require_once 'PEAR.php';
|
||||
require_once 'Net/Socket.php';
|
||||
|
||||
/**
|
||||
* Provides an implementation of the SMTP protocol using PEAR's
|
||||
* Net_Socket:: class.
|
||||
*
|
||||
* @package Net_SMTP
|
||||
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||
* @author Jon Parise <jon@php.net>
|
||||
* @author Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>
|
||||
*
|
||||
* @example basic.php A basic implementation of the Net_SMTP package.
|
||||
*/
|
||||
class Net_SMTP
|
||||
{
|
||||
/**
|
||||
* The server to connect to.
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $host = 'localhost';
|
||||
|
||||
/**
|
||||
* The port to connect to.
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
var $port = 25;
|
||||
|
||||
/**
|
||||
* The value to give when sending EHLO or HELO.
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $localhost = 'localhost';
|
||||
|
||||
/**
|
||||
* List of supported authentication methods, in preferential order.
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN');
|
||||
|
||||
/**
|
||||
* Should debugging output be enabled?
|
||||
* @var boolean
|
||||
* @access private
|
||||
*/
|
||||
var $_debug = false;
|
||||
|
||||
/**
|
||||
* The socket resource being used to connect to the SMTP server.
|
||||
* @var resource
|
||||
* @access private
|
||||
*/
|
||||
var $_socket = null;
|
||||
|
||||
/**
|
||||
* The most recent server response code.
|
||||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
var $_code = -1;
|
||||
|
||||
/**
|
||||
* The most recent server response arguments.
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $_arguments = array();
|
||||
|
||||
/**
|
||||
* Stores detected features of the SMTP server.
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $_esmtp = array();
|
||||
|
||||
/**
|
||||
* Instantiates a new Net_SMTP object, overriding any defaults
|
||||
* with parameters that are passed in.
|
||||
*
|
||||
* @param string The server to connect to.
|
||||
* @param int The port to connect to.
|
||||
* @param string The value to give when sending EHLO or HELO.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function Net_SMTP($host = null, $port = null, $localhost = null)
|
||||
{
|
||||
if (isset($host)) $this->host = $host;
|
||||
if (isset($port)) $this->port = $port;
|
||||
if (isset($localhost)) $this->localhost = $localhost;
|
||||
|
||||
$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) {
|
||||
$pos = array_search('DIGEST-MD5', $this->auth_methods);
|
||||
unset($this->auth_methods[$pos]);
|
||||
$pos = array_search('CRAM-MD5', $this->auth_methods);
|
||||
unset($this->auth_methods[$pos]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the debugging flag.
|
||||
*
|
||||
* @param boolean $debug New value for the debugging flag.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function setDebug($debug)
|
||||
{
|
||||
$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.1.0
|
||||
*/
|
||||
function _send($data)
|
||||
{
|
||||
if ($this->_debug) {
|
||||
echo "DEBUG: Send: $data\n";
|
||||
}
|
||||
|
||||
if (PEAR::isError($error = $this->_socket->write($data))) {
|
||||
return new PEAR_Error('Failed to write to socket: ' .
|
||||
$error->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to the server with an optional string of arguments.
|
||||
* A carriage return / linefeed (CRLF) sequence will be appended to each
|
||||
* command string before it is sent to the SMTP server.
|
||||
*
|
||||
* @param string $command The SMTP command to send to the server.
|
||||
* @param string $args A string of optional arguments to append
|
||||
* to the command.
|
||||
*
|
||||
* @return mixed The result of the _send() call.
|
||||
*
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _put($command, $args = '')
|
||||
{
|
||||
if (!empty($args)) {
|
||||
return $this->_send($command . ' ' . $args . "\r\n");
|
||||
}
|
||||
|
||||
return $this->_send($command . "\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a reply from the SMTP server. The reply consists of a response
|
||||
* code and a response message.
|
||||
*
|
||||
* @param mixed $valid The set of valid response codes. These
|
||||
* may be specified as an array of integer
|
||||
* values or as a single integer value.
|
||||
*
|
||||
* @return mixed True if the server returned a valid response code or
|
||||
* a PEAR_Error object is an error condition is reached.
|
||||
*
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*
|
||||
* @see getResponse
|
||||
*/
|
||||
function _parseResponse($valid)
|
||||
{
|
||||
$this->_code = -1;
|
||||
$this->_arguments = array();
|
||||
|
||||
while ($line = $this->_socket->readLine()) {
|
||||
if ($this->_debug) {
|
||||
echo "DEBUG: Recv: $line\n";
|
||||
}
|
||||
|
||||
/* If we receive an empty line, the connection has been closed. */
|
||||
if (empty($line)) {
|
||||
$this->disconnect();
|
||||
return new PEAR_Error("Connection was unexpectedly closed");
|
||||
}
|
||||
|
||||
/* Read the code and store the rest in the arguments array. */
|
||||
$code = substr($line, 0, 3);
|
||||
$this->_arguments[] = trim(substr($line, 4));
|
||||
|
||||
/* Check the syntax of the response code. */
|
||||
if (is_numeric($code)) {
|
||||
$this->_code = (int)$code;
|
||||
} else {
|
||||
$this->_code = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this is not a multiline response, we're done. */
|
||||
if (substr($line, 3, 1) != '-') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare the server's response code with the valid code. */
|
||||
if (is_int($valid) && ($this->_code === $valid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we were given an array of valid response codes, check each one. */
|
||||
if (is_array($valid)) {
|
||||
foreach ($valid as $valid_code) {
|
||||
if ($this->_code === $valid_code) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new PEAR_Error("Invalid response code received from server");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a 2-tuple containing the last response from the SMTP server.
|
||||
*
|
||||
* @return array A two-element array: the first element contains the
|
||||
* response code as an integer and the second element
|
||||
* contains the response's arguments as a string.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function getResponse()
|
||||
{
|
||||
return array($this->_code, join("\n", $this->_arguments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to connect to the SMTP server.
|
||||
*
|
||||
* @param int $timeout The timeout value (in seconds) for the
|
||||
* socket connection.
|
||||
* @param bool $persistent Should a persistent socket connection
|
||||
* be used?
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function connect($timeout = null, $persistent = false)
|
||||
{
|
||||
$result = $this->_socket->connect($this->host, $this->port,
|
||||
$persistent, $timeout);
|
||||
if (PEAR::isError($result)) {
|
||||
return new PEAR_Error('Failed to connect socket: ' .
|
||||
$result->getMessage());
|
||||
}
|
||||
|
||||
if (PEAR::isError($error = $this->_parseResponse(220))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_negotiate())) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to disconnect from the SMTP server.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function disconnect()
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('QUIT'))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(221))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_socket->disconnect())) {
|
||||
return new PEAR_Error('Failed to disconnect socket: ' .
|
||||
$error->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to send the EHLO command and obtain a list of ESMTP
|
||||
* extensions available, and failing that just send HELO.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
*
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _negotiate()
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
if (PEAR::isError($this->_parseResponse(250))) {
|
||||
/* If we receive a 503 response, we're already authenticated. */
|
||||
if ($this->_code === 503) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the EHLO failed, try the simpler HELO command. */
|
||||
if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($this->_parseResponse(250))) {
|
||||
return new PEAR_Error('HELO was not accepted: ', $this->_code);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->_arguments as $argument) {
|
||||
$verb = strtok($argument, ' ');
|
||||
$arguments = substr($argument, strlen($verb) + 1,
|
||||
strlen($argument) - strlen($verb) - 1);
|
||||
$this->_esmtp[$verb] = $arguments;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the best authentication method that the server
|
||||
* has advertised.
|
||||
*
|
||||
* @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.1.0
|
||||
*/
|
||||
function _getBestAuthMethod()
|
||||
{
|
||||
$available_methods = explode(' ', $this->_esmtp['AUTH']);
|
||||
|
||||
foreach ($this->auth_methods as $method) {
|
||||
if (in_array($method, $available_methods)) {
|
||||
return $method;
|
||||
}
|
||||
}
|
||||
|
||||
return new PEAR_Error('No supported authentication methods');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to do SMTP authentication.
|
||||
*
|
||||
* @param string The userid to authenticate as.
|
||||
* @param string The password to authenticate with.
|
||||
* @param string The requested authentication method. If none is
|
||||
* specified, the best supported method will be used.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function auth($uid, $pwd , $method = '')
|
||||
{
|
||||
if (empty($this->_esmtp['AUTH'])) {
|
||||
return new PEAR_Error('SMTP server does no support authentication');
|
||||
}
|
||||
|
||||
/*
|
||||
* If no method has been specified, get the name of the best supported
|
||||
* method advertised by the SMTP server.
|
||||
*/
|
||||
if (empty($method)) {
|
||||
if (PEAR::isError($method = $this->_getBestAuthMethod())) {
|
||||
/* Return the PEAR_Error object from _getBestAuthMethod(). */
|
||||
return $method;
|
||||
}
|
||||
} else {
|
||||
$method = strtoupper($method);
|
||||
if (!in_array($method, $this->auth_methods)) {
|
||||
return new PEAR_Error("$method is not a supported authentication 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;
|
||||
default:
|
||||
$result = new PEAR_Error("$method is not a supported authentication method");
|
||||
break;
|
||||
}
|
||||
|
||||
/* If an error was encountered, return the PEAR_Error object. */
|
||||
if (PEAR::isError($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/* RFC-2554 requires us to re-negotiate ESMTP after an AUTH. */
|
||||
if (PEAR::isError($error = $this->_negotiate())) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the user using the DIGEST-MD5 method.
|
||||
*
|
||||
* @param string The userid to authenticate as.
|
||||
* @param string The password to authenticate with.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _authDigest_MD5($uid, $pwd)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
/* 503: Error: already authenticated */
|
||||
if ($this->_code === 503) {
|
||||
return true;
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
$challenge = base64_decode($this->_arguments[0]);
|
||||
$digest = &Auth_SASL::factory('digestmd5');
|
||||
$auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge,
|
||||
$this->host, "smtp"));
|
||||
|
||||
if (PEAR::isError($error = $this->_put($auth_str))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't use the protocol's third step because SMTP doesn't allow
|
||||
* subsequent authentication, so we just silently ignore it.
|
||||
*/
|
||||
if (PEAR::isError($error = $this->_put(' '))) {
|
||||
return $error;
|
||||
}
|
||||
/* 235: Authentication successful */
|
||||
if (PEAR::isError($error = $this->_parseResponse(235))) {
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the user using the CRAM-MD5 method.
|
||||
*
|
||||
* @param string The userid to authenticate as.
|
||||
* @param string The password to authenticate with.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _authCRAM_MD5($uid, $pwd)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
/* 503: Error: already authenticated */
|
||||
if ($this->_code === 503) {
|
||||
return true;
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
$challenge = base64_decode($this->_arguments[0]);
|
||||
$cram = &Auth_SASL::factory('crammd5');
|
||||
$auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
|
||||
|
||||
if (PEAR::isError($error = $this->_put($auth_str))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
/* 235: Authentication successful */
|
||||
if (PEAR::isError($error = $this->_parseResponse(235))) {
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the user using the LOGIN method.
|
||||
*
|
||||
* @param string The userid to authenticate as.
|
||||
* @param string The password to authenticate with.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _authLogin($uid, $pwd)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
/* 503: Error: already authenticated */
|
||||
if ($this->_code === 503) {
|
||||
return true;
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
if (PEAR::isError($error = $this->_put(base64_encode($uid)))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
/* 235: Authentication successful */
|
||||
if (PEAR::isError($error = $this->_parseResponse(235))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the user using the PLAIN method.
|
||||
*
|
||||
* @param string The userid to authenticate as.
|
||||
* @param string The password to authenticate with.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access private
|
||||
* @since 1.1.0
|
||||
*/
|
||||
function _authPlain($uid, $pwd)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) {
|
||||
return $error;
|
||||
}
|
||||
/* 334: Continue authentication request */
|
||||
if (PEAR::isError($error = $this->_parseResponse(334))) {
|
||||
/* 503: Error: already authenticated */
|
||||
if ($this->_code === 503) {
|
||||
return true;
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
$auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd);
|
||||
|
||||
if (PEAR::isError($error = $this->_put($auth_str))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
/* 235: Authentication successful */
|
||||
if (PEAR::isError($error = $this->_parseResponse(235))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the HELO command.
|
||||
*
|
||||
* @param string The domain name to say we are.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function helo($domain)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('HELO', $domain))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the MAIL FROM: command.
|
||||
*
|
||||
* @param string The sender (reverse path) to set.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function mailFrom($sender)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('MAIL', "FROM:<$sender>"))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the RCPT TO: command.
|
||||
*
|
||||
* @param string The recipient (forward path) to add.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function rcptTo($recipient)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('RCPT', "TO:<$recipient>"))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(array(250, 251)))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the data so that it meets SMTP standards.
|
||||
*
|
||||
* This is provided as a separate public function to facilitate easier
|
||||
* overloading for the cases where it is desirable to customize the
|
||||
* quoting behavior.
|
||||
*
|
||||
* @param string The message text to quote. The string must be passed
|
||||
* by reference, and the text will be modified in place.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.2
|
||||
*/
|
||||
function quotedata(&$data)
|
||||
{
|
||||
/*
|
||||
* Change Unix (\n) and Mac (\r) linefeeds into Internet-standard CRLF
|
||||
* (\r\n) linefeeds.
|
||||
*/
|
||||
$data = preg_replace("/([^\r]{1})\n/", "\\1\r\n", $data);
|
||||
$data = preg_replace("/\n\n/", "\n\r\n", $data);
|
||||
|
||||
/*
|
||||
* Because a single leading period (.) signifies an end to the data,
|
||||
* legitimate leading periods need to be "doubled" (e.g. '..').
|
||||
*/
|
||||
$data = preg_replace("/\n\./", "\n..", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the DATA command.
|
||||
*
|
||||
* @param string The message body to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function data($data)
|
||||
{
|
||||
/*
|
||||
* RFC 1870, section 3, subsection 3 states "a value of zero indicates
|
||||
* that no fixed maximum message size is in force". Furthermore, it
|
||||
* says that if "the parameter is omitted no information is conveyed
|
||||
* about the server's fixed maximum message size".
|
||||
*/
|
||||
if (isset($this->_esmtp['SIZE']) && ($this->_esmtp['SIZE'] > 0)) {
|
||||
if (strlen($data) >= $this->_esmtp['SIZE']) {
|
||||
$this->disconnect();
|
||||
return new PEAR_Error('Message size excedes the server limit');
|
||||
}
|
||||
}
|
||||
|
||||
/* Quote the data based on the SMTP standards. */
|
||||
$this->quotedata($data);
|
||||
|
||||
if (PEAR::isError($error = $this->_put('DATA'))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(354))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
if (PEAR::isError($this->_send($data . "\r\n.\r\n"))) {
|
||||
return new PEAR_Error('write to socket failed');
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the SEND FROM: command.
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.2.6
|
||||
*/
|
||||
function sendFrom($path)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatibility wrapper for sendFrom().
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.0
|
||||
* @deprecated 1.2.6
|
||||
*/
|
||||
function send_from($path)
|
||||
{
|
||||
return sendFrom($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the SOML FROM: command.
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.2.6
|
||||
*/
|
||||
function somlFrom($path)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatibility wrapper for somlFrom().
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.0
|
||||
* @deprecated 1.2.6
|
||||
*/
|
||||
function soml_from($path)
|
||||
{
|
||||
return somlFrom($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the SAML FROM: command.
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.2.6
|
||||
*/
|
||||
function samlFrom($path)
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatibility wrapper for samlFrom().
|
||||
*
|
||||
* @param string The reverse path to send.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.0
|
||||
* @deprecated 1.2.6
|
||||
*/
|
||||
function saml_from($path)
|
||||
{
|
||||
return samlFrom($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the RSET command.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function rset()
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('RSET'))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the VRFY command.
|
||||
*
|
||||
* @param string The string to verify
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function vrfy($string)
|
||||
{
|
||||
/* Note: 251 is also a valid response code */
|
||||
if (PEAR::isError($error = $this->_put('VRFY', $string))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the NOOP command.
|
||||
*
|
||||
* @return mixed Returns a PEAR_Error with an error message on any
|
||||
* kind of failure, or true on success.
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function noop()
|
||||
{
|
||||
if (PEAR::isError($error = $this->_put('NOOP'))) {
|
||||
return $error;
|
||||
}
|
||||
if (PEAR::isError($error = $this->_parseResponse(250))) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatibility method. identifySender()'s functionality is
|
||||
* now handled internally.
|
||||
*
|
||||
* @return boolean This method always return true.
|
||||
*
|
||||
* @access public
|
||||
* @since 1.0
|
||||
*/
|
||||
function identifySender()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
528
include/pear/Net/Socket.php
Normal file
528
include/pear/Net/Socket.php
Normal file
@@ -0,0 +1,528 @@
|
||||
<?php
|
||||
//
|
||||
// +----------------------------------------------------------------------+
|
||||
// | PHP Version 4 |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Copyright (c) 1997-2003 The PHP Group |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | This source file is subject to version 2.0 of the PHP license, |
|
||||
// | that is bundled with this package in the file LICENSE, and is |
|
||||
// | available at through the world-wide-web at |
|
||||
// | http://www.php.net/license/2_02.txt. |
|
||||
// | If you did not receive a copy of the PHP license and are unable to |
|
||||
// | obtain it through the world-wide-web, please send a note to |
|
||||
// | license@php.net so we can mail you a copy immediately. |
|
||||
// +----------------------------------------------------------------------+
|
||||
// | Authors: Stig Bakken <ssb@php.net> |
|
||||
// | Chuck Hagenbuch <chuck@horde.org> |
|
||||
// +----------------------------------------------------------------------+
|
||||
//
|
||||
// $Id: Socket.php,v 1.24 2005/02/03 20:40:16 chagenbu Exp $
|
||||
|
||||
require_once 'PEAR.php';
|
||||
|
||||
define('NET_SOCKET_READ', 1);
|
||||
define('NET_SOCKET_WRITE', 2);
|
||||
define('NET_SOCKET_ERROR', 3);
|
||||
|
||||
/**
|
||||
* Generalized Socket class.
|
||||
*
|
||||
* @version 1.1
|
||||
* @author Stig Bakken <ssb@php.net>
|
||||
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||
*/
|
||||
class Net_Socket extends PEAR {
|
||||
|
||||
/**
|
||||
* Socket file pointer.
|
||||
* @var resource $fp
|
||||
*/
|
||||
var $fp = null;
|
||||
|
||||
/**
|
||||
* Whether the socket is blocking. Defaults to true.
|
||||
* @var boolean $blocking
|
||||
*/
|
||||
var $blocking = true;
|
||||
|
||||
/**
|
||||
* Whether the socket is persistent. Defaults to false.
|
||||
* @var boolean $persistent
|
||||
*/
|
||||
var $persistent = false;
|
||||
|
||||
/**
|
||||
* The IP address to connect to.
|
||||
* @var string $addr
|
||||
*/
|
||||
var $addr = '';
|
||||
|
||||
/**
|
||||
* The port number to connect to.
|
||||
* @var integer $port
|
||||
*/
|
||||
var $port = 0;
|
||||
|
||||
/**
|
||||
* Number of seconds to wait on socket connections before assuming
|
||||
* there's no more data. Defaults to no timeout.
|
||||
* @var integer $timeout
|
||||
*/
|
||||
var $timeout = false;
|
||||
|
||||
/**
|
||||
* Number of bytes to read at a time in readLine() and
|
||||
* readAll(). Defaults to 2048.
|
||||
* @var integer $lineLength
|
||||
*/
|
||||
var $lineLength = 2048;
|
||||
|
||||
/**
|
||||
* Connect to the specified port. If called when the socket is
|
||||
* already connected, it disconnects and connects again.
|
||||
*
|
||||
* @param string $addr IP address or host name.
|
||||
* @param integer $port TCP port number.
|
||||
* @param boolean $persistent (optional) Whether the connection is
|
||||
* persistent (kept open between requests
|
||||
* by the web server).
|
||||
* @param integer $timeout (optional) How long to wait for data.
|
||||
* @param array $options See options for stream_context_create.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return boolean | PEAR_Error True on success or a PEAR_Error on failure.
|
||||
*/
|
||||
function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
|
||||
{
|
||||
if (is_resource($this->fp)) {
|
||||
@fclose($this->fp);
|
||||
$this->fp = null;
|
||||
}
|
||||
|
||||
if (!$addr) {
|
||||
return $this->raiseError('$addr cannot be empty');
|
||||
} elseif (strspn($addr, '.0123456789') == strlen($addr) ||
|
||||
strstr($addr, '/') !== false) {
|
||||
$this->addr = $addr;
|
||||
} else {
|
||||
$this->addr = @gethostbyname($addr);
|
||||
}
|
||||
|
||||
$this->port = $port % 65536;
|
||||
|
||||
if ($persistent !== null) {
|
||||
$this->persistent = $persistent;
|
||||
}
|
||||
|
||||
if ($timeout !== null) {
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
$openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
if ($options && function_exists('stream_context_create')) {
|
||||
if ($this->timeout) {
|
||||
$timeout = $this->timeout;
|
||||
} else {
|
||||
$timeout = 0;
|
||||
}
|
||||
$context = stream_context_create($options);
|
||||
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
|
||||
} else {
|
||||
if ($this->timeout) {
|
||||
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
|
||||
} else {
|
||||
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$fp) {
|
||||
return $this->raiseError($errstr, $errno);
|
||||
}
|
||||
|
||||
$this->fp = $fp;
|
||||
|
||||
return $this->setBlocking($this->blocking);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the peer, closes the socket.
|
||||
*
|
||||
* @access public
|
||||
* @return mixed true on success or an error object otherwise
|
||||
*/
|
||||
function disconnect()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
@fclose($this->fp);
|
||||
$this->fp = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if the socket is in blocking mode.
|
||||
*
|
||||
* @access public
|
||||
* @return boolean The current blocking mode.
|
||||
*/
|
||||
function isBlocking()
|
||||
{
|
||||
return $this->blocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the socket connection should be blocking or
|
||||
* not. A read call to a non-blocking socket will return immediately
|
||||
* if there is no data available, whereas it will block until there
|
||||
* is data for blocking sockets.
|
||||
*
|
||||
* @param boolean $mode True for blocking sockets, false for nonblocking.
|
||||
* @access public
|
||||
* @return mixed true on success or an error object otherwise
|
||||
*/
|
||||
function setBlocking($mode)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$this->blocking = $mode;
|
||||
socket_set_blocking($this->fp, $this->blocking);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout value on socket descriptor,
|
||||
* expressed in the sum of seconds and microseconds
|
||||
*
|
||||
* @param integer $seconds Seconds.
|
||||
* @param integer $microseconds Microseconds.
|
||||
* @access public
|
||||
* @return mixed true on success or an error object otherwise
|
||||
*/
|
||||
function setTimeout($seconds, $microseconds)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return socket_set_timeout($this->fp, $seconds, $microseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about an existing socket resource.
|
||||
* Currently returns four entries in the result array:
|
||||
*
|
||||
* <p>
|
||||
* timed_out (bool) - The socket timed out waiting for data<br>
|
||||
* blocked (bool) - The socket was blocked<br>
|
||||
* eof (bool) - Indicates EOF event<br>
|
||||
* unread_bytes (int) - Number of bytes left in the socket buffer<br>
|
||||
* </p>
|
||||
*
|
||||
* @access public
|
||||
* @return mixed Array containing information about existing socket resource or an error object otherwise
|
||||
*/
|
||||
function getStatus()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return socket_get_status($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specified line of data
|
||||
*
|
||||
* @access public
|
||||
* @return $size bytes of data from the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function gets($size)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return @fgets($this->fp, $size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a specified amount of data. This is guaranteed to return,
|
||||
* and has the added benefit of getting everything in one fread()
|
||||
* chunk; if you know the size of the data you're getting
|
||||
* beforehand, this is definitely the way to go.
|
||||
*
|
||||
* @param integer $size The number of bytes to read from the socket.
|
||||
* @access public
|
||||
* @return $size bytes of data from the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function read($size)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return @fread($this->fp, $size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a specified amount of data.
|
||||
*
|
||||
* @param string $data Data to write.
|
||||
* @param integer $blocksize Amount of data to write at once.
|
||||
* NULL means all at once.
|
||||
*
|
||||
* @access public
|
||||
* @return mixed true on success or an error object otherwise
|
||||
*/
|
||||
function write($data, $blocksize = null)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
if (is_null($blocksize) && !OS_WINDOWS) {
|
||||
return fwrite($this->fp, $data);
|
||||
} else {
|
||||
if (is_null($blocksize)) {
|
||||
$blocksize = 1024;
|
||||
}
|
||||
|
||||
$pos = 0;
|
||||
$size = strlen($data);
|
||||
while ($pos < $size) {
|
||||
$written = @fwrite($this->fp, substr($data, $pos, $blocksize));
|
||||
if ($written === false) {
|
||||
return false;
|
||||
}
|
||||
$pos += $written;
|
||||
}
|
||||
|
||||
return $pos;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a line of data to the socket, followed by a trailing "\r\n".
|
||||
*
|
||||
* @access public
|
||||
* @return mixed fputs result, or an error
|
||||
*/
|
||||
function writeLine($data)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return fwrite($this->fp, $data . "\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for end-of-file on a socket descriptor.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function eof()
|
||||
{
|
||||
return (is_resource($this->fp) && feof($this->fp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a byte of data
|
||||
*
|
||||
* @access public
|
||||
* @return 1 byte of data from the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readByte()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
return ord(@fread($this->fp, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a word of data
|
||||
*
|
||||
* @access public
|
||||
* @return 1 word of data from the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readWord()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$buf = @fread($this->fp, 2);
|
||||
return (ord($buf[0]) + (ord($buf[1]) << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int of data
|
||||
*
|
||||
* @access public
|
||||
* @return integer 1 int of data from the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readInt()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$buf = @fread($this->fp, 4);
|
||||
return (ord($buf[0]) + (ord($buf[1]) << 8) +
|
||||
(ord($buf[2]) << 16) + (ord($buf[3]) << 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a zero-terminated string of data
|
||||
*
|
||||
* @access public
|
||||
* @return string, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readString()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$string = '';
|
||||
while (($char = @fread($this->fp, 1)) != "\x00") {
|
||||
$string .= $char;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an IP Address and returns it in a dot formated string
|
||||
*
|
||||
* @access public
|
||||
* @return Dot formated string, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readIPAddress()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$buf = @fread($this->fp, 4);
|
||||
return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
|
||||
ord($buf[2]), ord($buf[3]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read until either the end of the socket or a newline, whichever
|
||||
* comes first. Strips the trailing newline from the returned data.
|
||||
*
|
||||
* @access public
|
||||
* @return All available data up to a newline, without that
|
||||
* newline, or until the end of the socket, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readLine()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$line = '';
|
||||
$timeout = time() + $this->timeout;
|
||||
while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
|
||||
$line .= @fgets($this->fp, $this->lineLength);
|
||||
if (substr($line, -1) == "\n") {
|
||||
return rtrim($line, "\r\n");
|
||||
}
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read until the socket closes, or until there is no more data in
|
||||
* the inner PHP buffer. If the inner buffer is empty, in blocking
|
||||
* mode we wait for at least 1 byte of data. Therefore, in
|
||||
* blocking mode, if there is no data at all to be read, this
|
||||
* function will never exit (unless the socket is closed on the
|
||||
* remote end).
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return string All data until the socket closes, or a PEAR_Error if
|
||||
* not connected.
|
||||
*/
|
||||
function readAll()
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$data = '';
|
||||
while (!feof($this->fp)) {
|
||||
$data .= @fread($this->fp, $this->lineLength);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the equivalent of the select() system call on the socket
|
||||
* with a timeout specified by tv_sec and tv_usec.
|
||||
*
|
||||
* @param integer $state Which of read/write/error to check for.
|
||||
* @param integer $tv_sec Number of seconds for timeout.
|
||||
* @param integer $tv_usec Number of microseconds for timeout.
|
||||
*
|
||||
* @access public
|
||||
* @return False if select fails, integer describing which of read/write/error
|
||||
* are ready, or PEAR_Error if not connected.
|
||||
*/
|
||||
function select($state, $tv_sec, $tv_usec = 0)
|
||||
{
|
||||
if (!is_resource($this->fp)) {
|
||||
return $this->raiseError('not connected');
|
||||
}
|
||||
|
||||
$read = null;
|
||||
$write = null;
|
||||
$except = null;
|
||||
if ($state & NET_SOCKET_READ) {
|
||||
$read[] = $this->fp;
|
||||
}
|
||||
if ($state & NET_SOCKET_WRITE) {
|
||||
$write[] = $this->fp;
|
||||
}
|
||||
if ($state & NET_SOCKET_ERROR) {
|
||||
$except[] = $this->fp;
|
||||
}
|
||||
if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = 0;
|
||||
if (count($read)) {
|
||||
$result |= NET_SOCKET_READ;
|
||||
}
|
||||
if (count($write)) {
|
||||
$result |= NET_SOCKET_WRITE;
|
||||
}
|
||||
if (count($except)) {
|
||||
$result |= NET_SOCKET_ERROR;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user