2
0
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:
azammitdcarf
2008-10-15 22:36:05 +00:00
parent 4f0b4f0bbb
commit 1445da495b
2237 changed files with 714445 additions and 0 deletions

943
include/pear/Net/NNTP.php Normal file
View 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";
}
// }}}
}
// }}}
?>

View 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'];
}
// }}}
}
// }}}
?>

File diff suppressed because it is too large Load Diff

970
include/pear/Net/SMTP.php Normal file
View 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
View 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;
}
}