/**
 * 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.geronimo.javamail.store.imap.connection;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.mail.Flags;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MailDateFormat;
import javax.mail.internet.ParameterList;

import org.apache.geronimo.javamail.util.ResponseFormatException;

/**
 * @version $Rev: 953638 $ $Date: 2010-06-11 06:09:00 -0400 (Fri, 11 Jun 2010) $
 */
public class IMAPResponseTokenizer {
    /*
     * set up the decoding table.
     */
    protected static final byte[] decodingTable = new byte[256];

    protected static void initializeDecodingTable()
    {
        for (int i = 0; i < IMAPCommand.encodingTable.length; i++)
        {
            decodingTable[IMAPCommand.encodingTable[i]] = (byte)i;
        }
    }


    static {
        initializeDecodingTable();
    }

    // a singleton formatter for header dates.
    protected static MailDateFormat dateParser = new MailDateFormat();


    public static class Token {
        // Constant values from J2SE 1.4 API Docs (Constant values)
        public static final int ATOM = -1;
        public static final int QUOTEDSTRING = -2;
        public static final int LITERAL = -3;
        public static final int NUMERIC = -4;
        public static final int EOF = -5;
        public static final int NIL = -6;
        // special single character markers
        public static final int CONTINUATION = '+';
        public static final int UNTAGGED = '*';

        /**
         * The type indicator.  This will be either a specific type, represented by
         * a negative number, or the actual character value.
         */
        private int type;
        /**
         * The String value associated with this token.  All tokens have a String value,
         * except for the EOF and NIL tokens.
         */
        private String value;

        public Token(int type, String value) {
            this.type = type;
            this.value = value;
        }

        public int getType() {
            return type;
        }

        public String getValue() {
            return value;
        }

        public boolean isType(int type) {
            return this.type == type;
        }

        /**
         * Return the token as an integer value.  If this can't convert, an exception is
         * thrown.
         *
         * @return The integer value of the token.
         * @exception ResponseFormatException
         */
        public int getInteger() throws MessagingException {
            if (value != null) {
                try {
                    return Integer.parseInt(value);
                } catch (NumberFormatException e) {
                }
            }

            throw new ResponseFormatException("Number value expected in response; fount: " + value);
        }

        /**
         * Return the token as a long value.  If it can't convert, an exception is
         * thrown.
         *
         * @return The token as a long value.
         * @exception ResponseFormatException
         */
        public long getLong() throws MessagingException {
            if (value != null) {
                try {
                    return Long.parseLong(value);
                } catch (NumberFormatException e) {
                }
            }
            throw new ResponseFormatException("Number value expected in response; fount: " + value);
        }

        /**
         * Handy debugging toString() method for token.
         *
         * @return The string value of the token.
         */
        public String toString() {
            if (type == NIL) {
                return "NIL";
            }
            else if (type == EOF) {
                return "EOF";
            }

            if (value == null) {
                return "";
            }
            return value;
        }
    }

    public static final Token EOF = new Token(Token.EOF, null);
    public static final Token NIL = new Token(Token.NIL, null);

    private static final String WHITE = " \t\n\r";
    // The list of delimiter characters we process when
    // handling parsing of ATOMs.
    private static final String atomDelimiters = "(){}%*\"\\" + WHITE;
    // this set of tokens is a slighly expanded set used for
    // specific response parsing.  When dealing with Body
    // section names, there are sub pieces to the name delimited
    // by "[", "]", ".", "<", ">" and SPACE, so reading these using
    // a superset of the ATOM processing makes for easier parsing.
    private static final String tokenDelimiters = "<>[].(){}%*\"\\" + WHITE;

    // the response data read from the connection
    private byte[] response;
    // current parsing position
    private int pos;

    public IMAPResponseTokenizer(byte [] response) {
        this.response = response;
    }

