/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.net.nntp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Vector;

import org.apache.commons.net.MalformedServerReplyException;
import org.apache.commons.net.io.DotTerminatedMessageReader;
import org.apache.commons.net.io.DotTerminatedMessageWriter;
import org.apache.commons.net.io.Util;
import org.apache.commons.net.util.NetConstants;

/**
 * NNTPClient encapsulates all the functionality necessary to post and
 * retrieve articles from an NNTP server.  As with all classes derived
 * from {@link org.apache.commons.net.SocketClient},
 * you must first connect to the server with
 * {@link org.apache.commons.net.SocketClient#connect  connect }
 * before doing anything, and finally
 * {@link org.apache.commons.net.nntp.NNTP#disconnect  disconnect() }
 * after you're completely finished interacting with the server.
 * Remember that the
 * {@link org.apache.commons.net.nntp.NNTP#isAllowedToPost isAllowedToPost()}
 *  method is defined in
 * {@link org.apache.commons.net.nntp.NNTP}.
 * <p>
 * You should keep in mind that the NNTP server may choose to prematurely
 * close a connection if the client has been idle for longer than a
 * given time period or if the server is being shutdown by the operator or
 * some other reason.  The NNTP class will detect a
 * premature NNTP server connection closing when it receives a
 * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
 *  response to a command.
 * When that occurs, the NNTP class method encountering that reply will throw
 * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
 * .
 * <code>NNTPConectionClosedException</code>
 * is a subclass of <code> IOException </code> and therefore need not be
 * caught separately, but if you are going to catch it separately, its
 * catch block must appear before the more general <code> IOException </code>
 * catch block.  When you encounter an
 * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
 * , you must disconnect the connection with
 * {@link org.apache.commons.net.nntp.NNTP#disconnect  disconnect() }
 *  to properly clean up the
 * system resources used by NNTP.  Before disconnecting, you may check the
 * last reply code and text with
 * {@link org.apache.commons.net.nntp.NNTP#getReplyCode  getReplyCode } and
 * {@link org.apache.commons.net.nntp.NNTP#getReplyString  getReplyString }.
 * <p>
 * Rather than list it separately for each method, we mention here that
 * every method communicating with the server and throwing an IOException
 * can also throw a
 * {@link org.apache.commons.net.MalformedServerReplyException}
 * , which is a subclass
 * of IOException.  A MalformedServerReplyException will be thrown when
 * the reply received from the server deviates enough from the protocol
 * specification that it cannot be interpreted in a useful manner despite
 * attempts to be as lenient as possible.
 *
 * @see NNTP
 * @see NNTPConnectionClosedException
 * @see org.apache.commons.net.MalformedServerReplyException
 */

public class NNTPClient extends NNTP
{

    private static final NewsgroupInfo[] EMPTY_NEWSGROUP_INFO_ARRAY = new NewsgroupInfo[0];

    /**
     * Parse a response line from {@link #retrieveArticleInfo(long, long)}.
     *
     * @param line a response line
     * @return the parsed {@link Article}, if unparseable then isDummy()
     * will be true, and the subject will contain the raw info.
     * @since 3.0
     */
    static Article parseArticleEntry(final String line) {
        // Extract the article information
        // Mandatory format (from NNTP RFC 2980) is :
        // articleNumber\tSubject\tAuthor\tDate\tID\tReference(s)\tByte Count\tLine Count

        final Article article = new Article();
        article.setSubject(line); // in case parsing fails
        final String parts[] = line.split("\t");
        if (parts.length > 6) {
            int i = 0;
            try {
                article.setArticleNumber(Long.parseLong(parts[i++]));
                article.setSubject(parts[i++]);
                article.setFrom(parts[i++]);
                article.setDate(parts[i++]);
                article.setArticleId(parts[i++]);
                article.addReference(parts[i++]);
            } catch (final NumberFormatException e) {
                // ignored, already handled
            }
        }
        return article;
    }

    /*
     * 211 n f l s group selected
     *     (n = estimated number of articles in group,
     *     f = first article number in the group,
     *     l = last article number in the group,
     *     s = name of the group.)
     */

    private static void parseGroupReply(final String reply, final NewsgroupInfo info)
    throws MalformedServerReplyException
    {
        final String tokens[] = reply.split(" ");
        if (tokens.length >= 5) {
            int i = 1;  // Skip numeric response value
            try
            {
                // Get estimated article count
                info.setArticleCount(Long.parseLong(tokens[i++]));
                // Get first article number
                info.setFirstArticle(Long.parseLong(tokens[i++]));
                // Get last article number
                info.setLastArticle(Long.parseLong(tokens[i++]));
                // Get newsgroup name
                info.setNewsgroup(tokens[i++]);

                info.setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
                return ;
            } catch (final NumberFormatException e)
            {
               // drop through to report error
            }
        }

        throw new MalformedServerReplyException(
            "Could not parse newsgroup info.\nServer reply: " + reply);
    }


