Source for file NNTP.php
Documentation is available at NNTP.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | 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.15.2.4 2004/03/10 08:47:13 heino Exp $
// Deprecated due to naming
/* 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 );
* The NNTP:: class fetches UseNet news articles acording to the standard
* @author Martin Kaltoft <martin@nitro.dk>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Heino H. Gehlsen <heino@gehlsen.dk>
class Net_NNTP extends PEAR
/** File pointer of the nntp-connection */
* Connect to the newsserver
* @param string $nntpserver The adress of the NNTP-server to connect to.
* @param int $port (optional) the port-number to connect to, defaults to 119.
* @param string $user (optional) The user name to authenticate with
* @param string $pass (optional) The password
* @param string $authmode (optional) The authentication mode
* @return mixed True on success or Pear Error object on failure
* @see Net_Nntp::authenticate()
function connect ($nntpserver,
$authmode = NET_NNTP_AUTHORIGINAL )
$fp = @fsockopen($nntpserver, $port, $errno, $errstr, 15 );
return $this->raiseError (" Could not connect to NNTP-server $nntpserver" );
return $this->raiseError ('Not connected');
$response = fgets($fp, 256 );
$this->authmode = $authmode;
* 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 $nntpserver The adress of the NNTP-server to connect to.
* @param int $port (optional) the port-number to connect to, defaults to 119.
* @param string $newsgroup The name of the newsgroup to use.
* @param string $user (optional) The user name to authenticate with
* @param string $pass (optional) The password
* @param string $authmode (optional) The authentication mode
* @return mixed True on success or Pear Error object on failure
* @see Net_Nntp::authenticate()
* @deprecated Use connect() instead
function prepareConnection ($nntpserver,
$authmode = NET_NNTP_AUTHORIGINAL )
/* connect to the server */
$err = $this->connect ($nntpserver, $port, $user, $pass, $authmode);
if (PEAR ::isError ($err)) {
/* issue a GROUP command */
$r = $this->command (" GROUP $newsgroup" );
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
$response_arr = split(' ', $r);
$this->max = $response_arr[3 ];
$this->min = $response_arr[2 ];
function prepare_connection ($nntpserver,
$authmode = NET_NNTP_AUTHORIGINAL )
return $this->prepareConnection ($nntpserver, $port, $newsgroup, $user, $pass, $authmode);
* Auth process (not yet standarized but used any way)
* http://www.mibsoftware.com/userkt/nntpext/index.html
* @param string $user The user name
* @param string $pass (optional) The password if needed
* @param string $mode Authinfo form: original, simple, generic
* @return mixed (bool) true on success or Pear Error obj on fail
function authenticate ($user = null , $pass = null , $mode = NET_NNTP_AUTHORIGINAL )
return $this->raiseError ('Authentication required but no user supplied');
281 Authentication accepted
381 More authentication information required
480 Authentication required
482 Authentication rejected
$response = $this->command (" AUTHINFO user $user" , false );
if ($this->responseCode ($response) != 281 ) {
if ($this->responseCode ($response) == 381 && $pass !== null ) {
$response = $this->command (" AUTHINFO pass $pass" , false );
if ($this->responseCode ($response) != 281 ) {
return $this->raiseError (" Authentication failed: $response" );
$this->raiseError (" The auth mode: $mode isn't implemented" );
* Get an article from the currently open connection.
* To get articles from another newsgroup a new prepare_connection() -
* call has to be made with apropriate parameters
* @param mixed $article Either the message-id or the message-number on the server of the article to fetch
* @return string the article
function getArticle ($article)
/* tell the newsserver we want an article */
$r = $this->command (" ARTICLE $article" );
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
while (!feof($this->fp)) {
function get_article ($article)
return $this->getArticle ($article);
* Post an article to a newsgroup.
* 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 string $aditionak (optional) Aditional headers to send.
* @return string server response
function post ($subject, $newsgroup, $from, $body, $aditional = "")
return $this->raiseError ('Not connected');
/* tell the newsserver we want to post an article */
$r = $this->command ('POST');
if (PEAR ::isError ($r) || $this->responseCode ($r) != 340 ) {
return $this->raiseError ($r);
$data .= " From: $from\r\n";
$data .= " Newsgroups: $newsgroup\r\n";
$data .= " Subject: $subject\r\n";
$data .= "X-poster: PEAR::Net_NNTP (0.2)\r\n";
if (!empty ($aditional)) {
$data .= rtrim($aditional, "\r\n"). "\r\n";
return $this->command ($data, false );
* Get the headers of an article from the currently open connection
* To get the headers of an article from another newsgroup, a new
* prepare_connection()-call has to be made with apropriate parameters
* @param string $article Either a message-id or a message-number of the article to fetch the headers from.
function getHeaders ($article)
/* tell the newsserver we want an article */
$r = $this->command (" HEAD $article" );
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
while (!feof($this->fp)) {
$headers .= $line . "\n";
function get_headers ($article)
return $this->getHeaders ($article);
* Returns the headers of a given article in the form of
* an associative array. Ex:
* 'From' => 'foo@bar.com (Foo Smith)',
* 'Subject' => 'Re: Using NNTP class',
* @param $article string Article number or id
* @return array Assoc array with headers names as key or Pear obj error
function splitHeaders ($article)
$headers = $this->get_headers ($article);
if (PEAR ::isError ($headers)) {
foreach ($lines as $line) {
if (($pos = strpos($line, ':')) !== false ) {
$head = substr($line, 0 , $pos);
// if the field was longer than 256 chars, look also in the next line
// XXX a better way to discover that than strpos?
if (isset ($ret['References']) &&
$ret['References'] = $matches[0 ];
function split_headers ($article) {
return $this->splitHeaders ($article);
* Get the body of an article from the currently open connection.
* To get the body of an article from another newsgroup, a new
* prepare_connection()-call has to be made with apropriate parameters
* @param string $article Either a message-id or a message-number of the article to fetch the headers from.
function getBody ($article)
/* tell the newsserver we want an article */
$r = $this->command (" BODY $article" );
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
while (!feof($this->fp)) {
function get_body ($article) {
return $this->getBody ($article);
* Get data until a line with only a '.' in it is read and return data.
* @author Morgan Christiansson <mog@linux.nu>
while (!feof($this->fp)) {
return $this->_getData ();
* Selects a news group (issue a GROUP command to the server)
* @param string $newsgroup The newsgroup name
* @return mixed Array on success or Pear Error object on failure
function selectGroup ($newsgroup)
$r = $this->command (" GROUP $newsgroup" );
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
$response_arr = split(' ', $r);
$this->max = $response_arr[3 ];
$this->min = $response_arr[2 ];
"first" => $response_arr[2 ],
"last" => $response_arr[3 ]
function select_group ($newsgroup) {
return $this->selectGroup ($newsgroup);
* Fetches a list of all avaible newsgroups
* @param int $fetch PEAR_NNTP_ALL PEAR_NNTP_NAMES PEAR_NNTP_LIST
* @return array nested array with informations about
* @author Morgan Christiansson <mog@linux.nu>
function getGroups ($fetch = true )
foreach($this->_getData () as $line) {
$groups[$arr[0 ]]["group"] = $arr[0 ];
$groups[$arr[0 ]]["last"] = $arr[1 ];
$groups[$arr[0 ]]["first"] = $arr[2 ];
$groups[$arr[0 ]]["posting_allowed"] = $arr[3 ];
$this->command ("LIST NEWSGROUPS");
foreach($this->_getData () as $line) {
$groups[$matches[1 ]]["desc"] = $matches[2 ];
function get_groups ($fetch=true ) {
return $this->getGroups ($fetch);
* Returns a list of avaible headers
* which are send from newsserver to client
* @return array header names
function getOverviewFmt ()
$this->command ("LIST OVERVIEW.FMT");
$format = array ("number");
// XXX Use the splitHeaders() algorithm for supporting
foreach ($body = $this->_getData () as $line) {
function get_overview_fmt () {
return $this->getOverviewFmt ();
* from message number $first until $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 array nested array of message and
function getOverview ($first,$last) {
$format = $this->getOverviewFmt ();
$this->command (" XOVER $first-$last" );
foreach($this->_getData () as $line) {
foreach(explode("\t",$line) as $line) {
$message[$format[$i++ ]] = $line;
$messages[$message["Message-ID"]] = $message;
function get_overview ($first,$last) {
return $this->getOverview ($first, $last);
* Get the date from the newsserver
* format of returned date:
$r = $this->command ('DATE');
if (PEAR ::isError ($r) || $this->responseCode ($r) > 299 ) {
return $this->raiseError ($r);
$date['y']= substr($data[1 ],0 ,4 );
$date['m']= substr($data[1 ],4 ,2 );
$date['d']= substr($data[1 ],6 ,2 );
* Maximum article number in current group
* @return integer maximum
return $this->raiseError ('Not connected');
* Minimum article number in current group
* @return integer minimum
return $this->raiseError ('Not connected');
* Test whether we are connected or not.
* @return bool true or false
function is_connected () {
return $this->isConnected ();
* Close connection to the newsserver
* returns the response code
* of a newsserver command
* @param string $response newsserver answer
* @return integer response code
function responseCode ($response)
* @param boolean $on true=on, false=off
function setDebug ($on = true )
function set_debug ($on = true ) {
return $this->setDebug ();
* Issue a command to the NNTP server
* @param string $cmd The command to launch, ie: "ARTICLE 1004853"
* @param bool $testauth Test or not the auth
* @return mixed True on success or Pear Error object on failure
function command ($cmd, $testauth = true )
return $this->raiseError ('Not connected');
fputs($this->fp, " $cmd\r\n" );
$response = fgets($this->fp, 128 );
// From the spec: "In all cases, clients must provide
// this information when requested by the server. Servers are
// not required to accept authentication information that is
// volunteered by the client"
$code = $this->responseCode ($response);
if ($testauth && ($code == 450 || $code == 480 )) {
$error = $this->authenticate ($this->user, $this->pass, $this->authmode);
if (PEAR ::isError ($error)) {
/* re-issue the command */
$response = $this->command ($cmd, false );
Documentation generated on Mon, 11 Mar 2019 13:53:06 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|