    /**
     * Get the remainder of the response as a string.
     *
     * @return A string representing the remainder of the response.
     */
    public String getRemainder() {
        // make sure we're still in range
        if (pos >= response.length) {
            return "";
        }

        try {
            return new String(response, pos, response.length - pos, "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            return null; 
        }
    }


    public Token next() throws MessagingException {
        return next(false);
    }

    public Token next(boolean nilAllowed) throws MessagingException {
        return readToken(nilAllowed, false);
    }

    public Token next(boolean nilAllowed, boolean expandedDelimiters) throws MessagingException {
        return readToken(nilAllowed, expandedDelimiters);
    }

    public Token peek() throws MessagingException {
        return peek(false, false);
    }

    public Token peek(boolean nilAllowed) throws MessagingException {
        return peek(nilAllowed, false);
    }

    public Token peek(boolean nilAllowed, boolean expandedDelimiters) throws MessagingException {
        int start = pos;
        try {
            return readToken(nilAllowed, expandedDelimiters);
        } finally {
            pos = start;
        }
    }

    /**
     * Read an ATOM token from the parsed response.
     *
     * @return A token containing the value of the atom token.
     */
    private Token readAtomicToken(String delimiters) {
        // skip to next delimiter
        int start = pos;
        while (++pos < response.length) {
            // break on the first non-atom character.
            byte ch = response[pos];
            if (delimiters.indexOf(response[pos]) != -1 || ch < 32 || ch >= 127) {
                break;
            }
        }

        try {
            // Numeric tokens we store as a different type.
            String value = new String(response, start, pos - start, "ISO8859-1");
            try {
                int intValue = Integer.parseInt(value);
                return new Token(Token.NUMERIC, value);
            } catch (NumberFormatException e) {
            }
            return new Token(Token.ATOM, value);
        } catch (UnsupportedEncodingException e) {
            return null; 
        }
    }

    /**
     * Read the next token from the response.
     *
     * @return The next token from the response.  White space is skipped, and comment
     *         tokens are also skipped if indicated.
     * @exception ResponseFormatException
     */
    private Token readToken(boolean nilAllowed, boolean expandedDelimiters) throws MessagingException {
        String delimiters = expandedDelimiters ? tokenDelimiters : atomDelimiters;

        if (pos >= response.length) {
            return EOF;
        } else {
            byte ch = response[pos];
            if (ch == '\"') {
                return readQuotedString();
            // beginning of a length-specified literal?
            } else if (ch == '{') {
                return readLiteral();
            // white space, eat this and find a real token.
            } else if (WHITE.indexOf(ch) != -1) {
                eatWhiteSpace();
                return readToken(nilAllowed, expandedDelimiters);
            // either a CTL or special.  These characters have a self-defining token type.
            } else if (ch < 32 || ch >= 127 || delimiters.indexOf(ch) != -1) {
                pos++;
                return new Token((int)ch, String.valueOf((char)ch));
            } else {
                // start of an atom, parse it off.
                Token token = readAtomicToken(delimiters);
                // now, if we've been asked to look at NIL tokens, check to see if it is one,
                // and return that instead of the ATOM.
                if (nilAllowed) {
                    if (token.getValue().equalsIgnoreCase("NIL")) {
                        return NIL;
                    }
                }
                return token;
            }
        }
    }

    /**
     * Read the next token from the response, returning it as a byte array value.
     *
     * @return The next token from the response.  White space is skipped, and comment
     *         tokens are also skipped if indicated.
     * @exception ResponseFormatException
     */
    private byte[] readData(boolean nilAllowed) throws MessagingException {
        if (pos >= response.length) {
            return null;
        } else {
            byte ch = response[pos];
            if (ch == '\"') {
                return readQuotedStringData();
            // beginning of a length-specified literal?
            } else if (ch == '{') {
                return readLiteralData();
            // white space, eat this and find a real token.
            } else if (WHITE.indexOf(ch) != -1) {
                eatWhiteSpace();
                return readData(nilAllowed);
            // either a CTL or special.  These characters have a self-defining token type.
            } else if (ch < 32 || ch >= 127 || atomDelimiters.indexOf(ch) != -1) {
                throw new ResponseFormatException("Invalid string value: " + ch);
            } else {
                // only process this if we're allowing NIL as an option.
                if (nilAllowed) {
                    // start of an atom, parse it off.
                    Token token = next(true);
                    if (token.isType(Token.NIL)) {
                        return null;
                    }
                    // invalid token type.
                    throw new ResponseFormatException("Invalid string value: " + token.getValue());
                }
                // invalid token type.
                throw new ResponseFormatException("Invalid string value: " + ch);
            }
        }
    }

    /**
     * Extract a substring from the response string and apply any
     * escaping/folding rules to the string.
     *
     * @param start  The starting offset in the response.
     * @param end    The response end offset + 1.
     *
     * @return The processed string value.
     * @exception ResponseFormatException
     */
    private byte[] getEscapedValue(int start, int end) throws MessagingException {
        ByteArrayOutputStream value = new ByteArrayOutputStream();

        for (int i = start; i < end; i++) {
            byte ch = response[i];
            // is this an escape character?
            if (ch == '\\') {
                i++;
                if (i == end) {
                    throw new ResponseFormatException("Invalid escape character");
                }
                value.write(response[i]);
            }
            // line breaks are ignored, except for naked '\n' characters, which are consider
            // parts of linear whitespace.
            else if (ch == '\r') {
                // see if this is a CRLF sequence, and skip the second if it is.
                if (i < end - 1 && response[i + 1] == '\n') {
                    i++;
                }
            }
            else {
                // just append the ch value.
                value.write(ch);
            }
        }
        return value.toByteArray();
    }

    /**
     * Parse out a quoted string from the response, applying escaping
     * rules to the value.
     *
     * @return The QUOTEDSTRING token with the value.
     * @exception ResponseFormatException
     */
    private Token readQuotedString() throws MessagingException {
        try {
            String value = new String(readQuotedStringData(), "ISO8859-1");
            return new Token(Token.QUOTEDSTRING, value);
        } catch (UnsupportedEncodingException e) {
            return null; 
        }
    }

    /**
     * Parse out a quoted string from the response, applying escaping
     * rules to the value.
     *
     * @return The byte array with the resulting string bytes.
     * @exception ResponseFormatException
     */
    private byte[] readQuotedStringData() throws MessagingException {
        int start = pos + 1;
        boolean requiresEscaping = false;

        // skip to end of comment/string
        while (++pos < response.length) {
            byte ch = response[pos];
            if (ch == '"') {
                byte[] value;
                if (requiresEscaping) {
                    value = getEscapedValue(start, pos);
                }
                else {
                    value = subarray(start, pos);
                }
                // step over the delimiter for all cases.
                pos++;
                return value;
            }
            else if (ch == '\\') {
                pos++;
                requiresEscaping = true;
            }
            // we need to process line breaks also
            else if (ch == '\r') {
                requiresEscaping = true;
            }
        }

        throw new ResponseFormatException("Missing '\"'");
    }


    /**
     * Parse out a literal string from the response, using the length
     * encoded before the listeral.
     *
     * @return The LITERAL token with the value.
     * @exception ResponseFormatException
     */
    protected Token readLiteral() throws MessagingException {
        try {
            String value = new String(readLiteralData(), "ISO8859-1");
            return new Token(Token.LITERAL, value);
        } catch (UnsupportedEncodingException e) {
            return null; 
        }
    }


    /**
     * Parse out a literal string from the response, using the length
     * encoded before the listeral.
     *
     * @return The byte[] array with the value.
     * @exception ResponseFormatException
     */
    protected byte[] readLiteralData() throws MessagingException {
        int lengthStart = pos + 1;

        // see if we have a close marker.
        int lengthEnd = indexOf("}\r\n", lengthStart);
        if (lengthEnd == -1) {
            throw new ResponseFormatException("Missing terminator on literal length");
        }

        int count = 0;
        try {
            count = Integer.parseInt(substring(lengthStart, lengthEnd));
        } catch (NumberFormatException e) {
            throw new ResponseFormatException("Invalid literal length " + substring(lengthStart, lengthEnd));
        }

        // step over the length
        pos = lengthEnd + 3;

        // too long?
        if (pos + count > response.length) {
            throw new ResponseFormatException("Invalid literal length: " + count);
        }

        byte[] value = subarray(pos, pos + count);
        pos += count;

        return value;
    }


    /**
     * Extract a substring from the response buffer.
     *
     * @param start  The starting offset.
     * @param end    The end offset (+ 1).
     *
     * @return A String extracted from the buffer.
     */
    protected String substring(int start, int end ) {
        try {
            return new String(response, start, end - start, "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            return null; 
        }
    }


    /**
     * Extract a subarray from the response buffer.
     *
     * @param start  The starting offset.
     * @param end    The end offset (+ 1).
     *
     * @return A byte array string extracted rom the buffer.
     */
    protected byte[] subarray(int start, int end ) {
        byte[] result = new byte[end - start];
        System.arraycopy(response, start, result, 0, end - start);
        return result;
    }


    /**
     * Test if the bytes in the response buffer match a given
     * string value.
     *
     * @param position The compare position.
     * @param needle   The needle string we're testing for.
     *
     * @return True if the bytes match the needle value, false for any
     *         mismatch.
     */
    public boolean match(int position, String needle) {
        int length = needle.length();

        if (response.length - position < length) {
            return false;
        }

        for (int i = 0; i < length; i++) {
            if (response[position + i ] != needle.charAt(i)) {
                return false;
            }
        }
        return true;
    }


    /**
     * Search for a given string starting from the current position
     * cursor.
     *
     * @param needle The search string.
     *
     * @return The index of a match (in absolute byte position in the
     *         response buffer).
     */
    public int indexOf(String needle) {
        return indexOf(needle, pos);
    }

    /**
     * Search for a string in the response buffer starting from the
     * indicated position.
     *
     * @param needle   The search string.
     * @param position The starting buffer position.
     *
     * @return The index of the match position.  Returns -1 for no match.
     */
    public int indexOf(String needle, int position) {
        // get the last possible match position
        int last = response.length - needle.length();
        // no match possible
        if (last < position) {
            return -1;
        }

        for (int i = position; i <= last; i++) {
            if (match(i, needle)) {
                return i;
            }
        }
        return -1;
    }



    /**
     * Skip white space in the token string.
     */
    private void eatWhiteSpace() {
        // skip to end of whitespace
        while (++pos < response.length
                && WHITE.indexOf(response[pos]) != -1)
            ;
    }


    /**
     * Ensure that the next token in the parsed response is a
     * '(' character.
     *
     * @exception ResponseFormatException
     */
    public void checkLeftParen() throws MessagingException {
        Token token = next();
        if (token.getType() != '(') {
            throw new ResponseFormatException("Missing '(' in response");
        }
    }


    /**
     * Ensure that the next token in the parsed response is a
     * ')' character.
     *
     * @exception ResponseFormatException
     */
    public void checkRightParen() throws MessagingException {
        Token token = next();
        if (token.getType() != ')') {
            throw new ResponseFormatException("Missing ')' in response");
        }
    }


    /**
     * Read a string-valued token from the response.  A string
     * valued token can be either a quoted string, a literal value,
     * or an atom.  Any other token type is an error.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    public String readString() throws MessagingException {
        Token token = next(true);
        int type = token.getType();
        if (type == Token.NIL) {
            return null;
        }
        if (type != Token.ATOM && type != Token.QUOTEDSTRING && type != Token.LITERAL && type != Token.NUMERIC) {
            throw new ResponseFormatException("String token expected in response: " + token.getValue());
        }
        return token.getValue();
    }


    /**
     * Read an encoded string-valued token from the response.  A string
     * valued token can be either a quoted string, a literal value,
     * or an atom.  Any other token type is an error.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    public String readEncodedString() throws MessagingException {
        String value = readString();
        return decode(value);
    }


    /**
     * Decode a Base 64 encoded string value.
     *
     * @param original The original encoded string.
     *
     * @return The decoded string.
     * @exception MessagingException
     */
    public String decode(String original) throws MessagingException {
        StringBuffer result = new StringBuffer();

        for (int i = 0; i < original.length(); i++) {
            char ch = original.charAt(i);

            if (ch == '&') {
                i = decode(original, i, result);
            }
            else {
                result.append(ch);
            }
        }

        return result.toString();
    }


    /**
     * Decode a section of an encoded string value.
     *
     * @param original The original source string.
     * @param index    The current working index.
     * @param result   The StringBuffer used for the decoded result.
     *
     * @return The new index for the decoding operation.
     * @exception MessagingException
     */
    public static int decode(String original, int index, StringBuffer result) throws MessagingException {
        // look for the section terminator
        int terminator = original.indexOf('-', index);

        // unmatched?
        if (terminator == -1) {
            throw new MessagingException("Invalid UTF-7 encoded string");
        }

        // is this just an escaped "&"?
        if (terminator == index + 1) {
            // append and skip over this.
            result.append('&');
            return index + 2;
        }

        // step over the starting char
        index++;

        int chars = terminator - index;
        int quads = chars / 4;
        int residual = chars % 4;

        // buffer for decoded characters
        byte[] buffer = new byte[4];
        int bufferCount = 0;

        // process each of the full triplet pairs
        for (int i = 0; i < quads; i++) {
            byte b1 = decodingTable[original.charAt(index++) & 0xff];
            byte b2 = decodingTable[original.charAt(index++) & 0xff];
            byte b3 = decodingTable[original.charAt(index++) & 0xff];
            byte b4 = decodingTable[original.charAt(index++) & 0xff];

            buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));
            buffer[bufferCount++] = (byte)((b2 << 4) | (b3 >> 2));
            buffer[bufferCount++] = (byte)((b3 << 6) | b4);

            // we've written 3 bytes to the buffer, but we might have a residual from a previous
            // iteration to deal with.
            if (bufferCount == 4) {
                // two complete chars here
                b1 = buffer[0];
                b2 = buffer[1];
                result.append((char)((b1 << 8) + (b2 & 0xff)));
                b1 = buffer[2];
                b2 = buffer[3];
                result.append((char)((b1 << 8) + (b2 & 0xff)));
                bufferCount = 0;
            }
            else {
                // we need to save the 3rd byte for the next go around
                b1 = buffer[0];
                b2 = buffer[1];
                result.append((char)((b1 << 8) + (b2 & 0xff)));
                buffer[0] = buffer[2];
                bufferCount = 1;
            }
        }

        // properly encoded, we should have an even number of bytes left.

        switch (residual) {
            // no residual...so we better not have an extra in the buffer
            case 0:
                // this is invalid...we have an odd number of bytes so far,
                if (bufferCount == 1) {
                    throw new MessagingException("Invalid UTF-7 encoded string");
                }
            // one byte left.  This shouldn't be valid.  We need at least 2 bytes to
            // encode one unprintable char.
            case 1:
                throw new MessagingException("Invalid UTF-7 encoded string");

            // ok, we have two bytes left, which can only encode a single byte.  We must have
            // a dangling unhandled char.
            case 2:
            {
                if (bufferCount != 1) {
                    throw new MessagingException("Invalid UTF-7 encoded string");
                }
                byte b1 = decodingTable[original.charAt(index++) & 0xff];
                byte b2 = decodingTable[original.charAt(index++) & 0xff];
                buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));

                b1 = buffer[0];
                b2 = buffer[1];
                result.append((char)((b1 << 8) + (b2 & 0xff)));
                break;
            }