    // Format: group last first p
    static NewsgroupInfo parseNewsgroupListEntry(final String entry)
    {
        final String tokens[] = entry.split(" ");
        if (tokens.length < 4) {
            return null;
        }
        final NewsgroupInfo result = new NewsgroupInfo();

        int i = 0;

        result.setNewsgroup(tokens[i++]);

        try
        {
            final long lastNum = Long.parseLong(tokens[i++]);
            final long firstNum = Long.parseLong(tokens[i++]);
            result.setFirstArticle(firstNum);
            result.setLastArticle(lastNum);
            if ((firstNum == 0) && (lastNum == 0)) {
                result.setArticleCount(0);
            } else {
                result.setArticleCount(lastNum - firstNum + 1);
            }
        } catch (final NumberFormatException e) {
            return null;
        }

        switch (tokens[i++].charAt(0))
        {
        case 'y':
        case 'Y':
            result.setPostingPermission(
                NewsgroupInfo.PERMITTED_POSTING_PERMISSION);
            break;
        case 'n':
        case 'N':
            result.setPostingPermission(
                NewsgroupInfo.PROHIBITED_POSTING_PERMISSION);
            break;
        case 'm':
        case 'M':
            result.setPostingPermission(
                NewsgroupInfo.MODERATED_POSTING_PERMISSION);
            break;
        default:
            result.setPostingPermission(
                NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
            break;
        }

        return result;
    }

    @SuppressWarnings("deprecation")
    private void ai2ap(final ArticleInfo ai, final ArticlePointer ap){
        if (ap != null) { // ai cannot be null
            ap.articleId = ai.articleId;
            ap.articleNumber = (int) ai.articleNumber;
        }
    }

    private ArticleInfo ap2ai(@SuppressWarnings("deprecation") final ArticlePointer ap) {
        if (ap == null) {
            return null;
        }
        final ArticleInfo ai = new ArticleInfo();
        return ai;
    }


    /**
     * Log into a news server by sending the AUTHINFO USER/AUTHINFO
     * PASS command sequence. This is usually sent in response to a
     * 480 reply code from the NNTP server.
     * <p>
     * @param username a valid username
     * @param password the corresponding password
     * @return True for successful login, false for a failure
     * @throws IOException on error
     */
    public boolean authenticate(final String username, final String password)
        throws IOException
    {
        int replyCode = authinfoUser(username);

        if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED)
            {
                replyCode = authinfoPass(password);

                if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED)
                    {
                        this._isAllowedToPost = true;
                        return true;
                    }
            }
        return false;
    }


    /**
     * There are a few NNTPClient methods that do not complete the
     * entire sequence of NNTP commands to complete a transaction.  These
     * commands require some action by the programmer after the reception
     * of a positive preliminary command.  After the programmer's code
     * completes its actions, it must call this method to receive
     * the completion reply from the server and verify the success of the
     * entire transaction.
     * <p>
     * For example
     * <pre>
     * writer = client.postArticle();
     * if(writer == null) // failure
     *   return false;
     * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
     * header.addNewsgroup("alt.test");
     * writer.write(header.toString());
     * writer.write("This is just a test");
     * writer.close();
     * if(!client.completePendingCommand()) // failure
     *   return false;
     * </pre>
     * <p>
     * @return True if successfully completed, false if not.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean completePendingCommand() throws IOException
    {
        return NNTPReply.isPositiveCompletion(getReply());
    }



    public Writer forwardArticle(final String articleId) throws IOException
    {
        if (!NNTPReply.isPositiveIntermediate(ihave(articleId))) {
            return null;
        }

        return new DotTerminatedMessageWriter(_writer_);
    }

    /**
     * Return article headers for all articles between lowArticleNumber
     * and highArticleNumber, inclusively, using the XOVER command.
     * <p>
     * @param lowArticleNumber low
     * @param highArticleNumber high
     * @return an Iterable of Articles
     * @throws IOException if the command failed
     * @since 3.0
     */
    public Iterable<Article> iterateArticleInfo(final long lowArticleNumber, final long highArticleNumber)
        throws IOException
    {
        final BufferedReader info = retrieveArticleInfo(lowArticleNumber,highArticleNumber);
        if (info == null) {
            throw new IOException("XOVER command failed: "+getReplyString());
        }
        // N.B. info is already DotTerminated, so don't rewrap
        return new ArticleIterator(new ReplyIterator(info, false));
    }

    /**
     * List all new articles added to the NNTP server since a particular
     * date subject to the conditions of the specified query.  If no new
     * new news is found, no entries will be returned.
     * This uses the "NEWNEWS" command.
     * You must add at least one newsgroup to the query, else the command will fail.
     * Each String which is returned is a unique message identifier including the
     * enclosing &lt; and &gt;.
     * <p>
     * @param query  The query restricting how to search for new news.  You
     *    must add at least one newsgroup to the query.
     * @return An iterator of String instances containing the unique message
     *    identifiers for each new article added to the NNTP server.  If no
     *    new news is found, no strings will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @since 3.0
     */
    public Iterable<String> iterateNewNews(final NewGroupsOrNewsQuery query) throws IOException {
        if (NNTPReply.isPositiveCompletion(newnews(
                query.getNewsgroups(), query.getDate(), query.getTime(),
                query.isGMT(), query.getDistributions()))) {
            return new ReplyIterator(_reader_);
        }
        throw new IOException("NEWNEWS command failed: "+getReplyString());
    }


    /**
     * List all new newsgroups added to the NNTP server since a particular
     * date subject to the conditions of the specified query.  If no new
     * newsgroups were added, no entries will be returned.
     * This uses the "NEWGROUPS" command.
     * <p>
     * @param query  The query restricting how to search for new newsgroups.
     * @return An iterable of Strings containing the raw information
     *    for each new newsgroup added to the NNTP server.   If no newsgroups
     *    were added, no entries will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @since 3.0
     */
    public Iterable<String> iterateNewNewsgroupListing(final NewGroupsOrNewsQuery query) throws IOException {
        if (NNTPReply.isPositiveCompletion(newgroups(
                query.getDate(), query.getTime(),
                query.isGMT(), query.getDistributions()))) {
            return new ReplyIterator(_reader_);
        }
        throw new IOException("NEWGROUPS command failed: "+getReplyString());
    }

    /**
     * List all new newsgroups added to the NNTP server since a particular
     * date subject to the conditions of the specified query.  If no new
     * newsgroups were added, no entries will be returned.
     * This uses the "NEWGROUPS" command.
     * <p>
     * @param query  The query restricting how to search for new newsgroups.
     * @return An iterable of NewsgroupInfo instances containing the information
     *    for each new newsgroup added to the NNTP server.   If no newsgroups
     *    were added, no entries will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @since 3.0
     */
    public Iterable<NewsgroupInfo> iterateNewNewsgroups(final NewGroupsOrNewsQuery query) throws IOException {
        return new NewsgroupIterator(iterateNewNewsgroupListing(query));
    }



    /**
     * List all newsgroups served by the NNTP server.  If no newsgroups
     * are served, no entries will be returned.
     * The method uses the "LIST" command.
     * <p>
     * @return An iterable of NewsgroupInfo instances containing the information
     *    for each newsgroup served by the NNTP server.   If no newsgroups
     *    are served, no entries will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @since 3.0
     */
    public Iterable<String> iterateNewsgroupListing() throws IOException {
        if (NNTPReply.isPositiveCompletion(list())) {
            return new ReplyIterator(_reader_);
        }
        throw new IOException("LIST command failed: "+getReplyString());
    }

    /**
     * List the newsgroups that match a given pattern.
     * Uses the "LIST ACTIVE" command.
     * <p>
     * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
     * @return An iterable of Strings containing the raw information
     *    for each newsgroup served by the NNTP server corresponding to the
     *    supplied pattern.   If no such newsgroups are served, no entries
     *    will be returned.
     * @throws IOException on error
     * @since 3.0
     */
    public Iterable<String> iterateNewsgroupListing(final String wildmat) throws IOException {
        if(NNTPReply.isPositiveCompletion(listActive(wildmat))) {
            return new ReplyIterator(_reader_);
        }
        throw new IOException("LIST ACTIVE "+wildmat+" command failed: "+getReplyString());
    }

    /**
     * List all newsgroups served by the NNTP server.  If no newsgroups
     * are served, no entries will be returned.
     * The method uses the "LIST" command.
     * <p>
     * @return An iterable of Strings containing the raw information
     *    for each newsgroup served by the NNTP server.   If no newsgroups
     *    are served, no entries will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @since 3.0
     */
    public Iterable<NewsgroupInfo> iterateNewsgroups() throws IOException {
        return new NewsgroupIterator(iterateNewsgroupListing());
    }


    /**
     * List the newsgroups that match a given pattern.
     * Uses the "LIST ACTIVE" command.
     * <p>
     * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
     * @return An iterable NewsgroupInfo instances containing the information
     *    for each newsgroup served by the NNTP server corresponding to the
     *    supplied pattern.   If no such newsgroups are served, no entries
     *    will be returned.
     * @throws IOException on error
     * @since 3.0
     */
    public Iterable<NewsgroupInfo> iterateNewsgroups(final String wildmat) throws IOException {
        return new NewsgroupIterator(iterateNewsgroupListing(wildmat));
    }


    /**
     * List the command help from the server.
     * <p>
     * @return The sever help information.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public String listHelp() throws IOException
    {
        if (!NNTPReply.isInformational(help())) {
            return null;
        }

        try (final StringWriter help = new StringWriter();
                final BufferedReader reader = new DotTerminatedMessageReader(_reader_)) {
            Util.copyReader(reader, help);
            return help.toString();
        }
    }



    /**
     * List all new articles added to the NNTP server since a particular
     * date subject to the conditions of the specified query.  If no new
     * new news is found, a zero length array will be returned.  If the
     * command fails, null will be returned.  You must add at least one
     * newsgroup to the query, else the command will fail.  Each String
     * in the returned array is a unique message identifier including the
     * enclosing &lt; and &gt;.
     * This uses the "NEWNEWS" command.
     * <p>
     * @param query  The query restricting how to search for new news.  You
     *    must add at least one newsgroup to the query.
     * @return An array of String instances containing the unique message
     *    identifiers for each new article added to the NNTP server.  If no
     *    new news is found, a zero length array will be returned.  If the
     *    command fails, null will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     *
     * @see #iterateNewNews(NewGroupsOrNewsQuery)
     */
    public String[] listNewNews(final NewGroupsOrNewsQuery query)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(newnews(query.getNewsgroups(), query.getDate(), query.getTime(),
                query.isGMT(), query.getDistributions()))) {
            return null;
        }

        final Vector<String> list = new Vector<>();
        try (final BufferedReader reader = new DotTerminatedMessageReader(_reader_)) {

            String line;
            while ((line = reader.readLine()) != null) {
                list.addElement(line);
            }
        }

        final int size = list.size();
        if (size < 1) {
            return NetConstants.EMPTY_STRING_ARRAY;
        }

        final String[] result = new String[size];
        list.copyInto(result);

        return result;
    }

    /**
     * List all new newsgroups added to the NNTP server since a particular
     * date subject to the conditions of the specified query.  If no new
     * newsgroups were added, a zero length array will be returned.  If the
     * command fails, null will be returned.
     * This uses the "NEWGROUPS" command.
     * <p>
     * @param query  The query restricting how to search for new newsgroups.
     * @return An array of NewsgroupInfo instances containing the information
     *    for each new newsgroup added to the NNTP server.   If no newsgroups
     *    were added, a zero length array will be returned.  If the command
     *    fails, null will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @see #iterateNewNewsgroups(NewGroupsOrNewsQuery)
     * @see #iterateNewNewsgroupListing(NewGroupsOrNewsQuery)
     */
    public NewsgroupInfo[] listNewNewsgroups(final NewGroupsOrNewsQuery query)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(newgroups(
                                                query.getDate(), query.getTime(),
                                                query.isGMT(), query.getDistributions())))
        {
            return null;
        }

        return readNewsgroupListing();
    }

    /**
     * List all newsgroups served by the NNTP server.  If no newsgroups
     * are served, a zero length array will be returned.  If the command
     * fails, null will be returned.
     * The method uses the "LIST" command.
     * <p>
     * @return An array of NewsgroupInfo instances containing the information
     *    for each newsgroup served by the NNTP server.   If no newsgroups
     *    are served, a zero length array will be returned.  If the command
     *    fails, null will be returned.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     * @see #iterateNewsgroupListing()
     * @see #iterateNewsgroups()
     */
    public NewsgroupInfo[] listNewsgroups() throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(list())) {
            return null;
        }

        return readNewsgroupListing();
    }


    /**
     * List the newsgroups that match a given pattern.
     * Uses the "LIST ACTIVE" command.
     * <p>
     * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
     * @return An array of NewsgroupInfo instances containing the information
     *    for each newsgroup served by the NNTP server corresponding to the
     *    supplied pattern.   If no such newsgroups are served, a zero length
     *    array will be returned.  If the command fails, null will be returned.
     * @throws IOException on error
     * @see #iterateNewsgroupListing(String)
     * @see #iterateNewsgroups(String)
     */
    public NewsgroupInfo[] listNewsgroups(final String wildmat) throws IOException
    {
        if(!NNTPReply.isPositiveCompletion(listActive(wildmat))) {
            return null;
        }
        return readNewsgroupListing();
    }


    /**
     * Send a "LIST OVERVIEW.FMT" command to the server.
     *
     * @return the contents of the Overview format, of {@code null} if the command failed
     * @throws IOException on error
     */
    public String[] listOverviewFmt() throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(sendCommand("LIST", "OVERVIEW.FMT"))) {
            return null;
        }

        try (final BufferedReader reader = new DotTerminatedMessageReader(_reader_)) {
            String line;
            final ArrayList<String> list = new ArrayList<>();
            while ((line = reader.readLine()) != null) {
                list.add(line);
            }
            return list.toArray(NetConstants.EMPTY_STRING_ARRAY);
        }
    }


    /**
     * Logs out of the news server gracefully by sending the QUIT command.
     * However, you must still disconnect from the server before you can open
     * a new connection.
     * <p>
     * @return True if successfully completed, false if not.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean logout() throws IOException
    {
        return NNTPReply.isPositiveCompletion(quit());
    }

    /**
     * Parse the reply and store the id and number in the pointer.
     *
     * @param reply the reply to parse "22n nnn <aaa>"
     * @param pointer the pointer to update
     *
     * @throws MalformedServerReplyException if response could not be parsed
     */
    private void parseArticlePointer(final String reply, final ArticleInfo pointer)
    throws MalformedServerReplyException
    {
        final String tokens[] = reply.split(" ");
        if (tokens.length >= 3) { // OK, we can parset the line
            int i = 1; // skip reply code
            try
            {
                // Get article number
                pointer.articleNumber = Long.parseLong(tokens[i++]);
                // Get article id
                pointer.articleId = tokens[i++];
                return; // done
            }
            catch (final NumberFormatException e)
            {
                // drop through and raise exception
            }
        }
        throw new MalformedServerReplyException(
            "Could not parse article pointer.\nServer reply: " + reply);
    }

    /**
     * Post an article to the NNTP server.  This method returns a
     * DotTerminatedMessageWriter instance to which the article can be
     * written.  Null is returned if the posting attempt fails.  You
     * should check {@link NNTP#isAllowedToPost isAllowedToPost() }
     *  before trying to post.  However, a posting
     * attempt can fail due to malformed headers.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * (other methods) until you finish writing to the returned Writer
     * instance and close it.  The NNTP protocol uses the same stream for
     * issuing commands as it does for returning results.  Therefore the
     * returned Writer actually writes directly to the NNTP connection.
     * After you close the writer, you can execute new commands.  If you
     * do not follow these requirements your program will not work properly.
     * <p>
     * Different NNTP servers will require different header formats, but
     * you can use the provided
     * {@link org.apache.commons.net.nntp.SimpleNNTPHeader}
     * class to construct the bare minimum acceptable header for most
     * news readers.  To construct more complicated headers you should
     * refer to RFC 822.  When the Java Mail API is finalized, you will be
     * able to use it to compose fully compliant Internet text messages.
     * The DotTerminatedMessageWriter takes care of doubling line-leading
     * dots and ending the message with a single dot upon closing, so all
     * you have to worry about is writing the header and the message.
     * <p>
     * Upon closing the returned Writer, you need to call
     * {@link #completePendingCommand  completePendingCommand() }
     * to finalize the posting and verify its success or failure from
     * the server reply.
     * <p>
     * @return A DotTerminatedMessageWriter to which the article (including
     *      header) can be written.  Returns null if the command fails.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */

    public Writer postArticle() throws IOException
    {
        if (!NNTPReply.isPositiveIntermediate(post())) {
            return null;
        }

        return new DotTerminatedMessageWriter(_writer_);
    }

    private NewsgroupInfo[] readNewsgroupListing() throws IOException
    {

        // Start of with a big vector because we may be reading a very large
        // amount of groups.
        final Vector<NewsgroupInfo> list = new Vector<>(2048);

        String line;
        try (final BufferedReader reader = new DotTerminatedMessageReader(_reader_)) {
            while ((line = reader.readLine()) != null) {
                final NewsgroupInfo tmp = parseNewsgroupListEntry(line);
                if (tmp != null) {
                    list.addElement(tmp);
                } else {
                    throw new MalformedServerReplyException(line);
                }
            }
        }
        final int size;
        if ((size = list.size()) < 1) {
            return EMPTY_NEWSGROUP_INFO_ARRAY;
        }

        final NewsgroupInfo[] info = new NewsgroupInfo[size];
        list.copyInto(info);

        return info;
    }

    private BufferedReader retrieve(final int command, final long articleNumber, final ArticleInfo pointer)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(sendCommand(command,
                                            Long.toString(articleNumber)))) {
            return null;
        }

        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return new DotTerminatedMessageReader(_reader_);
    }

    private BufferedReader retrieve(final int command, final String articleId, final ArticleInfo pointer)
    throws IOException
    {
        if (articleId != null)
        {
            if (!NNTPReply.isPositiveCompletion(sendCommand(command, articleId))) {
                return null;
            }
        } else if (!NNTPReply.isPositiveCompletion(sendCommand(command))) {
            return null;
        }


        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return new DotTerminatedMessageReader(_reader_);
    }

    /**
     * Same as <code> retrieveArticle((String) null) </code>
     * Note: the return can be cast to a {@link BufferedReader}
     * @return A DotTerminatedMessageReader instance from which the article can be read.
     * null if the article does not exist.
     * @throws IOException if an IO error occurs
     */
    public Reader retrieveArticle() throws IOException
    {
        return retrieveArticle((String) null);
    }


    /**
     * @param articleNumber The number of the the article to retrieve
     * @return A DotTerminatedMessageReader instance from which the article
     *         can be read.  null if the article does not exist.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveArticle(long)} instead
     */
    @Deprecated
    public Reader retrieveArticle(final int articleNumber) throws IOException {
        return retrieveArticle((long) articleNumber);
    }


    /**
     * @param articleNumber  The number of the the article to retrieve.
     * @param pointer A parameter through which to return the article's number and unique id
     * @return A DotTerminatedMessageReader instance from which the article
     *         can be read.  null if the article does not exist.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveArticle(long, ArticleInfo)} instead
     */
    @Deprecated
    public Reader retrieveArticle(final int articleNumber, final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final Reader rdr = retrieveArticle(articleNumber, ai);
        ai2ap(ai, pointer);
        return rdr;
    }


    /**
     * Same as <code> retrieveArticle(articleNumber, null) </code>
     * @param articleNumber the article number to fetch
     * @return A DotTerminatedMessageReader instance from which the article
     *         can be read.  null if the article does not exist.
     * @throws IOException if an IO error occurs
     */
    public BufferedReader retrieveArticle(final long articleNumber) throws IOException
    {
        return retrieveArticle(articleNumber, null);
    }

    /**
     * Retrieves an article from the currently selected newsgroup.  The
     * article is referenced by its article number.
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleNumber  The number of the the article to
     *     retrieve.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticle(final long articleNumber, final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.ARTICLE, articleNumber, pointer);
    }


    /**
     * Same as <code> retrieveArticle(articleId, (ArticleInfo) null) </code>
     * Note: the return can be cast to a {@link BufferedReader}
     * @param articleId the article id to retrieve
     * @return A DotTerminatedMessageReader instance from which the article can be read.
     * null if the article does not exist.
     * @throws IOException if an IO error occurs
     */
    public Reader retrieveArticle(final String articleId) throws IOException
    {
        return retrieveArticle(articleId, (ArticleInfo) null);
    }


    /**
     * Retrieves an article from the NNTP server.  The article is referenced
     * by its unique article identifier (including the enclosing &lt; and &gt;).
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleId  The unique article identifier of the article to
     *     retrieve.  If this parameter is null, the currently selected
     *     article is retrieved.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticle(final String articleId, final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.ARTICLE, articleId, pointer);

    }


    /**
     * @param articleId The unique article identifier of the article to retrieve
     * @param pointer A parameter through which to return the article's number and unique id
     * @deprecated 3.0 use {@link #retrieveArticle(String, ArticleInfo)} instead
     * @return A DotTerminatedMessageReader instance from which the article can be read.
     * null if the article does not exist.
     * @throws IOException on error
     */
    @Deprecated
    public Reader retrieveArticle(final String articleId, final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final Reader rdr = retrieveArticle(articleId, ai);
        ai2ap(ai, pointer);
        return rdr;
    }

    /**
     * Same as <code> retrieveArticleBody(null) </code>
     *  Note: the return can be cast to a {@link BufferedReader}
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws IOException if an error occurs
     */
    public Reader retrieveArticleBody() throws IOException
    {
        return retrieveArticleBody(null);
    }

    /**
     * @param a  tba
     * @return  tba
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #retrieveArticleBody(long)} instead
     */
    @Deprecated
    public Reader retrieveArticleBody(final int a) throws IOException {
        return retrieveArticleBody((long) a);
    }

    /**
     * @param a  tba
     * @param ap  tba
     * @return  tba
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #retrieveArticleBody(long, ArticleInfo)} instead
     */
    @Deprecated
    public Reader retrieveArticleBody(final int a, final ArticlePointer ap) throws IOException {
        final ArticleInfo ai =  ap2ai(ap);
        final Reader rdr = retrieveArticleBody(a, ai);
        ai2ap(ai, ap);
        return rdr;
    }


    /**
     * Same as <code> retrieveArticleBody(articleNumber, null) </code>
     * @param articleNumber the article number
     * @return the reader
     * @throws IOException if an error occurs
     */
    public BufferedReader retrieveArticleBody(final long articleNumber) throws IOException
    {
        return retrieveArticleBody(articleNumber, null);
    }

    /**
     * Retrieves an article body from the currently selected newsgroup.  The
     * article is referenced by its article number.
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleNumber  The number of the the article whose body is
     *     being retrieved.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticleBody(final long articleNumber,
                                      final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.BODY, articleNumber, pointer);
    }

    /**
     * Same as <code> retrieveArticleBody(articleId, (ArticleInfo) null) </code>
     *  Note: the return can be cast to a {@link BufferedReader}
     * @param articleId the article id
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws IOException if an error occurs
     */
    public Reader retrieveArticleBody(final String articleId) throws IOException
    {
        return retrieveArticleBody(articleId, (ArticleInfo) null);
    }

    /**
     * Retrieves an article body from the NNTP server.  The article is
     * referenced
     * by its unique article identifier (including the enclosing &lt; and &gt;).
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleId  The unique article identifier of the article whose
     *    body is being retrieved.  If this parameter is null, the
     *    body of the currently selected article is retrieved.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticleBody(final String articleId, final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.BODY, articleId, pointer);

    }

    /**
     * @param articleId The unique article identifier of the article to retrieve
     * @param pointer A parameter through which to return the article's number and unique id
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveArticleBody(String, ArticleInfo)} instead
     */
    @Deprecated
    public Reader retrieveArticleBody(final String articleId, final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final Reader rdr = retrieveArticleBody(articleId, ai);
        ai2ap(ai, pointer);
        return rdr;
    }

    /**
     * Same as <code> retrieveArticleHeader((String) null) </code>
     *  Note: the return can be cast to a {@link BufferedReader}
     * @return the reader
     * @throws IOException if an error occurs
     */
    public Reader retrieveArticleHeader() throws IOException
    {
        return retrieveArticleHeader((String) null);
    }

    /**
     * @param a  tba
     * @return  tba
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #retrieveArticleHeader(long)} instead
     */
    @Deprecated
    public Reader retrieveArticleHeader(final int a) throws IOException {
        return retrieveArticleHeader((long) a);
    }

    /**
     * @param a  tba
     * @param ap  tba
     * @return  tba
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #retrieveArticleHeader(long, ArticleInfo)} instead
     */
    @Deprecated
    public Reader retrieveArticleHeader(final int a, final ArticlePointer ap) throws IOException {
        final ArticleInfo ai =  ap2ai(ap);
        final Reader rdr = retrieveArticleHeader(a, ai);
        ai2ap(ai, ap);
        return rdr;
    }

    /**
     * Same as <code> retrieveArticleHeader(articleNumber, null) </code>
     *
     * @param articleNumber the article number
     * @return the reader
     * @throws IOException if an error occurs
     */
    public BufferedReader retrieveArticleHeader(final long articleNumber) throws IOException
    {
        return retrieveArticleHeader(articleNumber, null);
    }


    /**
     * Retrieves an article header from the currently selected newsgroup.  The
     * article is referenced by its article number.
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleNumber  The number of the the article whose header is
     *     being retrieved.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         header can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticleHeader(final long articleNumber,
                                        final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.HEAD, articleNumber, pointer);
    }


    /**
     * Same as <code> retrieveArticleHeader(articleId, (ArticleInfo) null) </code>
     *  Note: the return can be cast to a {@link BufferedReader}
     * @param articleId the article id  to fetch
     * @return the reader
     * @throws IOException if an error occurs
     */
    public Reader retrieveArticleHeader(final String articleId) throws IOException
    {
        return retrieveArticleHeader(articleId, (ArticleInfo) null);
    }


    /**
     * Retrieves an article header from the NNTP server.  The article is
     * referenced
     * by its unique article identifier (including the enclosing &lt; and &gt;).
     * The article number and identifier contained in the server reply
     * are returned through an ArticleInfo.  The <code> articleId </code>
     * field of the ArticleInfo cannot always be trusted because some
     * NNTP servers do not correctly follow the RFC 977 reply format.
     * <p>
     * A DotTerminatedMessageReader is returned from which the article can
     * be read.  If the article does not exist, null is returned.
     * <p>
     * You must not issue any commands to the NNTP server (i.e., call any
     * other methods) until you finish reading the message from the returned
     * BufferedReader instance.
     * The NNTP protocol uses the same stream for issuing commands as it does
     * for returning results.  Therefore the returned BufferedReader actually reads
     * directly from the NNTP connection.  After the end of message has been
     * reached, new commands can be executed and their replies read.  If
     * you do not follow these requirements, your program will not work
     * properly.
     * <p>
     * @param articleId  The unique article identifier of the article whose
     *    header is being retrieved.  If this parameter is null, the
     *    header of the currently selected article is retrieved.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return A DotTerminatedMessageReader instance from which the article
     *         header can be read.  null if the article does not exist.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public BufferedReader retrieveArticleHeader(final String articleId, final ArticleInfo pointer)
    throws IOException
    {
        return retrieve(NNTPCommand.HEAD, articleId, pointer);

    }

    /**
     * @param articleId The unique article identifier of the article to retrieve
     * @param pointer A parameter through which to return the article's number and unique id
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveArticleHeader(String, ArticleInfo)} instead
     */
    @Deprecated
    public Reader retrieveArticleHeader(final String articleId, final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final Reader rdr = retrieveArticleHeader(articleId, ai);
        ai2ap(ai, pointer);
        return rdr;
    }

    /**
     * @param lowArticleNumber to fetch
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #retrieveArticleInfo(long)} instead
     */
    @Deprecated
    public Reader retrieveArticleInfo(final int lowArticleNumber) throws IOException {
        return retrieveArticleInfo((long) lowArticleNumber);
    }

    /**
     * @param lowArticleNumber to fetch
     * @param highArticleNumber to fetch
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveArticleInfo(long, long)} instead
     */
    @Deprecated
    public Reader retrieveArticleInfo(final int lowArticleNumber, final int highArticleNumber) throws IOException {
        return retrieveArticleInfo((long) lowArticleNumber, (long) highArticleNumber);
    }

    /**
     * Return article headers for a specified post.
     * <p>
     * @param articleNumber the article to retrieve headers for
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     */
    public BufferedReader retrieveArticleInfo(final long articleNumber) throws IOException
    {
        return retrieveArticleInfo(Long.toString(articleNumber));
    }

    /**
     * Return article headers for all articles between lowArticleNumber
     * and highArticleNumber, inclusively. Uses the XOVER command.
     * <p>
     * @param lowArticleNumber low number
     * @param highArticleNumber high number
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     */
    public BufferedReader retrieveArticleInfo(final long lowArticleNumber,
            final long highArticleNumber)
        throws IOException
    {
        return
            retrieveArticleInfo(lowArticleNumber + "-" +
                                             highArticleNumber);
    }

    /**
     * Private implementation of XOVER functionality.
     *
     * See {@link NNTP#xover}
     * for legal agument formats. Alternatively, read RFC 2980 :-)
     * <p>
     * @param articleRange
     * @return Returns a DotTerminatedMessageReader if successful, null
     *         otherwise
     * @throws IOException
     */
    private BufferedReader retrieveArticleInfo(final String articleRange)
        throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(xover(articleRange))) {
            return null;
        }

        return new DotTerminatedMessageReader(_reader_);
    }

    /**
     * @param a tba
     * @param b  tba
     * @return  tba
     * @throws IOException tba
     * @deprecated 3.0 use {@link #retrieveHeader(String, long)} instead
     */
    @Deprecated
    public Reader retrieveHeader(final String a, final int b) throws IOException {
        return retrieveHeader(a, (long) b);
    }





    // DEPRECATED METHODS - for API compatibility only - DO NOT USE
    // ============================================================



    /**
     * @param header the header
     * @param lowArticleNumber to fetch
     * @param highArticleNumber to fetch
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     * @deprecated 3.0 use {@link #retrieveHeader(String, long, long)} instead
     */
    @Deprecated
    public Reader retrieveHeader(final String header, final int lowArticleNumber, final int highArticleNumber)
        throws IOException
    {
        return retrieveHeader(header, (long) lowArticleNumber, (long) highArticleNumber);
    }

    /**
     * Return an article header for a specified post.
     * <p>
     * @param header the header to retrieve
     * @param articleNumber the article to retrieve the header for
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     */
    public BufferedReader retrieveHeader(final String header, final long articleNumber)
        throws IOException
    {
        return retrieveHeader(header, Long.toString(articleNumber));
    }

    /**
     * Return an article header for all articles between lowArticleNumber
     * and highArticleNumber, inclusively.
     * <p>
     * @param header the header
     * @param lowArticleNumber to fetch
     * @param highArticleNumber to fetch
     * @return a DotTerminatedReader if successful, null otherwise
     * @throws IOException on error
     */
    public BufferedReader retrieveHeader(final String header, final long lowArticleNumber,
                                 final long highArticleNumber)
        throws IOException
    {
        return
            retrieveHeader(header,lowArticleNumber + "-" + highArticleNumber);
    }

    /**
     * Private implementation of XHDR functionality.
     *
     * See {@link NNTP#xhdr}
     * for legal agument formats. Alternatively, read RFC 1036.
     * <p>
     * @param header
     * @param articleRange
     * @return Returns a DotTerminatedMessageReader if successful, null
     *         otherwise
     * @throws IOException
     */
    private BufferedReader retrieveHeader(final String header, final String articleRange)
        throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange))) {
            return null;
        }

        return new DotTerminatedMessageReader(_reader_);
    }

    /***
     * Same as <code> selectArticle((String) null, articleId) </code>.  Useful
     * for retrieving the current article number.
     * @param pointer to the article
     * @return true if OK
     * @throws IOException on error
     */
    public boolean selectArticle(final ArticleInfo pointer) throws IOException
    {
        return selectArticle(null, pointer);
    }

    /**
     * @param pointer A parameter through which to return the article's number and unique id
     * @return True if successful, false if not.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #selectArticle(ArticleInfo)} instead
     */
    @Deprecated
    public boolean selectArticle(final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final boolean b = selectArticle(ai);
        ai2ap(ai, pointer);
        return b;

    }

    /**
     * @param a  tba
     * @return  tba
     * @throws IOException  tba
     * @deprecated 3.0 use {@link #selectArticle(long)} instead
     */
    @Deprecated
    public boolean selectArticle(final int a) throws IOException {
        return selectArticle((long) a);
    }

    /**
     * @param a  tba
     * @param ap  tba
     * @return  tba
     * @throws IOException tba
     * @deprecated 3.0 use {@link #selectArticle(long, ArticleInfo)} instead
     */
    @Deprecated
    public boolean selectArticle(final int a, final ArticlePointer ap) throws IOException {
        final ArticleInfo ai =  ap2ai(ap);
        final boolean b = selectArticle(a, ai);
        ai2ap(ai, ap);
        return b;
    }

    /** Same as <code> selectArticle(articleNumber, null) </code>
     * @param articleNumber the numger
     * @return true if successful
     * @throws IOException on error */
    public boolean selectArticle(final long articleNumber) throws IOException
    {
        return selectArticle(articleNumber, null);
    }

    /**
     * Select an article in the currently selected newsgroup by its number.
     * and return its article number and id through the
     * pointer parameter.  This is achieved through the STAT command.
     * According to RFC 977, this WILL set the current article pointer
     * on the server.  Use this command to select an article before retrieving
     * it, or to obtain an article's unique identifier given its number.
     * <p>
     * @param articleNumber The number of the article to select from the
     *       currently selected newsgroup.
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  Although the articleId field cannot always
     *   be trusted because of server deviations from RFC 977 reply formats,
     *   we haven't found a server that misformats this information in response
     *   to this particular command.  You may set this parameter to null if
     *   you do not desire to retrieve the returned article information.
     * @return True if successful, false if not.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean selectArticle(final long articleNumber, final ArticleInfo pointer)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(stat(articleNumber))) {
            return false;
        }

        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return true;
    }

    /**
     * Same as <code> selectArticle(articleId, (ArticleInfo) null) </code>
     * @param articleId the article Id
     * @return true if successful
     * @throws IOException on error
     */
    public boolean selectArticle(final String articleId) throws IOException
    {
        return selectArticle(articleId, (ArticleInfo) null);
    }

    /**
     * Select an article by its unique identifier (including enclosing
     * &lt; and &gt;) and return its article number and id through the
     * pointer parameter.  This is achieved through the STAT command.
     * According to RFC 977, this will NOT set the current article pointer
     * on the server.  To do that, you must reference the article by its
     * number.
     * <p>
     * @param articleId  The unique article identifier of the article that
     *    is being selectedd.  If this parameter is null, the
     *    body of the current article is selected
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return True if successful, false if not.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean selectArticle(final String articleId, final ArticleInfo pointer)
    throws IOException
    {
        if (articleId != null) {
            if (!NNTPReply.isPositiveCompletion(stat(articleId))) {
                return false;
            }
        } else if (!NNTPReply.isPositiveCompletion(stat())) {
            return false;
        }

        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return true;
    }

    /**
     * @param articleId The unique article identifier of the article to retrieve
     * @param pointer A parameter through which to return the article's number and unique id
     * @return A DotTerminatedMessageReader instance from which the article
     *         body can be read.  null if the article does not exist.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #selectArticle(String, ArticleInfo)} instead
     */
    @Deprecated
    public boolean selectArticle(final String articleId, final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final boolean b = selectArticle(articleId, ai);
        ai2ap(ai, pointer);
        return b;

    }

    /**
     * Same as <code> selectNewsgroup(newsgroup, null) </code>
     * @param newsgroup the newsgroup name
     * @return true if newsgroup exist and was selected
     * @throws IOException if an error occurs
     */
    public boolean selectNewsgroup(final String newsgroup) throws IOException
    {
        return selectNewsgroup(newsgroup, null);
    }

    /**
     * Select the specified newsgroup to be the target of for future article
     * retrieval and posting operations.  Also return the newsgroup
     * information contained in the server reply through the info parameter.
     * <p>
     * @param newsgroup  The newsgroup to select.
     * @param info  A parameter through which the newsgroup information of
     *      the selected newsgroup contained in the server reply is returned.
     *      Set this to null if you do not desire this information.
     * @return True if the newsgroup exists and was selected, false otherwise.
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean selectNewsgroup(final String newsgroup, final NewsgroupInfo info)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(group(newsgroup))) {
            return false;
        }

        if (info != null) {
            parseGroupReply(getReplyString(), info);
        }

        return true;
    }

    /** Same as <code> selectNextArticle((ArticleInfo) null) </code>
     * @return true if successful
     * @throws IOException on error */
    public boolean selectNextArticle() throws IOException
    {
        return selectNextArticle((ArticleInfo) null);
    }

    /**
     * Select the article following the currently selected article in the
     * currently selected newsgroup and return its number and unique id
     * through the pointer parameter.  Because of deviating server
     * implementations, the articleId information cannot be trusted.  To
     * obtain the article identifier, issue a
     * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
     * afterward.
     * <p>
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return True if successful, false if not (e.g., there is no following
     *         article).
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean selectNextArticle(final ArticleInfo pointer) throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(next())) {
            return false;
        }

        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return true;
    }

    /**
     * @param pointer A parameter through which to return the article's number and unique id
     * @return True if successful, false if not.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #selectNextArticle(ArticleInfo)} instead
     */
    @Deprecated
    public boolean selectNextArticle(final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final boolean b = selectNextArticle(ai);
        ai2ap(ai, pointer);
        return b;

    }

    /** Same as <code> selectPreviousArticle((ArticleInfo) null) </code>
     * @return true if successful
     * @throws IOException on error */
    public boolean selectPreviousArticle() throws IOException
    {
        return selectPreviousArticle((ArticleInfo) null);
    }

   // Helper methods

    /**
     * Select the article preceeding the currently selected article in the
     * currently selected newsgroup and return its number and unique id
     * through the pointer parameter.  Because of deviating server
     * implementations, the articleId information cannot be trusted.  To
     * obtain the article identifier, issue a
     * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
     * afterward.
     * <p>
     * @param pointer    A parameter through which to return the article's
     *   number and unique id.  The articleId field cannot always be trusted
     *   because of server deviations from RFC 977 reply formats.  You may
     *   set this parameter to null if you do not desire to retrieve the
     *   returned article information.
     * @return True if successful, false if not (e.g., there is no previous
     *     article).
     * @throws NNTPConnectionClosedException
     *      If the NNTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send NNTP reply code 400.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean selectPreviousArticle(final ArticleInfo pointer)
    throws IOException
    {
        if (!NNTPReply.isPositiveCompletion(last())) {
            return false;
        }

        if (pointer != null) {
            parseArticlePointer(getReplyString(), pointer);
        }

        return true;
    }

    /**
     * @param pointer A parameter through which to return the article's number and unique id
     * @return True if successful, false if not.
     * @throws IOException on error
     * @deprecated 3.0 use {@link #selectPreviousArticle(ArticleInfo)} instead
     */
    @Deprecated
    public boolean selectPreviousArticle(final ArticlePointer pointer) throws IOException {
        final ArticleInfo ai =  ap2ai(pointer);
        final boolean b = selectPreviousArticle(ai);
        ai2ap(ai, pointer);
        return b;
    }
}
