Linux ns1.utparral.edu.mx 6.8.0-79-generic #79~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 15 16:54:53 UTC 2 x86_64
Apache/2.4.58 (Unix) OpenSSL/1.1.1w PHP/8.2.12 mod_perl/2.0.12 Perl/v5.34.1
: 10.10.1.9 | : 10.10.1.254
Cant Read [ /etc/named.conf ]
daemon
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
README
+ Create Folder
+ Create File
/
opt /
lampp /
lib /
php /
Net /
NNTP /
Protocol /
[ HOME SHELL ]
Name
Size
Permission
Action
Client.php
69.24
KB
-rw-r--r--
Responsecode.php
12.03
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : Client.php
<?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */ /** * * * PHP versions 4 and 5 * * <pre> * +-----------------------------------------------------------------------+ * | | * | W3C� SOFTWARE NOTICE AND LICENSE | * | http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 | * | | * | This work (and included software, documentation such as READMEs, | * | 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 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: | * | | * | 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, the W3C Software Short | * | Notice should be included (hypertext is preferred, text is | * | permitted) within the body of any redistributed or derivative | * | code. | * | | * | 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. | * | | * +-----------------------------------------------------------------------+ * </pre> * * @category Net * @package Net_NNTP * @author Heino H. Gehlsen <heino@gehlsen.dk> * @copyright 2002-2011 Heino H. Gehlsen <heino@gehlsen.dk>. All Rights Reserved. * @license http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 W3C� SOFTWARE NOTICE AND LICENSE * @version SVN: $Id: Client.php 330426 2013-05-31 14:41:46Z janpascal $ * @link http://pear.php.net/package/Net_NNTP * @see */ // Warn about PHP bugs if (version_compare(PHP_VERSION, '5.2.11') === 0) { trigger_error('PHP bug #16657 breaks feof() on socket streams! Connection consistency might be compromised!', E_USER_WARNING); } /** * */ require_once 'PEAR.php'; //require_once 'Net/NNTP/Error.php'; require_once 'Net/NNTP/Protocol/Responsecode.php'; // {{{ constants /** * Default host * * @access public * @ignore */ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_HOST', 'localhost'); /** * Default port * * @access public * @ignore */ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); // }}} // {{{ Net_NNTP_Protocol_Client /** * Low level NNTP Client * * Implements the client part of the NNTP standard acording to: * - RFC 977, * - RFC 2980, * - RFC 850/1036, and * - RFC 822/2822 * * Each NNTP command is represented by a method: cmd*() * * WARNING: The Net_NNTP_Protocol_Client class is considered an internal class * (and should therefore currently not be extended directly outside of * the Net_NNTP package). Therefore its API is NOT required to be fully * stable, for as long as such changes doesn't affect the public API of * the Net_NNTP_Client class, which is considered stable. * * TODO: cmdListActiveTimes() * cmdDistribPats() * * @category Net * @package Net_NNTP * @author Heino H. Gehlsen <heino@gehlsen.dk> * @version package: 1.5.0 (stable) * @version api: 0.9.0 (alpha) * @access private * @see Net_NNTP_Client */ class Net_NNTP_Protocol_Client extends PEAR { // {{{ properties /** * The socket resource being used to connect to the NNTP server. * * @var resource * @access private */ var $_socket = null; /** * Contains the last recieved status response code and text * * @var array * @access private */ var $_currentStatusResponse = null; /** * * * @var object * @access private */ var $_logger = null; // }}} // {{{ constructor /** * Constructor * * @access public */ function Net_NNTP_Protocol_Client() { // // parent::PEAR('Net_NNTP_Error'); parent::PEAR(); } // }}} // {{{ getPackageVersion() /** * * * @access public */ function getPackageVersion() { return '1.5.0'; } // }}} // {{{ getApiVersion() /** * * * @access public */ function getApiVersion() { return '0.9.0'; } // }}} // {{{ setLogger() /** * * * @param object $logger * * @access protected */ function setLogger($logger) { $this->_logger = $logger; } // }}} // {{{ setDebug() /** * @deprecated */ function setDebug($debug = true) { trigger_error('You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: setDebug() ! Debugging in now automatically handled when a logger is given.', E_USER_NOTICE); } // }}} // {{{ _sendCommand() /** * Send command * * Send a command to the server. A carriage return / linefeed (CRLF) sequence * will be appended to each command string before it is sent to the IMAP 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 private */ function _sendCommand($cmd) { // NNTP/RFC977 only allows command up to 512 (-2) chars. if (!strlen($cmd) > 510) { return $this->throwError('Failed writing to socket! (Command to long - max 510 chars)'); } /***************************************************************************************/ /* Credit: Thanks to Brendan Coles <bcoles@gmail.com> (http://itsecuritysolutions.org) */ /* for pointing out possibility to inject pipelined NNTP commands into pretty */ /* much any Net_NNTP command-sending function with user input, by appending */ /* a new line character followed by the injection. */ /***************************************************************************************/ // Prevent new line (and possible future) characters in the NNTP commands // Net_NNTP does not support pipelined commands. Inserting a new line charecter // allows sending multiple commands and thereby making the communication between // NET_NNTP and the server out of sync... if (preg_match_all('/\r?\n/', $cmd, $matches, PREG_PATTERN_ORDER)) { foreach ($matches[0] as $key => $match) { $this->_logger->debug("Illegal character in command: ". htmlentities(str_replace(array("\r","\n"), array("'Carriage Return'", "'New Line'"), $match))); } return $this->throwError("Illegal character(s) in NNTP command!"); } // Check if connected if (!$this->_isConnected()) { return $this->throwError('Failed to write to socket! (connection lost!)'); } // Send the command $R = @fwrite($this->_socket, $cmd . "\r\n"); if ($R === false) { return $this->throwError('Failed to write to socket!'); } // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('C: ' . $cmd); } // return $this->_getStatusResponse(); } // }}} // {{{ _getStatusResponse() /** * Get servers status response after a command. * * @return mixed (int) statuscode on success or (object) pear_error on failure * @access private */ function _getStatusResponse() { // Retrieve a line (terminated by "\r\n") from the server. // RFC says max is 510, but IETF says "be liberal in what you accept"... $response = @fgets($this->_socket, 4096); if ($response === false) { return $this->throwError('Failed to read from socket...!'); } // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('S: ' . rtrim($response, "\r\n")); } // Trim the start of the response in case of misplased whitespace (should not be needen!!!) $response = ltrim($response); $this->_currentStatusResponse = array( (int) substr($response, 0, 3), (string) rtrim(substr($response, 4)) ); // return $this->_currentStatusResponse[0]; } // }}} // {{{ _getTextResponse() /** * Retrieve textural data * * Get data until a line with only a '.' in it is read and return data. * * @return mixed (array) text response on success or (object) pear_error on failure * @access private */ function _getTextResponse() { $data = array(); $line = ''; // $debug = $this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG); // Continue until connection is lost while (!feof($this->_socket)) { // Retrieve and append up to 1024 characters from the server. $recieved = @fgets($this->_socket, 1024); if ($recieved === false) { return $this->throwError('Failed to read line from socket.', null); } $line .= $recieved; // Continue if the line is not terminated by CRLF if (substr($line, -2) != "\r\n" || strlen($line) < 2) { continue; } // Validate recieved line if (false) { // Lines should/may not be longer than 998+2 chars (RFC2822 2.3) if (strlen($line) > 1000) { if ($this->_logger) { $this->_logger->notice('Max line length...'); } return $this->throwError('Invalid line recieved!', null); } } // Remove CRLF from the end of the line $line = substr($line, 0, -2); // Check if the line terminates the textresponse if ($line == '.') { if ($this->_logger) { $this->_logger->debug('T: ' . $line); } // return all previous lines return $data; } // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1) if (substr($line, 0, 2) == '..') { $line = substr($line, 1); } // if ($debug) { $this->_logger->debug('T: ' . $line); } // Add the line to the array of lines $data[] = $line; // Reset/empty $line $line = ''; } if ($this->_logger) { $this->_logger->warning('Broke out of reception loop! This souldn\'t happen unless connection has been lost?'); } // return $this->throwError('End of stream! Connection lost?', null); } // }}} // {{{ _sendText() /** * * * @access private */ function _sendArticle($article) { /* data should be in the format specified by RFC850 */ switch (true) { case is_string($article): // @fwrite($this->_socket, $article); @fwrite($this->_socket, "\r\n.\r\n"); // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $article) as $line) { $this->_logger->debug('D: ' . $line); } $this->_logger->debug('D: .'); } break; case is_array($article): // $header = reset($article); $body = next($article); /* Experimental... // If header is an array, implode it. if (is_array($header)) { $header = implode("\r\n", $header) . "\r\n"; } */ // Send header (including separation line) @fwrite($this->_socket, $header); @fwrite($this->_socket, "\r\n"); // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $header) as $line) { $this->_logger->debug('D: ' . $line); } } /* Experimental... // If body is an array, implode it. if (is_array($body)) { $header = implode("\r\n", $body) . "\r\n"; } */ // Send body @fwrite($this->_socket, $body); @fwrite($this->_socket, "\r\n.\r\n"); // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $body) as $line) { $this->_logger->debug('D: ' . $line); } $this->_logger->debug('D: .'); } break; default: return $this->throwError('Ups...', null, null); } return true; } // }}} // {{{ _currentStatusResponse() /** * * * @return string status text * @access private */ function _currentStatusResponse() { return $this->_currentStatusResponse[1]; } // }}} // {{{ _handleUnexpectedResponse() /** * * * @param int $code Status code number * @param string $text Status text * * @return mixed * @access private */ function _handleUnexpectedResponse($code = null, $text = null) { if ($code === null) { $code = $this->_currentStatusResponse[0]; } if ($text === null) { $text = $this->_currentStatusResponse(); } switch ($code) { case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: // 502, 'access restriction or permission denied' / service permanently unavailable return $this->throwError('Command not permitted / Access restriction / Permission denied', $code, $text); break; default: return $this->throwError("Unexpected response: '$text'", $code, $text); } } // }}} /* Session administration commands */ // {{{ Connect() /** * Connect to a NNTP server * * @param string $host (optional) The address of the NNTP-server to connect to, defaults to 'localhost'. * @param mixed $encryption (optional) * @param int $port (optional) The port number to connect to, defaults to 119. * @param int $timeout (optional) * * @return mixed (bool) on success (true when posting allowed, otherwise false) or (object) pear_error on failure * @access protected */ function connect($host = null, $encryption = null, $port = null, $timeout = null) { // if ($this->_isConnected() ) { return $this->throwError('Already connected, disconnect first!', null); } // v1.0.x API if (is_int($encryption)) { trigger_error('You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE); $port = $encryption; $encryption = false; } // if (is_null($host)) { $host = 'localhost'; } // Choose transport based on encryption, and if no port is given, use default for that encryption switch ($encryption) { case null: case false: $transport = 'tcp'; $port = is_null($port) ? 119 : $port; break; case 'ssl': case 'tls': $transport = $encryption; $port = is_null($port) ? 563 : $port; break; default: trigger_error('$encryption parameter must be either tcp, tls or ssl.', E_USER_ERROR); } // if (is_null($timeout)) { $timeout = 15; } // Open Connection $R = stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout); if ($R === false) { if ($this->_logger) { $this->_logger->notice("Connection to $transport://$host:$port failed."); } return $R; } $this->_socket = $R; // if ($this->_logger) { $this->_logger->info("Connection to $transport://$host:$port has been established."); } // Retrive the server's initial response. $response = $this->_getStatusResponse(); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // 200, Posting allowed // TODO: Set some variable before return return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: // 201, Posting NOT allowed // if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; break; case 400: return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: // 502, 'access restriction or permission denied' / service permanently unavailable return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ disconnect() /** * alias for cmdQuit() * * @access protected */ function disconnect() { return $this->cmdQuit(); } // }}} // {{{ cmdCapabilities() /** * Returns servers capabilities * * @return mixed (array) list of capabilities on success or (object) pear_error on failure * @access protected */ function cmdCapabilities() { // tell the newsserver we want an article $response = $this->_sendCommand('CAPABILITIES'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_CAPABILITIES_FOLLOW: // 101, Draft: 'Capability list follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } return $data; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdModeReader() /** * * * @return mixed (bool) true when posting allowed, false when postind disallowed or (object) pear_error on failure * @access protected */ function cmdModeReader() { // tell the newsserver we want an article $response = $this->_sendCommand('MODE READER'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // 200, RFC2980: 'Hello, you can post' // TODO: Set some variable before return return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: // 201, RFC2980: 'Hello, you can't post' if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: // 502, 'access restriction or permission denied' / service permanently unavailable return $this->throwError('Connection being closed, since service so permanently unavailable', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdQuit() /** * Disconnect from the NNTP server * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdQuit() { // Tell the server to close the connection $response = $this->_sendCommand('QUIT'); if (PEAR::isError($response)) { return $response; } switch ($response) { case 205: // RFC977: 'closing connection - goodbye!' // If socket is still open, close it. if ($this->_isConnected()) { fclose($this->_socket); } if ($this->_logger) { $this->_logger->info('Connection closed.'); } return true; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* */ // {{{ cmdStartTLS() /** * * * @return mixed (bool) on success or (object) pear_error on failure * @access protected */ function cmdStartTLS() { $response = $this->_sendCommand('STARTTLS'); if (PEAR::isError($response)) { return $response; } switch ($response) { case 382: // RFC4642: 'continue with TLS negotiation' $encrypted = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); switch (true) { case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption started.'); } return true; break; case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption failed.'); } return $this->throwError('Could not initiate TLS negotiation', $response, $this->_currentStatusResponse()); break; case is_int($encrypted): return $this->throwError('', $response, $this->_currentStatusResponse()); break; default: return $this->throwError('Internal error - unknown response from stream_socket_enable_crypto()', $response, $this->_currentStatusResponse()); } break; case 580: // RFC4642: 'can not initiate TLS negotiation' return $this->throwError('', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* Article posting and retrieval */ /* Group and article selection */ // {{{ cmdGroup() /** * Selects a news group (issue a GROUP command to the server) * * @param string $newsgroup The newsgroup name * * @return mixed (array) groupinfo on success or (object) pear_error on failure * @access protected */ function cmdGroup($newsgroup) { $response = $this->_sendCommand('GROUP '.$newsgroup); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: // 211, RFC977: 'n f l s group selected' $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { $this->_logger->info('Group selected: '.$response_arr[3]); } return array('group' => $response_arr[3], 'first' => $response_arr[1], 'last' => $response_arr[2], 'count' => $response_arr[0]); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: // 411, RFC977: 'no such news group' return $this->throwError('No such news group', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdListgroup() /** * * * @param optional string $newsgroup * @param optional mixed $range * * @return optional mixed (array) on success or (object) pear_error on failure * @access protected */ function cmdListgroup($newsgroup = null, $range = null) { if (is_null($newsgroup)) { $command = 'LISTGROUP'; } else { if (is_null($range)) { $command = 'LISTGROUP ' . $newsgroup; } else { $command = 'LISTGROUP ' . $newsgroup . ' ' . $range; } } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: // 211, RFC2980: 'list of article numbers follow' $articles = $this->_getTextResponse(); if (PEAR::isError($articles)) { return $articles; } $response_arr = explode(' ', trim($this->_currentStatusResponse()), 4); // If server does not return group summary in status response, return null'ed array if (!is_numeric($response_arr[0]) || !is_numeric($response_arr[1]) || !is_numeric($response_arr[2]) || empty($response_arr[3])) { return array('group' => null, 'first' => null, 'last' => null, 'count' => null, 'articles' => $articles); } return array('group' => $response_arr[3], 'first' => $response_arr[1], 'last' => $response_arr[2], 'count' => $response_arr[0], 'articles' => $articles); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC2980: 'Not currently in newsgroup' return $this->throwError('Not currently in newsgroup', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdLast() /** * * * @return mixed (array) or (string) or (int) or (object) pear_error on failure * @access protected */ function cmdLast() { // $response = $this->_sendCommand('LAST'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup selected' return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC977: 'no current article has been selected' return $this->throwError('No current article has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: // 422, RFC977: 'no previous article in this group' return $this->throwError('No previous article in this group', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdNext() /** * * * @return mixed (array) or (string) or (int) or (object) pear_error on failure * @access protected */ function cmdNext() { // $response = $this->_sendCommand('NEXT'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup selected' return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC977: 'no current article has been selected' return $this->throwError('No current article has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: // 421, RFC977: 'no next article in this group' return $this->throwError('No next article in this group', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* Retrieval of articles and article sections */ // {{{ cmdArticle() /** * Get an article from the currently open connection. * * @param mixed $article Either a message-id or a message-number of the article to fetch. If null or '', then use current article. * * @return mixed (array) article on success or (object) pear_error on failure * @access protected */ function cmdArticle($article = null) { if (is_null($article)) { $command = 'ARTICLE'; } else { $command = 'ARTICLE ' . $article; } // tell the newsserver we want an article $response = $this->_sendCommand($command); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS: // 220, RFC977: 'n <a> article retrieved - head and body follow (n = article number, <a> = message-id)' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } if ($this->_logger) { $this->_logger->info(($article == null ? 'Fetched current article' : 'Fetched article: '.$article)); } return $data; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup has been selected' return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC977: 'no current article has been selected' return $this->throwError('No current article has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: // 423, RFC977: 'no such article number in this group' return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: // 430, RFC977: 'no such article found' return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdHead() /** * Get the headers of an article from the currently open connection. * * @param mixed $article Either a message-id or a message-number of the article to fetch the headers from. If null or '', then use current article. * * @return mixed (array) headers on success or (object) pear_error on failure * @access protected */ function cmdHead($article = null) { if (is_null($article)) { $command = 'HEAD'; } else { $command = 'HEAD ' . $article; } // tell the newsserver we want the header of an article $response = $this->_sendCommand($command); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: // 221, RFC977: 'n <a> article retrieved - head follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } if ($this->_logger) { $this->_logger->info(($article == null ? 'Fetched current article header' : 'Fetched article header for article: '.$article)); } return $data; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup has been selected' return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC977: 'no current article has been selected' return $this->throwError('No current article has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: // 423, RFC977: 'no such article number in this group' return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: // 430, RFC977: 'no such article found' return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdBody() /** * Get the body of an article from the currently open connection. * * @param mixed $article Either a message-id or a message-number of the article to fetch the body from. If null or '', then use current article. * * @return mixed (array) body on success or (object) pear_error on failure * @access protected */ function cmdBody($article = null) { if (is_null($article)) { $command = 'BODY'; } else { $command = 'BODY ' . $article; } // tell the newsserver we want the body of an article $response = $this->_sendCommand($command); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS: // 222, RFC977: 'n <a> article retrieved - body follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } if ($this->_logger) { $this->_logger->info(($article == null ? 'Fetched current article body' : 'Fetched article body for article: '.$article)); } return $data; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup has been selected' return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC977: 'no current article has been selected' return $this->throwError('No current article has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: // 423, RFC977: 'no such article number in this group' return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: // 430, RFC977: 'no such article found' return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdStat /** * * * @param mixed $article * * @return mixed (array) or (string) or (int) or (object) pear_error on failure * @access protected */ function cmdStat($article = null) { if (is_null($article)) { $command = 'STAT'; } else { $command = 'STAT ' . $article; } // tell the newsserver we want an article $response = $this->_sendCommand($command); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: // 223, RFC977: 'n <a> article retrieved - request text separately' (actually not documented, but copied from the ARTICLE command) $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { $this->_logger->info('Selected article: ' . $response_arr[0].' - '.$response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC977: 'no newsgroup has been selected' (actually not documented, but copied from the ARTICLE command) return $this->throwError('No newsgroup has been selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: // 423, RFC977: 'no such article number in this group' (actually not documented, but copied from the ARTICLE command) return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: // 430, RFC977: 'no such article found' (actually not documented, but copied from the ARTICLE command) return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* Article posting */ // {{{ cmdPost() /** * Post an article to a newsgroup. * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdPost() { // tell the newsserver we want to post an article $response = $this->_sendCommand('POST'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND: // 340, RFC977: 'send article to be posted. End with <CR-LF>.<CR-LF>' return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: // 440, RFC977: 'posting not allowed' return $this->throwError('Posting not allowed', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdPost2() /** * Post an article to a newsgroup. * * @param mixed $article (string/array) * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdPost2($article) { /* should be presented in the format specified by RFC850 */ // $this->_sendArticle($article); // Retrive server's response. $response = $this->_getStatusResponse(); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS: // 240, RFC977: 'article posted ok' return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: // 441, RFC977: 'posting failed' return $this->throwError('Posting failed', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdIhave() /** * * * @param string $id * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdIhave($id) { // tell the newsserver we want to post an article $response = $this->_sendCommand('IHAVE ' . $id); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: // 335 return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: // 435 return $this->throwError('Article not wanted', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 return $this->throwError('Transfer not possible; try again later', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdIhave2() /** * * * @param mixed $article (string/array) * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdIhave2($article) { /* should be presented in the format specified by RFC850 */ // $this->_sendArticle($article); // Retrive server's response. $response = $this->_getStatusResponse(); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: // 235 return true; break; case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 return $this->throwError('Transfer not possible; try again later', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: // 437 return $this->throwError('Transfer rejected; do not retry', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* Information commands */ // {{{ cmdDate() /** * Get the date from the newsserver format of returned date * * @return mixed (string) 'YYYYMMDDhhmmss' / (int) timestamp on success or (object) pear_error on failure * @access protected */ function cmdDate() { $response = $this->_sendCommand('DATE'); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE: // 111, RFC2980: 'YYYYMMDDhhmmss' return $this->_currentStatusResponse(); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdHelp() /** * Returns the server's help text * * @return mixed (array) help text on success or (object) pear_error on failure * @access protected */ function cmdHelp() { // tell the newsserver we want an article $response = $this->_sendCommand('HELP'); if (PEAR::isError($response)) { return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: // 100 $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } return $data; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdNewgroups() /** * Fetches a list of all newsgroups created since a specified date. * * @param int $time Last time you checked for groups (timestamp). * @param optional string $distributions (deprecaded in rfc draft) * * @return mixed (array) nested array with informations about existing newsgroups on success or (object) pear_error on failure * @access protected */ function cmdNewgroups($time, $distributions = null) { $date = gmdate('ymd His', $time); if (is_null($distributions)) { $command = 'NEWGROUPS ' . $date . ' GMT'; } else { $command = 'NEWGROUPS ' . $date . ' GMT <' . $distributions . '>'; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_GROUPS_FOLLOW: // 231, REF977: 'list of new newsgroups follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $groups = array(); foreach($data as $line) { $arr = explode(' ', trim($line)); $group = array('group' => $arr[0], 'last' => $arr[1], 'first' => $arr[2], 'posting' => $arr[3]); $groups[$group['group']] = $group; } return $groups; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdNewnews() /** * * * @param timestamp $time * @param mixed $newsgroups (string or array of strings) * @param mixed $distribution (string or array of strings) * * @return mixed * @access protected */ function cmdNewnews($time, $newsgroups, $distribution = null) { $date = gmdate('ymd His', $time); if (is_array($newsgroups)) { $newsgroups = implode(',', $newsgroups); } if (is_null($distribution)) { $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT'; } else { if (is_array($distribution)) { $distribution = implode(',', $distribution); } $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' . $distribution . '>'; } // TODO: the lenght of the request string may not exceed 510 chars $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW: // 230, RFC977: 'list of new articles by message-id follows' $messages = array(); foreach($this->_getTextResponse() as $line) { $messages[] = $line; } return $messages; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* The LIST commands */ // {{{ cmdList() /** * 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 protected */ function cmdList() { $response = $this->_sendCommand('LIST'); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: // 215, RFC977: 'list of newsgroups follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $groups = array(); foreach($data as $line) { $arr = explode(' ', trim($line)); $group = array('group' => $arr[0], 'last' => $arr[1], 'first' => $arr[2], 'posting' => $arr[3]); $groups[$group['group']] = $group; } return $groups; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdListActive() /** * Fetches a list of all avaible newsgroups * * @param string $wildmat * * @return mixed (array) nested array with informations about existing newsgroups on success or (object) pear_error on failure * @access protected */ function cmdListActive($wildmat = null) { if (is_null($wildmat)) { $command = 'LIST ACTIVE'; } else { $command = 'LIST ACTIVE ' . $wildmat; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: // 215, RFC977: 'list of newsgroups follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $groups = array(); foreach($data as $line) { $arr = explode(' ', trim($line)); $group = array('group' => $arr[0], 'last' => $arr[1], 'first' => $arr[2], 'posting' => $arr[3]); $groups[$group['group']] = $group; } if ($this->_logger) { $this->_logger->info('Fetched list of available groups'); } return $groups; break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdListNewsgroups() /** * Fetches a list of (all) avaible newsgroup descriptions. * * @param string $wildmat Wildmat of the groups, that is to be listed, defaults to null; * * @return mixed (array) nested array with description of existing newsgroups on success or (object) pear_error on failure * @access protected */ function cmdListNewsgroups($wildmat = null) { if (is_null($wildmat)) { $command = 'LIST NEWSGROUPS'; } else { $command = 'LIST NEWSGROUPS ' . $wildmat; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: // 215, RFC2980: 'information follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $groups = array(); foreach($data as $line) { if (preg_match("/^(\S+)\s+(.*)$/", ltrim($line), $matches)) { $groups[$matches[1]] = (string) $matches[2]; } else { if ($this->_logger) { $this->_logger->warning("Recieved non-standard line: '$line'"); } } } if ($this->_logger) { $this->_logger->info('Fetched group descriptions'); } return $groups; break; case 503: // RFC2980: 'program error, function not performed' return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /* Article field access commands */ // {{{ cmdOver() /** * Fetch message header from message number $first until $last * * The format of the returned array is: * $messages[][header_name] * * @param optional string $range articles to fetch * * @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure * @access protected */ function cmdOver($range = null) { if (is_null($range)) { $command = 'OVER'; } else { $command = 'OVER ' . $range; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: // 224, RFC2980: 'Overview information follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } foreach ($data as $key => $value) { $data[$key] = explode("\t", trim($value)); } if ($this->_logger) { $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: '.$range)); } return $data; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC2980: 'No news group current selected' return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC2980: 'No article(s) selected' return $this->throwError('No article(s) selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: // 423:, Draft27: 'No articles in that range' return $this->throwError('No articles in that range', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdXOver() /** * Fetch message header from message number $first until $last * * The format of the returned array is: * $messages[message_id][header_name] * * @param optional string $range articles to fetch * * @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure * @access protected */ function cmdXOver($range = null) { // deprecated API (the code _is_ still in alpha state) if (func_num_args() > 1 ) { die('The second parameter in cmdXOver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { $command = 'XOVER'; } else { $command = 'XOVER ' . $range; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: // 224, RFC2980: 'Overview information follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } foreach ($data as $key => $value) { $data[$key] = explode("\t", trim($value)); } if ($this->_logger) { $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: '.$range)); } return $data; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC2980: 'No news group current selected' return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC2980: 'No article(s) selected' return $this->throwError('No article(s) selected', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdListOverviewFmt() /** * Returns a list of avaible headers which are send from newsserver to client for every news message * * @return mixed (array) of header names on success or (object) pear_error on failure * @access protected */ function cmdListOverviewFmt() { $response = $this->_sendCommand('LIST OVERVIEW.FMT'); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: // 215, RFC2980: 'information follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $format = array(); foreach ($data as $line) { // Check if postfixed by ':full' (case-insensitive) if (0 == strcasecmp(substr($line, -5, 5), ':full')) { // ':full' is _not_ included in tag, but value set to true $format[substr($line, 0, -5)] = true; } else { // ':' is _not_ included in tag; value set to false $format[substr($line, 0, -1)] = false; } } if ($this->_logger) { $this->_logger->info('Fetched overview format'); } return $format; break; case 503: // RFC2980: 'program error, function not performed' return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdXHdr() /** * * * The format of the returned array is: * $messages[message_id] * * @param optional string $field * @param optional string $range articles to fetch * * @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure * @access protected */ function cmdXHdr($field, $range = null) { if (is_null($range)) { $command = 'XHDR ' . $field; } else { $command = 'XHDR ' . $field . ' ' . $range; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case 221: // 221, RFC2980: 'Header follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $return = array(); foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC2980: 'No news group current selected' return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC2980: 'No current article selected' return $this->throwError('No current article selected', $response, $this->_currentStatusResponse()); break; case 430: // 430, RFC2980: 'No such article' return $this->throwError('No such article', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} /** * Fetches a list of (all) avaible newsgroup descriptions. * Depresated as of RFC2980. * * @param string $wildmat Wildmat of the groups, that is to be listed, defaults to '*'; * * @return mixed (array) nested array with description of existing newsgroups on success or (object) pear_error on failure * @access protected */ function cmdXGTitle($wildmat = '*') { $response = $this->_sendCommand('XGTITLE '.$wildmat); if (PEAR::isError($response)){ return $response; } switch ($response) { case 282: // RFC2980: 'list of groups and descriptions follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $groups = array(); foreach($data as $line) { preg_match("/^(.*?)\s(.*?$)/", trim($line), $matches); $groups[$matches[1]] = (string) $matches[2]; } return $groups; break; case 481: // RFC2980: 'Groups and descriptions unavailable' return $this->throwError('Groups and descriptions unavailable', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdXROver() /** * Fetch message references from message number $first to $last * * @param optional string $range articles to fetch * * @return mixed (array) assoc. array of message references on success or (object) pear_error on failure * @access protected */ function cmdXROver($range = null) { // Warn about deprecated API (the code _is_ still in alpha state) if (func_num_args() > 1 ) { die('The second parameter in cmdXROver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { $command = 'XROVER'; } else { $command = 'XROVER ' . $range; } $response = $this->_sendCommand($command); if (PEAR::isError($response)){ return $response; } switch ($response) { case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: // 224, RFC2980: 'Overview information follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $return = array(); foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: // 412, RFC2980: 'No news group current selected' return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); break; case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: // 420, RFC2980: 'No article(s) selected' return $this->throwError('No article(s) selected', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdXPat() /** * * * @param string $field * @param string $range * @param mixed $wildmat * * @return mixed (array) nested array of message and there headers on success or (object) pear_error on failure * @access protected */ function cmdXPat($field, $range, $wildmat) { if (is_array($wildmat)) { $wildmat = implode(' ', $wildmat); } $response = $this->_sendCommand('XPAT ' . $field . ' ' . $range . ' ' . $wildmat); if (PEAR::isError($response)){ return $response; } switch ($response) { case 221: // 221, RFC2980: 'Header follows' $data = $this->_getTextResponse(); if (PEAR::isError($data)) { return $data; } $return = array(); foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; break; case 430: // 430, RFC2980: 'No such article' return $this->throwError('No current article selected', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'no permission' return $this->throwError('No permission', $response, $this->_currentStatusResponse()); break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdAuthinfo() /** * Authenticate using 'original' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdAuthinfo($user, $pass) { // Send the username $response = $this->_sendCommand('AUTHINFO user '.$user); if (PEAR::isError($response)) { return $response; } // Send the password, if the server asks if (($response == 381) && ($pass !== null)) { // Send the password $response = $this->_sendCommand('AUTHINFO pass '.$pass); if (PEAR::isError($response)) { return $response; } } switch ($response) { case 281: // RFC2980: 'Authentication accepted' if ($this->_logger) { $this->_logger->info("Authenticated (as user '$user')"); } // TODO: Set some variable before return return true; break; case 381: // RFC2980: 'More authentication information required' return $this->throwError('Authentication uncompleted', $response, $this->_currentStatusResponse()); break; case 482: // RFC2980: 'Authentication rejected' return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); break; case 502: // RFC2980: 'No permission' return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); break; // case 500: // case 501: // return $this->throwError('Authentication failed', $response, $this->_currentStatusResponse()); // break; default: return $this->_handleUnexpectedResponse($response); } } // }}} // {{{ cmdAuthinfoSimple() /** * Authenticate using 'simple' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdAuthinfoSimple($user, $pass) { return $this->throwError("The auth mode: 'simple' is has not been implemented yet", null); } // }}} // {{{ cmdAuthinfoGeneric() /** * Authenticate using 'generic' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ function cmdAuthinfoGeneric($user, $pass) { return $this->throwError("The auth mode: 'generic' is has not been implemented yet", null); } // }}} // {{{ _isConnected() /** * Test whether we are connected or not. * * @return bool true or false * @access protected */ function _isConnected() { return (is_resource($this->_socket) && (!feof($this->_socket))); } // }}} } // }}} /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * c-hanging-comment-ender-p: nil * End: */ ?>
Close