            // we have 2 encoded chars.  In this situation, we can't have a leftover.
            case 3:
            {
                // this is invalid...we have an odd number of bytes so far,
                if (bufferCount == 1) {
                    throw new MessagingException("Invalid UTF-7 encoded string");
                }
                byte b1 = decodingTable[original.charAt(index++) & 0xff];
                byte b2 = decodingTable[original.charAt(index++) & 0xff];
                byte b3 = decodingTable[original.charAt(index++) & 0xff];

                buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));
                buffer[bufferCount++] = (byte)((b2 << 4) | (b3 >> 2));

                b1 = buffer[0];
                b2 = buffer[1];
                result.append((char)((b1 << 8) + (b2 & 0xff)));
                break;
            }
        }

        // return the new scan location
        return terminator + 1;
    }

    /**
     * Read a string-valued token from the response, verifying this is an ATOM token.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    public String readAtom() throws MessagingException {
        return readAtom(false);
    }


    /**
     * Read a string-valued token from the response, verifying this is an ATOM token.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    public String readAtom(boolean expandedDelimiters) throws MessagingException {
        Token token = next(false, expandedDelimiters);
        int type = token.getType();

        if (type != Token.ATOM) {
            throw new ResponseFormatException("ATOM token expected in response: " + token.getValue());
        }
        return token.getValue();
    }


    /**
     * Read a number-valued token from the response.  This must be an ATOM
     * token.
     *
     * @return The integer value of the source token.
     * @exception ResponseFormatException
     */
    public int readInteger() throws MessagingException {
        Token token = next();
        return token.getInteger();
    }


    /**
     * Read a number-valued token from the response.  This must be an ATOM
     * token.
     *
     * @return The long value of the source token.
     * @exception ResponseFormatException
     */
    public int readLong() throws MessagingException {
        Token token = next();
        return token.getInteger();
    }


    /**
     * Read a string-valued token from the response.  A string
     * valued token can be either a quoted string, a literal value,
     * or an atom.  Any other token type is an error.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    public String readStringOrNil() throws MessagingException {
        // we need to recognize the NIL token.
        Token token = next(true);
        int type = token.getType();

        if (type != Token.ATOM && type != Token.QUOTEDSTRING && type != Token.LITERAL && type != Token.NIL) {
            throw new ResponseFormatException("String token or NIL expected in response: " + token.getValue());
        }
        // this returns null if the token is the NIL token.
        return token.getValue();
    }


    /**
     * Read a quoted string-valued token from the response.
     * Any other token type other than NIL is an error.
     *
     * @return The string value of the source token.
     * @exception ResponseFormatException
     */
    protected String readQuotedStringOrNil() throws MessagingException {
        // we need to recognize the NIL token.
        Token token = next(true);
        int type = token.getType();

        if (type != Token.QUOTEDSTRING && type != Token.NIL) {
            throw new ResponseFormatException("String token or NIL expected in response");
        }
        // this returns null if the token is the NIL token.
        return token.getValue();
    }


    /**
     * Read a date from a response string.  This is expected to be in
     * Internet Date format, but there's a lot of variation implemented
     * out there.  If we're unable to format this correctly, we'll
     * just return null.
     *
     * @return A Date object created from the source date.
     */
    public Date readDate() throws MessagingException {
        String value = readString();

        try {
            return dateParser.parse(value);
        } catch (Exception e) {
            // we're just skipping over this, so return null
            return null;
        }
    }


    /**
     * Read a date from a response string.  This is expected to be in
     * Internet Date format, but there's a lot of variation implemented
     * out there.  If we're unable to format this correctly, we'll
     * just return null.
     *
     * @return A Date object created from the source date.
     */
    public Date readDateOrNil() throws MessagingException {
        String value = readStringOrNil();
        // this might be optional
        if (value == null) {
            return null;
        }

        try {
            return dateParser.parse(value);
        } catch (Exception e) {
            // we're just skipping over this, so return null
            return null;
        }
    }

    /**
     * Read an internet address from a Fetch response.  The
     * addresses are returned as a set of string tokens in the
     * order "personal list mailbox host".  Any of these tokens
     * can be NIL.
     *
     * The address may also be the start of a group list, which
     * is indicated by the host being NIL.  If we have found the
     * start of a group, then we need to parse multiple elements
     * until we find the group end marker (indicated by both the
     * mailbox and the host being NIL), and create a group
     * InternetAddress instance from this.
     *
     * @return An InternetAddress instance parsed from the
     *         element.
     * @exception ResponseFormatException
     */
    public InternetAddress readAddress() throws MessagingException {
        // we recurse, expecting a null response back for sublists.
        if (peek().getType() != '(') {
            return null;
        }

        // must start with a paren
        checkLeftParen();

        // personal information
        String personal = readStringOrNil();
        // the domain routine information.
        String routing = readStringOrNil();
        // the target mailbox
        String mailbox = readStringOrNil();
        // and finally the host
        String host = readStringOrNil();
        // and validate the closing paren
        checkRightParen();

        // if this is a real address, we need to compose
        if (host != null) {
            StringBuffer address = new StringBuffer();
            if (routing != null) {
                address.append(routing);
                address.append(':');
            }
            address.append(mailbox);
            address.append('@');
            address.append(host);

            try {
                return new InternetAddress(address.toString(), personal);
            } catch (UnsupportedEncodingException e) {
                throw new ResponseFormatException("Invalid Internet address format");
            }
        }
        else {
            // we're going to recurse on this.  If the mailbox is null (the group name), this is the group item
            // terminator.
            if (mailbox == null) {
                return null;
            }

            StringBuffer groupAddress = new StringBuffer();

            groupAddress.append(mailbox);
            groupAddress.append(':');
            int count = 0;

            while (true) {
                // now recurse until we hit the end of the list
                InternetAddress member = readAddress();
                if (member == null) {
                    groupAddress.append(';');

                    try {
                        return new InternetAddress(groupAddress.toString(), personal);
                    } catch (UnsupportedEncodingException e) {
                        throw new ResponseFormatException("Invalid Internet address format");
                    }
                }
                else {
                    if (count != 0) {
                        groupAddress.append(',');
                    }
                    groupAddress.append(member.toString());
                    count++;
                }
            }
        }
    }


    /**
     * Parse out a list of addresses.  This list of addresses is
     * surrounded by parentheses, and each address is also
     * parenthized (SP?).
     *
     * @return An array of the parsed addresses.
     * @exception ResponseFormatException
     */
    public InternetAddress[] readAddressList() throws MessagingException {
        // must start with a paren, but can be NIL also.
        Token token = next(true);
        int type = token.getType();

        // either of these results in a null address.  The caller determines based on
        // context whether this was optional or not.
        if (type == Token.NIL) {
            return null;
        }
        // non-nil address and no paren.  This is a syntax error.
        else if (type != '(') {
            throw new ResponseFormatException("Missing '(' in response");
        }

        List addresses = new ArrayList();

        // we have a list, now parse it.
        while (notListEnd()) {
            // go read the next address.  If we had an address, add to the list.
            // an address ITEM cannot be NIL inside the parens.
            InternetAddress address = readAddress();
            addresses.add(address);
        }
        // we need to skip over the peeked token.
        checkRightParen();
        return (InternetAddress[])addresses.toArray(new InternetAddress[addresses.size()]);
    }


    /**
     * Check to see if we're at the end of a parenthized list
     * without advancing the parsing pointer.  If we are at the
     * end, then this will step over the closing paren.
     *
     * @return True if the next token is a closing list paren, false otherwise.
     * @exception ResponseFormatException
     */
    public boolean checkListEnd() throws MessagingException {
        Token token = peek(true);
        if (token.getType() == ')') {
            // step over this token.
            next();
            return true;
        }
        return false;
    }


    /**
     * Reads a string item which can be encoded either as a single
     * string-valued token or a parenthized list of string tokens.
     *
     * @return A List containing all of the strings.
     * @exception ResponseFormatException
     */
    public List readStringList() throws MessagingException {
        Token token = peek(true);

        if (token.getType() == '(') {
            List list = new ArrayList();

            next();

            while (notListEnd()) {
                String value = readString();
                // this can be NIL, technically
                if (value != null) {
                    list.add(value);
                }
            }
            // step over the closing paren
            next();

            return list;
        }
        else if (token != NIL) {
            List list = new ArrayList();

            // just a single string value.
            String value = readString();
            // this can be NIL, technically
            if (value != null) {
                list.add(value);
            }

            return list;
        } else {
            next();
        }
        return null;
    }


    /**
     * Reads all remaining tokens and returns them as a list of strings.
     * NIL values are not supported.
     *
     * @return A List containing all of the strings.
     * @exception ResponseFormatException
     */
    public List readStrings() throws MessagingException {
        List list = new ArrayList();

        while (hasMore()) {
            String value = readString();
            list.add(value);
        }
        return list;
    }


    /**
     * Skip over an extension item.  This may be either a string
     * token or a parenthized item (with potential nesting).
     *
     * At the point where this is called, we're looking for a closing
     * ')', but we know it is not that.  An EOF is an error, however,
     */
    public void skipExtensionItem() throws MessagingException {
        Token token = next();
        int type = token.getType();

        // list form?  Scan to find the correct list closure.
        if (type == '(') {
            skipNestedValue();
        }
        // found an EOF?  Big problem
        else if (type == Token.EOF) {
            throw new ResponseFormatException("Missing ')'");
        }
    }

    /**
     * Skip over a parenthized value that we're not interested in.
     * These lists may contain nested sublists, so we need to
     * handle the nesting properly.
     */
    public void skipNestedValue() throws MessagingException {
        Token token = next();

        while (true) {
            int type = token.getType();
            // list terminator?
            if (type == ')') {
                return;
            }
            // unexpected end of the tokens.
            else if (type == Token.EOF) {
                throw new ResponseFormatException("Missing ')'");
            }
            // encountered a nested list?
            else if (type == '(') {
                // recurse and finish this list.
                skipNestedValue();
            }
            // we're just skipping the token.
            token = next();
        }
    }

    /**
     * Get the next token and verify that it's of the expected type
     * for the context.
     *
     * @param type   The type of token we're expecting.
     */
    public void checkToken(int type) throws MessagingException {
        Token token = next();
        if (token.getType() != type) {
            throw new ResponseFormatException("Unexpected token: " + token.getValue());
        }
    }


    /**
     * Read the next token as binary data.  The next token can be a literal, a quoted string, or
     * the token NIL (which returns a null result).  Any other token throws a ResponseFormatException.
     *
     * @return A byte array representing the rest of the response data.
     */
    public byte[] readByteArray() throws MessagingException {
        return readData(true);
    }


    /**
     * Determine what type of token encoding needs to be
     * used for a string value.
     *
     * @param value  The string to test.
     *
     * @return Either Token.ATOM, Token.QUOTEDSTRING, or
     *         Token.LITERAL, depending on the characters contained
     *         in the value.
     */
    static public int getEncoding(byte[] value) {

        // a null string always needs to be represented as a quoted literal.
        if (value.length == 0) {
            return Token.QUOTEDSTRING;
        }

        for (int i = 0; i < value.length; i++) {
            int ch = value[i];
            // make sure the sign extension is eliminated
            ch = ch & 0xff;
            // check first for any characters that would
            // disqualify a quoted string
            // NULL
            if (ch == 0x00) {
                return Token.LITERAL;
            }
            // non-7bit ASCII
            if (ch > 0x7F) {
                return Token.LITERAL;
            }
            // carriage return
            if (ch == '\r') {
                return Token.LITERAL;
            }
            // linefeed
            if (ch == '\n') {
                return Token.LITERAL;
            }
            // now check for ATOM disqualifiers
            if (atomDelimiters.indexOf(ch) != -1) {
                return Token.QUOTEDSTRING;
            }
            // CTL character.  We've already eliminated the high characters
            if (ch < 0x20) {
                return Token.QUOTEDSTRING;
            }
        }
        // this can be an ATOM token
        return Token.ATOM;
    }


    /**
     * Read a ContentType or ContentDisposition parameter
     * list from an IMAP command response.
     *
     * @return A ParameterList instance containing the parameters.
     * @exception MessagingException
     */
    public ParameterList readParameterList() throws MessagingException {
        ParameterList params = new ParameterList();

        // read the tokens, taking NIL into account.
        Token token = next(true, false);

        // just return an empty list if this is NIL
        if (token.isType(token.NIL)) {
            return params;
        }

        // these are pairs of strings for each parameter value
        while (notListEnd()) {
            String name = readString();
            String value = readString();
            params.set(name, value);
        }
        // we need to consume the list terminator
        checkRightParen();
        return params;
    }


    /**
     * Test if we have more data in the response buffer.
     *
     * @return true if there are more tokens to process.  false if
     *         we've reached the end of the stream.
     */
    public boolean hasMore() throws MessagingException {
        // we need to eat any white space that might be in the stream.
        eatWhiteSpace();
        return pos < response.length;
    }


    /**
     * Tests if we've reached the end of a parenthetical
     * list in our parsing stream.
     *
     * @return true if the next token will be a ')'.  false if the
     *         next token is anything else.
     * @exception MessagingException
     */
    public boolean notListEnd() throws MessagingException {
        return peek().getType() != ')';
    }

    /**
     * Read a list of Flag values from an IMAP response,
     * returning a Flags instance containing the appropriate
     * pieces.
     *
     * @return A Flags instance with the flag values.
     * @exception MessagingException
     */
    public Flags readFlagList() throws MessagingException {
        Flags flags = new Flags();

        // this should be a list here
        checkLeftParen();

        // run through the flag list
        while (notListEnd()) {
            // the flags are a bit of a pain.  The flag names include "\" in the name, which
            // is not a character allowed in an atom.  This requires a bit of customized parsing
            // to handle this.
            Token token = next();
            // flags can be specified as just atom tokens, so allow this as a user flag.
            if (token.isType(token.ATOM)) {
                // append the atom as a raw name
                flags.add(token.getValue());
            }
            // all of the system flags start with a '\' followed by
            // an atom.  They also can be extension flags.  IMAP has a special
            // case of "\*" that we need to check for.
            else if (token.isType('\\')) {
                token = next();
                // the next token is the real bit we need to process.
                if (token.isType('*')) {
                    // this indicates USER flags are allowed.
                    flags.add(Flags.Flag.USER);
                }
                // if this is an atom name, handle as a system flag
                else if (token.isType(Token.ATOM)) {
                    String name = token.getValue();
                    if (name.equalsIgnoreCase("Seen")) {
                        flags.add(Flags.Flag.SEEN);
                    }
                    else if (name.equalsIgnoreCase("RECENT")) {
                        flags.add(Flags.Flag.RECENT);
                    }
                    else if (name.equalsIgnoreCase("DELETED")) {
                        flags.add(Flags.Flag.DELETED);
                    }
                    else if (name.equalsIgnoreCase("ANSWERED")) {
                        flags.add(Flags.Flag.ANSWERED);
                    }
                    else if (name.equalsIgnoreCase("DRAFT")) {
                        flags.add(Flags.Flag.DRAFT);
                    }
                    else if (name.equalsIgnoreCase("FLAGGED")) {
                        flags.add(Flags.Flag.FLAGGED);
                    }
                    else {
                        // this is a server defined flag....just add the name with the
                        // flag thingy prepended.
                        flags.add("\\" + name);
                    }
                }
                else {
                    throw new MessagingException("Invalid Flag: " + token.getValue());
                }
            }
            else {
                throw new MessagingException("Invalid Flag: " + token.getValue());
            }
        }

        // step over this for good practice.
        checkRightParen();

        return flags;
    }


    /**
     * Read a list of Flag values from an IMAP response,
     * returning a Flags instance containing the appropriate
     * pieces.
     *
     * @return A Flags instance with the flag values.
     * @exception MessagingException
     */
    public List readSystemNameList() throws MessagingException {
        List flags = new ArrayList();

        // this should be a list here
        checkLeftParen();

        // run through the flag list
        while (notListEnd()) {
            // the flags are a bit of a pain.  The flag names include "\" in the name, which
            // is not a character allowed in an atom.  This requires a bit of customized parsing
            // to handle this.
            Token token = next();
            // all of the system flags start with a '\' followed by
            // an atom.  They also can be extension flags.  IMAP has a special
            // case of "\*" that we need to check for.
            if (token.isType('\\')) {
                token = next();
                // if this is an atom name, handle as a system flag
                if (token.isType(Token.ATOM)) {
                    // add the token value to the list WITH the
                    // flag indicator included.  The attributes method returns
                    // these flag indicators, so we need to include it.
                    flags.add("\\" + token.getValue());
                }
                else {
                    throw new MessagingException("Invalid Flag: " + token.getValue());
                }
            }
            else {
                throw new MessagingException("Invalid Flag: " + token.getValue());
            }
        }

        // step over this for good practice.
        checkRightParen();

        return flags;
    }
}

