    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.net.nntp;
    019
    020    import java.io.BufferedReader;
    021    import java.io.BufferedWriter;
    022    import java.io.IOException;
    023    import java.io.InputStreamReader;
    024    import java.io.OutputStreamWriter;
    025
    026    import org.apache.commons.net.MalformedServerReplyException;
    027    import org.apache.commons.net.ProtocolCommandListener;
    028    import org.apache.commons.net.ProtocolCommandSupport;
    029    import org.apache.commons.net.SocketClient;
    030
    031    /***
    032     * The NNTP class is not meant to be used by itself and is provided
    033     * only so that you may easily implement your own NNTP client if
    034     * you so desire.  If you have no need to perform your own implementation,
    035     * you should use {@link org.apache.commons.net.nntp.NNTPClient}.
    036     * The NNTP class is made public to provide access to various NNTP constants
    037     * and to make it easier for adventurous programmers (or those with special
    038     * needs) to interact with the NNTP protocol and implement their own clients.
    039     * A set of methods with names corresponding to the NNTP command names are
    040     * provided to facilitate this interaction.
    041     * <p>
    042     * You should keep in mind that the NNTP server may choose to prematurely
    043     * close a connection if the client has been idle for longer than a
    044     * given time period or if the server is being shutdown by the operator or
    045     * some other reason.  The NNTP class will detect a
    046     * premature NNTP server connection closing when it receives a
    047     * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
    048     *  response to a command.
    049     * When that occurs, the NNTP class method encountering that reply will throw
    050     * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
    051     * .
    052     * <code>NNTPConectionClosedException</code>
    053     * is a subclass of <code> IOException </code> and therefore need not be
    054     * caught separately, but if you are going to catch it separately, its
    055     * catch block must appear before the more general <code> IOException </code>
    056     * catch block.  When you encounter an
    057     * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
    058     * , you must disconnect the connection with
    059     * {@link #disconnect  disconnect() } to properly clean up the
    060     * system resources used by NNTP.  Before disconnecting, you may check the
    061     * last reply code and text with
    062     * {@link #getReplyCode  getReplyCode } and
    063     * {@link #getReplyString  getReplyString }.
    064     * <p>
    065     * Rather than list it separately for each method, we mention here that
    066     * every method communicating with the server and throwing an IOException
    067     * can also throw a
    068     * {@link org.apache.commons.net.MalformedServerReplyException}
    069     * , which is a subclass
    070     * of IOException.  A MalformedServerReplyException will be thrown when
    071     * the reply received from the server deviates enough from the protocol
    072     * specification that it cannot be interpreted in a useful manner despite
    073     * attempts to be as lenient as possible.
    074     * <p>
    075     * <p>
    076     * @author Daniel F. Savarese
    077     * @author Rory Winston
    078     * @author Ted Wise
    079     * @see NNTPClient
    080     * @see NNTPConnectionClosedException
    081     * @see org.apache.commons.net.MalformedServerReplyException
    082     ***/
    083
    084    public class NNTP extends SocketClient
    085    {
    086        /*** The default NNTP port.  Its value is 119 according to RFC 977. ***/
    087        public static final int DEFAULT_PORT = 119;
    088
    089        // We have to ensure that the protocol communication is in ASCII
    090        // but we use ISO-8859-1 just in case 8-bit characters cross
    091        // the wire.
    092        private static final String __DEFAULT_ENCODING = "ISO-8859-1";
    093
    094        private StringBuffer __commandBuffer;
    095
    096        boolean _isAllowedToPost;
    097        int _replyCode;
    098        String _replyString;
    099
    100        /**
    101         * Wraps {@link SocketClient#_input_}
    102         * to communicate with server.  Initialized by {@link #_connectAction_}.
    103         * All server reads should be done through this variable.
    104         */
    105        protected BufferedReader _reader_;
    106
    107        /**
    108         * Wraps {@link SocketClient#_output_}
    109         * to communicate with server.  Initialized by {@link #_connectAction_}.
    110         * All server reads should be done through this variable.
    111         */
    112        protected BufferedWriter _writer_;
    113
    114        /***
    115         * A ProtocolCommandSupport object used to manage the registering of
    116         * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
    117         ***/
    118        protected ProtocolCommandSupport _commandSupport_;
    119
    120        /***
    121         * The default NNTP constructor.  Sets the default port to
    122         * <code>DEFAULT_PORT</code> and initializes internal data structures
    123         * for saving NNTP reply information.
    124         ***/
    125        public NNTP()
    126        {
    127            setDefaultPort(DEFAULT_PORT);
    128            __commandBuffer = new StringBuffer();
    129            _replyString = null;
    130            _reader_ = null;
    131            _writer_ = null;
    132            _isAllowedToPost = false;
    133            _commandSupport_ = new ProtocolCommandSupport(this);
    134        }
    135
    136        private void __getReply() throws IOException
    137        {
    138            _replyString = _reader_.readLine();
    139
    140            if (_replyString == null)
    141                throw new NNTPConnectionClosedException(
    142                    "Connection closed without indication.");
    143
    144            // In case we run into an anomaly we don't want fatal index exceptions
    145            // to be thrown.
    146            if (_replyString.length() < 3)
    147                throw new MalformedServerReplyException(
    148                    "Truncated server reply: " + _replyString);
    149            try
    150            {
    151                _replyCode = Integer.parseInt(_replyString.substring(0, 3));
    152            }
    153            catch (NumberFormatException e)
    154            {
    155                throw new MalformedServerReplyException(
    156                    "Could not parse response code.\nServer Reply: " + _replyString);
    157            }
    158
    159            if (_commandSupport_.getListenerCount() > 0)
    160                _commandSupport_.fireReplyReceived(_replyCode, _replyString +
    161                                                   SocketClient.NETASCII_EOL);
    162
    163            if (_replyCode == NNTPReply.SERVICE_DISCONTINUED)
    164                throw new NNTPConnectionClosedException(
    165                    "NNTP response 400 received.  Server closed connection.");
    166        }
    167
    168        /***
    169         * Initiates control connections and gets initial reply, determining
    170         * if the client is allowed to post to the server.  Initializes
    171         * {@link #_reader_} and {@link #_writer_} to wrap
    172         * {@link SocketClient#_input_} and {@link SocketClient#_output_}.
    173         ***/
    174        @Override
    175        protected void _connectAction_() throws IOException
    176        {
    177            super._connectAction_();
    178            _reader_ =
    179                new BufferedReader(new InputStreamReader(_input_,
    180                                                         __DEFAULT_ENCODING));
    181            _writer_ =
    182                new BufferedWriter(new OutputStreamWriter(_output_,
    183                                                          __DEFAULT_ENCODING));
    184            __getReply();
    185
    186            _isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED);
    187        }
    188
    189        /***
    190         * Adds a ProtocolCommandListener.  Delegates this task to
    191         * {@link #_commandSupport_  _commandSupport_ }.
    192         * <p>
    193         * @param listener  The ProtocolCommandListener to add.
    194         ***/
    195        public void addProtocolCommandListener(ProtocolCommandListener listener)
    196        {
    197            _commandSupport_.addProtocolCommandListener(listener);
    198        }
    199
    200        /***
    201         * Removes a ProtocolCommandListener.  Delegates this task to
    202         * {@link #_commandSupport_  _commandSupport_ }.
    203         * <p>
    204         * @param listener  The ProtocolCommandListener to remove.
    205         ***/
    206        public void removeProtocolCommandListener(ProtocolCommandListener listener)
    207        {
    208            _commandSupport_.removeProtocolCommandListener(listener);
    209        }
    210
    211        /***
    212         * Closes the connection to the NNTP server and sets to null
    213         * some internal data so that the memory may be reclaimed by the
    214         * garbage collector.  The reply text and code information from the
    215         * last command is voided so that the memory it used may be reclaimed.
    216         * <p>
    217         * @exception IOException If an error occurs while disconnecting.
    218         ***/
    219        @Override
    220        public void disconnect() throws IOException
    221        {
    222            super.disconnect();
    223            _reader_ = null;
    224            _writer_ = null;
    225            _replyString = null;
    226            _isAllowedToPost = false;
    227        }
    228
    229
    230        /***
    231         * Indicates whether or not the client is allowed to post articles to
    232         * the server it is currently connected to.
    233         * <p>
    234         * @return True if the client can post articles to the server, false
    235         *         otherwise.
    236         ***/
    237        public boolean isAllowedToPost()
    238        {
    239            return _isAllowedToPost;
    240        }
    241
    242
    243        /***
    244         * Sends an NNTP command to the server, waits for a reply and returns the
    245         * numerical response code.  After invocation, for more detailed
    246         * information, the actual reply text can be accessed by calling
    247         * {@link #getReplyString  getReplyString }.
    248         * <p>
    249         * @param command  The text representation of the  NNTP command to send.
    250         * @param args The arguments to the NNTP command.  If this parameter is
    251         *             set to null, then the command is sent with no argument.
    252         * @return The integer value of the NNTP reply code returned by the server
    253         *         in response to the command.
    254         * @exception NNTPConnectionClosedException
    255         *      If the NNTP server prematurely closes the connection as a result
    256         *      of the client being idle or some other reason causing the server
    257         *      to send NNTP reply code 400.  This exception may be caught either
    258         *      as an IOException or independently as itself.
    259         * @exception IOException  If an I/O error occurs while either sending the
    260         *      command or receiving the server reply.
    261         ***/
    262        public int sendCommand(String command, String args) throws IOException
    263        {
    264            String message;
    265
    266            __commandBuffer.setLength(0);
    267            __commandBuffer.append(command);
    268
    269            if (args != null)
    270            {
    271                __commandBuffer.append(' ');
    272                __commandBuffer.append(args);
    273            }
    274            __commandBuffer.append(SocketClient.NETASCII_EOL);
    275
    276            _writer_.write(message = __commandBuffer.toString());
    277            _writer_.flush();
    278
    279            if (_commandSupport_.getListenerCount() > 0)
    280                _commandSupport_.fireCommandSent(command, message);
    281
    282            __getReply();
    283            return _replyCode;
    284        }
    285
    286
    287        /***
    288         * Sends an NNTP command to the server, waits for a reply and returns the
    289         * numerical response code.  After invocation, for more detailed
    290         * information, the actual reply text can be accessed by calling
    291         * {@link #getReplyString  getReplyString }.
    292         * <p>
    293         * @param command  The NNTPCommand constant corresponding to the NNTP command
    294         *                 to send.
    295         * @param args The arguments to the NNTP command.  If this parameter is
    296         *             set to null, then the command is sent with no argument.
    297         * @return The integer value of the NNTP reply code returned by the server
    298         *         in response to the command.
    299         *         in response to the command.
    300         * @exception NNTPConnectionClosedException
    301         *      If the NNTP server prematurely closes the connection as a result
    302         *      of the client being idle or some other reason causing the server
    303         *      to send NNTP reply code 400.  This exception may be caught either
    304         *      as an IOException or independently as itself.
    305         * @exception IOException  If an I/O error occurs while either sending the
    306         *      command or receiving the server reply.
    307         ***/
    308        public int sendCommand(int command, String args) throws IOException
    309        {
    310            return sendCommand(NNTPCommand._commands[command], args);
    311        }
    312
    313
    314        /***
    315         * Sends an NNTP command with no arguments to the server, waits for a
    316         * reply and returns the numerical response code.  After invocation, for
    317         * more detailed information, the actual reply text can be accessed by
    318         * calling {@link #getReplyString  getReplyString }.
    319         * <p>
    320         * @param command  The text representation of the  NNTP command to send.
    321         * @return The integer value of the NNTP reply code returned by the server
    322         *         in response to the command.
    323         *         in response to the command.
    324         * @exception NNTPConnectionClosedException
    325         *      If the NNTP server prematurely closes the connection as a result
    326         *      of the client being idle or some other reason causing the server
    327         *      to send NNTP reply code 400.  This exception may be caught either
    328         *      as an IOException or independently as itself.
    329         * @exception IOException  If an I/O error occurs while either sending the
    330         *      command or receiving the server reply.
    331         ***/
    332        public int sendCommand(String command) throws IOException
    333        {
    334            return sendCommand(command, null);
    335        }
    336
    337
    338        /***
    339         * Sends an NNTP command with no arguments to the server, waits for a
    340         * reply and returns the numerical response code.  After invocation, for
    341         * more detailed information, the actual reply text can be accessed by
    342         * calling {@link #getReplyString  getReplyString }.
    343         * <p>
    344         * @param command  The NNTPCommand constant corresponding to the NNTP command
    345         *                 to send.
    346         * @return The integer value of the NNTP reply code returned by the server
    347         *         in response to the command.
    348         *         in response to the command.
    349         * @exception NNTPConnectionClosedException
    350         *      If the NNTP server prematurely closes the connection as a result
    351         *      of the client being idle or some other reason causing the server
    352         *      to send NNTP reply code 400.  This exception may be caught either
    353         *      as an IOException or independently as itself.
    354         * @exception IOException  If an I/O error occurs while either sending the
    355         *      command or receiving the server reply.
    356         ***/
    357        public int sendCommand(int command) throws IOException
    358        {
    359            return sendCommand(command, null);
    360        }
    361
    362
    363        /***
    364         * Returns the integer value of the reply code of the last NNTP reply.
    365         * You will usually only use this method after you connect to the
    366         * NNTP server to check that the connection was successful since
    367         * <code> connect </code> is of type void.
    368         * <p>
    369         * @return The integer value of the reply code of the last NNTP reply.
    370         ***/
    371        public int getReplyCode()
    372        {
    373            return _replyCode;
    374        }
    375
    376        /***
    377         * Fetches a reply from the NNTP server and returns the integer reply
    378         * code.  After calling this method, the actual reply text can be accessed
    379         * from {@link #getReplyString  getReplyString }.  Only use this
    380         * method if you are implementing your own NNTP client or if you need to
    381         * fetch a secondary response from the NNTP server.
    382         * <p>
    383         * @return The integer value of the reply code of the fetched NNTP reply.
    384         *         in response to the command.
    385         * @exception NNTPConnectionClosedException
    386         *      If the NNTP server prematurely closes the connection as a result
    387         *      of the client being idle or some other reason causing the server
    388         *      to send NNTP reply code 400.  This exception may be caught either
    389         *      as an IOException or independently as itself.
    390         * @exception IOException  If an I/O error occurs while
    391         *      receiving the server reply.
    392         ***/
    393        public int getReply() throws IOException
    394        {
    395            __getReply();
    396            return _replyCode;
    397        }
    398
    399
    400        /***
    401         * Returns the entire text of the last NNTP server response exactly
    402         * as it was received, not including the end of line marker.
    403         * <p>
    404         * @return The entire text from the last NNTP response as a String.
    405         ***/
    406        public String getReplyString()
    407        {
    408            return _replyString;
    409        }
    410
    411
    412        /***
    413         * A convenience method to send the NNTP ARTICLE command to the server,
    414         * receive the initial reply, and return the reply code.
    415         * <p>
    416         * @param messageId  The message identifier of the requested article,
    417         *                   including the encapsulating &lt and &gt characters.
    418         * @return The reply code received from the server.
    419         * @exception NNTPConnectionClosedException
    420         *      If the NNTP server prematurely closes the connection as a result
    421         *      of the client being idle or some other reason causing the server
    422         *      to send NNTP reply code 400.  This exception may be caught either
    423         *      as an IOException or independently as itself.
    424         * @exception IOException  If an I/O error occurs while either sending the
    425         *      command or receiving the server reply.
    426         ***/
    427        public int article(String messageId) throws IOException
    428        {
    429            return sendCommand(NNTPCommand.ARTICLE, messageId);
    430        }
    431
    432        /***
    433         * A convenience method to send the NNTP ARTICLE command to the server,
    434         * receive the initial reply, and return the reply code.
    435         * <p>
    436         * @param articleNumber The number of the article to request from the
    437         *                      currently selected newsgroup.
    438         * @return The reply code received from the server.
    439         * @exception NNTPConnectionClosedException
    440         *      If the NNTP server prematurely closes the connection as a result
    441         *      of the client being idle or some other reason causing the server
    442         *      to send NNTP reply code 400.  This exception may be caught either
    443         *      as an IOException or independently as itself.
    444         * @exception IOException  If an I/O error occurs while either sending the
    445         *      command or receiving the server reply.
    446         ***/
    447        public int article(int articleNumber) throws IOException
    448        {
    449            return sendCommand(NNTPCommand.ARTICLE, Integer.toString(articleNumber));
    450        }
    451
    452        /***
    453         * A convenience method to send the NNTP ARTICLE command to the server,
    454         * receive the initial reply, and return the reply code.
    455         * <p>
    456         * @return The reply code received from the server.
    457         * @exception NNTPConnectionClosedException
    458         *      If the NNTP server prematurely closes the connection as a result
    459         *      of the client being idle or some other reason causing the server
    460         *      to send NNTP reply code 400.  This exception may be caught either
    461         *      as an IOException or independently as itself.
    462         * @exception IOException  If an I/O error occurs while either sending the
    463         *      command or receiving the server reply.
    464         ***/
    465        public int article() throws IOException
    466        {
    467            return sendCommand(NNTPCommand.ARTICLE);
    468        }
    469
    470
    471
    472        /***
    473         * A convenience method to send the NNTP BODY command to the server,
    474         * receive the initial reply, and return the reply code.
    475         * <p>
    476         * @param messageId  The message identifier of the requested article,
    477         *                   including the encapsulating &lt and &gt characters.
    478         * @return The reply code received from the server.
    479         * @exception NNTPConnectionClosedException
    480         *      If the NNTP server prematurely closes the connection as a result
    481         *      of the client being idle or some other reason causing the server
    482         *      to send NNTP reply code 400.  This exception may be caught either
    483         *      as an IOException or independently as itself.
    484         * @exception IOException  If an I/O error occurs while either sending the
    485         *      command or receiving the server reply.
    486         ***/
    487        public int body(String messageId) throws IOException
    488        {
    489            return sendCommand(NNTPCommand.BODY, messageId);
    490        }
    491
    492        /***
    493         * A convenience method to send the NNTP BODY command to the server,
    494         * receive the initial reply, and return the reply code.
    495         * <p>
    496         * @param articleNumber The number of the article to request from the
    497         *                      currently selected newsgroup.
    498         * @return The reply code received from the server.
    499         * @exception NNTPConnectionClosedException
    500         *      If the NNTP server prematurely closes the connection as a result
    501         *      of the client being idle or some other reason causing the server
    502         *      to send NNTP reply code 400.  This exception may be caught either
    503         *      as an IOException or independently as itself.
    504         * @exception IOException  If an I/O error occurs while either sending the
    505         *      command or receiving the server reply.
    506         ***/
    507        public int body(int articleNumber) throws IOException
    508        {
    509            return sendCommand(NNTPCommand.BODY, Integer.toString(articleNumber));
    510        }
    511
    512        /***
    513         * A convenience method to send the NNTP BODY command to the server,
    514         * receive the initial reply, and return the reply code.
    515         * <p>
    516         * @return The reply code received from the server.
    517         * @exception NNTPConnectionClosedException
    518         *      If the NNTP server prematurely closes the connection as a result
    519         *      of the client being idle or some other reason causing the server
    520         *      to send NNTP reply code 400.  This exception may be caught either
    521         *      as an IOException or independently as itself.
    522         * @exception IOException  If an I/O error occurs while either sending the
    523         *      command or receiving the server reply.
    524         ***/
    525        public int body() throws IOException
    526        {
    527            return sendCommand(NNTPCommand.BODY);
    528        }
    529
    530
    531
    532        /***
    533         * A convenience method to send the NNTP HEAD command to the server,
    534         * receive the initial reply, and return the reply code.
    535         * <p>
    536         * @param messageId  The message identifier of the requested article,
    537         *                   including the encapsulating &lt and &gt characters.
    538         * @return The reply code received from the server.
    539         * @exception NNTPConnectionClosedException
    540         *      If the NNTP server prematurely closes the connection as a result
    541         *      of the client being idle or some other reason causing the server
    542         *      to send NNTP reply code 400.  This exception may be caught either
    543         *      as an IOException or independently as itself.
    544         * @exception IOException  If an I/O error occurs while either sending the
    545         *      command or receiving the server reply.
    546         ***/
    547        public int head(String messageId) throws IOException
    548        {
    549            return sendCommand(NNTPCommand.HEAD, messageId);
    550        }
    551
    552        /***
    553         * A convenience method to send the NNTP HEAD command to the server,
    554         * receive the initial reply, and return the reply code.
    555         * <p>
    556         * @param articleNumber The number of the article to request from the
    557         *                      currently selected newsgroup.
    558         * @return The reply code received from the server.
    559         * @exception NNTPConnectionClosedException
    560         *      If the NNTP server prematurely closes the connection as a result
    561         *      of the client being idle or some other reason causing the server
    562         *      to send NNTP reply code 400.  This exception may be caught either
    563         *      as an IOException or independently as itself.
    564         * @exception IOException  If an I/O error occurs while either sending the
    565         *      command or receiving the server reply.
    566         ***/
    567        public int head(int articleNumber) throws IOException
    568        {
    569            return sendCommand(NNTPCommand.HEAD, Integer.toString(articleNumber));
    570        }
    571
    572        /***
    573         * A convenience method to send the NNTP HEAD command to the server,
    574         * receive the initial reply, and return the reply code.
    575         * <p>
    576         * @return The reply code received from the server.
    577         * @exception NNTPConnectionClosedException
    578         *      If the NNTP server prematurely closes the connection as a result
    579         *      of the client being idle or some other reason causing the server
    580         *      to send NNTP reply code 400.  This exception may be caught either
    581         *      as an IOException or independently as itself.
    582         * @exception IOException  If an I/O error occurs while either sending the
    583         *      command or receiving the server reply.
    584         ***/
    585        public int head() throws IOException
    586        {
    587            return sendCommand(NNTPCommand.HEAD);
    588        }
    589
    590
    591
    592        /***
    593         * A convenience method to send the NNTP STAT command to the server,
    594         * receive the initial reply, and return the reply code.
    595         * <p>
    596         * @param messageId  The message identifier of the requested article,
    597         *                   including the encapsulating &lt and &gt characters.
    598         * @return The reply code received from the server.
    599         * @exception NNTPConnectionClosedException
    600         *      If the NNTP server prematurely closes the connection as a result
    601         *      of the client being idle or some other reason causing the server
    602         *      to send NNTP reply code 400.  This exception may be caught either
    603         *      as an IOException or independently as itself.
    604         * @exception IOException  If an I/O error occurs while either sending the
    605         *      command or receiving the server reply.
    606         ***/
    607        public int stat(String messageId) throws IOException
    608        {
    609            return sendCommand(NNTPCommand.STAT, messageId);
    610        }
    611
    612        /***
    613         * A convenience method to send the NNTP STAT command to the server,
    614         * receive the initial reply, and return the reply code.
    615         * <p>
    616         * @param articleNumber The number of the article to request from the
    617         *                      currently selected newsgroup.
    618         * @return The reply code received from the server.
    619         * @exception NNTPConnectionClosedException
    620         *      If the NNTP server prematurely closes the connection as a result
    621         *      of the client being idle or some other reason causing the server
    622         *      to send NNTP reply code 400.  This exception may be caught either
    623         *      as an IOException or independently as itself.
    624         * @exception IOException  If an I/O error occurs while either sending the
    625         *      command or receiving the server reply.
    626         ***/
    627        public int stat(int articleNumber) throws IOException
    628        {
    629            return sendCommand(NNTPCommand.STAT, Integer.toString(articleNumber));
    630        }
    631
    632        /***
    633         * A convenience method to send the NNTP STAT command to the server,
    634         * receive the initial reply, and return the reply code.
    635         * <p>
    636         * @return The reply code received from the server.
    637         * @exception NNTPConnectionClosedException
    638         *      If the NNTP server prematurely closes the connection as a result
    639         *      of the client being idle or some other reason causing the server
    640         *      to send NNTP reply code 400.  This exception may be caught either
    641         *      as an IOException or independently as itself.
    642         * @exception IOException  If an I/O error occurs while either sending the
    643         *      command or receiving the server reply.
    644         ***/
    645        public int stat() throws IOException
    646        {
    647            return sendCommand(NNTPCommand.STAT);
    648        }
    649
    650
    651        /***
    652         * A convenience method to send the NNTP GROUP command to the server,
    653         * receive the reply, and return the reply code.
    654         * <p>
    655         * @param newsgroup  The name of the newsgroup to select.
    656         * @return The reply code received from the server.
    657         * @exception NNTPConnectionClosedException
    658         *      If the NNTP server prematurely closes the connection as a result
    659         *      of the client being idle or some other reason causing the server
    660         *      to send NNTP reply code 400.  This exception may be caught either
    661         *      as an IOException or independently as itself.
    662         * @exception IOException  If an I/O error occurs while either sending the
    663         *      command or receiving the server reply.
    664         ***/
    665        public int group(String newsgroup) throws IOException
    666        {
    667            return sendCommand(NNTPCommand.GROUP, newsgroup);
    668        }
    669
    670
    671        /***
    672         * A convenience method to send the NNTP HELP command to the server,
    673         * receive the reply, and return the reply code.
    674         * <p>
    675         * @return The reply code received from the server.
    676         * @exception NNTPConnectionClosedException
    677         *      If the NNTP server prematurely closes the connection as a result
    678         *      of the client being idle or some other reason causing the server
    679         *      to send NNTP reply code 400.  This exception may be caught either
    680         *      as an IOException or independently as itself.
    681         * @exception IOException  If an I/O error occurs while either sending the
    682         *      command or receiving the server reply.
    683         ***/
    684        public int help() throws IOException
    685        {
    686            return sendCommand(NNTPCommand.HELP);
    687        }
    688
    689
    690        /***
    691         * A convenience method to send the NNTP IHAVE command to the server,
    692         * receive the reply, and return the reply code.
    693         * <p>
    694         * @param messageId  The article identifier,
    695         *                   including the encapsulating &lt and &gt characters.
    696         * @return The reply code received from the server.
    697         * @exception NNTPConnectionClosedException
    698         *      If the NNTP server prematurely closes the connection as a result
    699         *      of the client being idle or some other reason causing the server
    700         *      to send NNTP reply code 400.  This exception may be caught either
    701         *      as an IOException or independently as itself.
    702         * @exception IOException  If an I/O error occurs while either sending the
    703         *      command or receiving the server reply.
    704         ***/
    705        public int ihave(String messageId) throws IOException
    706        {
    707            return sendCommand(NNTPCommand.IHAVE, messageId);
    708        }
    709
    710
    711        /***
    712         * A convenience method to send the NNTP LAST command to the server,
    713         * receive the reply, and return the reply code.
    714         * <p>
    715         * @return The reply code received from the server.
    716         * @exception NNTPConnectionClosedException
    717         *      If the NNTP server prematurely closes the connection as a result
    718         *      of the client being idle or some other reason causing the server
    719         *      to send NNTP reply code 400.  This exception may be caught either
    720         *      as an IOException or independently as itself.
    721         * @exception IOException  If an I/O error occurs while either sending the
    722         *      command or receiving the server reply.
    723         ***/
    724        public int last() throws IOException
    725        {
    726            return sendCommand(NNTPCommand.LAST);
    727        }
    728
    729
    730
    731        /***
    732         * A convenience method to send the NNTP LIST command to the server,
    733         * receive the reply, and return the reply code.
    734         * <p>
    735         * @return The reply code received from the server.
    736         * @exception NNTPConnectionClosedException
    737         *      If the NNTP server prematurely closes the connection as a result
    738         *      of the client being idle or some other reason causing the server
    739         *      to send NNTP reply code 400.  This exception may be caught either
    740         *      as an IOException or independently as itself.
    741         * @exception IOException  If an I/O error occurs while either sending the
    742         *      command or receiving the server reply.
    743         ***/
    744        public int list() throws IOException
    745        {
    746            return sendCommand(NNTPCommand.LIST);
    747        }
    748
    749
    750
    751        /***
    752         * A convenience method to send the NNTP NEXT command to the server,
    753         * receive the reply, and return the reply code.
    754         * <p>
    755         * @return The reply code received from the server.
    756         * @exception NNTPConnectionClosedException
    757         *      If the NNTP server prematurely closes the connection as a result
    758         *      of the client being idle or some other reason causing the server
    759         *      to send NNTP reply code 400.  This exception may be caught either
    760         *      as an IOException or independently as itself.
    761         * @exception IOException  If an I/O error occurs while either sending the
    762         *      command or receiving the server reply.
    763         ***/
    764        public int next() throws IOException
    765        {
    766            return sendCommand(NNTPCommand.NEXT);
    767        }
    768
    769
    770        /***
    771         * A convenience method to send the NNTP NEWGROUPS command to the server,
    772         * receive the reply, and return the reply code.
    773         * <p>
    774         * @param date The date after which to check for new groups.
    775         *             Date format is YYMMDD
    776         * @param time The time after which to check for new groups.
    777         *             Time format is HHMMSS using a 24-hour clock.
    778         * @param GMT  True if the time is in GMT, false if local server time.
    779         * @param distributions  Comma-separated distribution list to check for
    780         *            new groups. Set to null if no distributions.
    781         * @return The reply code received from the server.
    782         * @exception NNTPConnectionClosedException
    783         *      If the NNTP server prematurely closes the connection as a result
    784         *      of the client being idle or some other reason causing the server
    785         *      to send NNTP reply code 400.  This exception may be caught either
    786         *      as an IOException or independently as itself.
    787         * @exception IOException  If an I/O error occurs while either sending the
    788         *      command or receiving the server reply.
    789         ***/
    790        public int newgroups(String date, String time, boolean GMT,
    791                             String distributions) throws IOException
    792        {
    793            StringBuilder buffer = new StringBuilder();
    794
    795            buffer.append(date);
    796            buffer.append(' ');
    797            buffer.append(time);
    798
    799            if (GMT)
    800            {
    801                buffer.append(' ');
    802                buffer.append("GMT");
    803            }
    804
    805            if (distributions != null)
    806            {
    807                buffer.append(" <");
    808                buffer.append(distributions);
    809                buffer.append('>');
    810            }
    811
    812            return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString());
    813        }
    814
    815
    816        /***
    817         * A convenience method to send the NNTP NEWGROUPS command to the server,
    818         * receive the reply, and return the reply code.
    819         * <p>
    820         * @param newsgroups A comma-separated list of newsgroups to check for new
    821         *             news.
    822         * @param date The date after which to check for new news.
    823         *             Date format is YYMMDD
    824         * @param time The time after which to check for new news.
    825         *             Time format is HHMMSS using a 24-hour clock.
    826         * @param GMT  True if the time is in GMT, false if local server time.
    827         * @param distributions  Comma-separated distribution list to check for
    828         *            new news. Set to null if no distributions.
    829         * @return The reply code received from the server.
    830         * @exception NNTPConnectionClosedException
    831         *      If the NNTP server prematurely closes the connection as a result
    832         *      of the client being idle or some other reason causing the server
    833         *      to send NNTP reply code 400.  This exception may be caught either
    834         *      as an IOException or independently as itself.
    835         * @exception IOException  If an I/O error occurs while either sending the
    836         *      command or receiving the server reply.
    837         ***/
    838        public int newnews(String newsgroups, String date, String time, boolean GMT,
    839                           String distributions) throws IOException
    840        {
    841            StringBuilder buffer = new StringBuilder();
    842
    843            buffer.append(newsgroups);
    844            buffer.append(' ');
    845            buffer.append(date);
    846            buffer.append(' ');
    847            buffer.append(time);
    848
    849            if (GMT)
    850            {
    851                buffer.append(' ');
    852                buffer.append("GMT");
    853            }
    854
    855            if (distributions != null)
    856            {
    857                buffer.append(" <");
    858                buffer.append(distributions);
    859                buffer.append('>');
    860            }
    861
    862            return sendCommand(NNTPCommand.NEWNEWS, buffer.toString());
    863        }
    864
    865
    866
    867        /***
    868         * A convenience method to send the NNTP POST command to the server,
    869         * receive the reply, and return the reply code.
    870         * <p>
    871         * @return The reply code received from the server.
    872         * @exception NNTPConnectionClosedException
    873         *      If the NNTP server prematurely closes the connection as a result
    874         *      of the client being idle or some other reason causing the server
    875         *      to send NNTP reply code 400.  This exception may be caught either
    876         *      as an IOException or independently as itself.
    877         * @exception IOException  If an I/O error occurs while either sending the
    878         *      command or receiving the server reply.
    879         ***/
    880        public int post() throws IOException
    881        {
    882            return sendCommand(NNTPCommand.POST);
    883        }
    884
    885
    886
    887        /***
    888         * A convenience method to send the NNTP QUIT command to the server,
    889         * receive the reply, and return the reply code.
    890         * <p>
    891         * @return The reply code received from the server.
    892         * @exception NNTPConnectionClosedException
    893         *      If the NNTP server prematurely closes the connection as a result
    894         *      of the client being idle or some other reason causing the server
    895         *      to send NNTP reply code 400.  This exception may be caught either
    896         *      as an IOException or independently as itself.
    897         * @exception IOException  If an I/O error occurs while either sending the
    898         *      command or receiving the server reply.
    899         ***/
    900        public int quit() throws IOException
    901        {
    902            return sendCommand(NNTPCommand.QUIT);
    903        }
    904
    905        /***
    906         * A convenience method to send the AUTHINFO USER command to the server,
    907         *  receive the reply, and return the reply code. (See RFC 2980)
    908         * <p>
    909         * @param username A valid username.
    910         * @return The reply code received from the server. The server should
    911         *          return a 381 or 281 for this command.
    912         * @exception NNTPConnectionClosedException
    913         *      If the NNTP server prematurely closes the connection as a result
    914         *      of the client being idle or some other reason causing the server
    915         *      to send NNTP reply code 400.  This exception may be caught either
    916         *      as an IOException or independently as itself.
    917         * @exception IOException  If an I/O error occurs while either sending the
    918         *      command or receiving the server reply.
    919         ***/
    920        public int authinfoUser(String username) throws IOException {
    921            String userParameter = "USER " + username;
    922            return sendCommand(NNTPCommand.AUTHINFO, userParameter);
    923        }
    924
    925        /***
    926         * A convenience method to send the AUTHINFO PASS command to the server,
    927         * receive the reply, and return the reply code.  If this step is
    928         * required, it should immediately follow the AUTHINFO USER command
    929         * (See RFC 2980)
    930         * <p>
    931         * @param password a valid password.
    932         * @return The reply code received from the server. The server should
    933         *         return a 281 or 502 for this command.
    934         * @exception NNTPConnectionClosedException
    935         *      If the NNTP server prematurely closes the connection as a result
    936         *      of the client being idle or some other reason causing the server
    937         *      to send NNTP reply code 400.  This exception may be caught either
    938         *      as an IOException or independently as itself.
    939         * @exception IOException  If an I/O error occurs while either sending the
    940         *      command or receiving the server reply.
    941         ***/
    942        public int authinfoPass(String password) throws IOException {
    943            String passParameter = "PASS " + password;
    944            return sendCommand(NNTPCommand.AUTHINFO, passParameter);
    945        }
    946
    947        /***
    948         * A convenience method to send the NNTP XOVER command to the server,
    949         * receive the reply, and return the reply code.
    950         * <p>
    951         * @param selectedArticles a String representation of the range of
    952         * article headers required. This may be an article number, or a
    953         * range of article numbers in the form "XXXX-YYYY", where XXXX
    954         * and YYYY are valid article numbers in the current group.  It
    955         * also may be of the form "XXX-", meaning "return XXX and all
    956         * following articles" In this revision, the last format is not
    957         * possible (yet).
    958         * @return The reply code received from the server.
    959         * @exception NNTPConnectionClosedException
    960         *      If the NNTP server prematurely closes the connection as a result
    961         *      of the client being idle or some other reason causing the server
    962         *      to send NNTP reply code 400.  This exception may be caught either
    963         *      as an IOException or independently as itself.
    964         * @exception IOException  If an I/O error occurs while either sending the
    965         *      command or receiving the server reply.
    966         ***/
    967        public int xover(String selectedArticles) throws IOException {
    968            return sendCommand(NNTPCommand.XOVER, selectedArticles);
    969        }
    970
    971        /***
    972         * A convenience method to send the NNTP XHDR command to the server,
    973         * receive the reply, and return the reply code.
    974         * <p>
    975         * @param header a String naming a header line (e.g., "subject").  See
    976         * RFC-1036 for a list of valid header lines.
    977         * @param selectedArticles a String representation of the range of
    978         * article headers required. This may be an article number, or a
    979         * range of article numbers in the form "XXXX-YYYY", where XXXX
    980         * and YYYY are valid article numbers in the current group.  It
    981         * also may be of the form "XXX-", meaning "return XXX and all
    982         * following articles" In this revision, the last format is not
    983         * possible (yet).
    984         * @return The reply code received from the server.
    985         * @exception NNTPConnectionClosedException
    986         *      If the NNTP server prematurely closes the connection as a result
    987         *      of the client being idle or some other reason causing the server
    988         *      to send NNTP reply code 400.  This exception may be caught either
    989         *      as an IOException or independently as itself.
    990         * @exception IOException  If an I/O error occurs while either sending the
    991         *      command or receiving the server reply.
    992         ***/
    993        public int xhdr(String header, String selectedArticles) throws IOException {
    994            StringBuilder command = new StringBuilder(header);
    995            command.append(" ");
    996            command.append(selectedArticles);
    997            return sendCommand(NNTPCommand.XHDR, command.toString());
    998        }
    999
    1000        /**
    1001         * A convenience wrapper for the extended LIST command that takes
    1002         * an argument, allowing us to selectively list multiple groups.
    1003         * <p>
    1004         * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for
    1005         *                details.
    1006         * @return the reply code received from the server.
    1007         * @throws IOException
    1008         */
    1009        public int listActive(String wildmat) throws IOException {
    1010            StringBuilder command = new StringBuilder("ACTIVE ");
    1011            command.append(wildmat);
    1012            return sendCommand(NNTPCommand.LIST, command.toString());
    1013        }
    1014    }
    1015
    1016    /* Emacs configuration
    1017     * Local variables:        **
    1018     * mode:             java  **
    1019     * c-basic-offset:   4     **
    1020     * indent-tabs-mode: nil   **
    1021     * End:                    **
    1022     */