/* ************************************************************************** * $OpenLDAP: /com/novell/sasl/client/TokenParser.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $ * * Copyright (C) 2002 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. ******************************************************************************/ package com.novell.sasl.client; import org.apache.harmony.javax.security.sasl.*; /** * The TokenParser class will parse individual tokens from a list of tokens that * are a directive value for a DigestMD5 authentication.The tokens are separated * commas. */ class TokenParser extends Object { private static final int STATE_LOOKING_FOR_FIRST_TOKEN = 1; private static final int STATE_LOOKING_FOR_TOKEN = 2; private static final int STATE_SCANNING_TOKEN = 3; private static final int STATE_LOOKING_FOR_COMMA = 4; private static final int STATE_PARSING_ERROR = 5; private static final int STATE_DONE = 6; private int m_curPos; private int m_scanStart; private int m_state; private String m_tokens; TokenParser( String tokens) { m_tokens = tokens; m_curPos = 0; m_scanStart = 0; m_state = STATE_LOOKING_FOR_FIRST_TOKEN; } /** * This function parses the next token from the tokens string and returns * it as a string. If there are no more tokens a null reference is returned. * * @return the parsed token or a null reference if there are no more * tokens * * @exception SASLException if an error occurs while parsing */ String parseToken() throws SaslException { char currChar; String token = null; if (m_state == STATE_DONE) return null; while (m_curPos < m_tokens.length() && (token == null)) { currChar = m_tokens.charAt(m_curPos); switch (m_state) { case STATE_LOOKING_FOR_FIRST_TOKEN: case STATE_LOOKING_FOR_TOKEN: if (isWhiteSpace(currChar)) { break; } else if (isValidTokenChar(currChar)) { m_scanStart = m_curPos; m_state = STATE_SCANNING_TOKEN; } else { m_state = STATE_PARSING_ERROR; throw new SaslException("Invalid token character at position " + m_curPos); } break; case STATE_SCANNING_TOKEN: if (isValidTokenChar(currChar)) { break; } else if (isWhiteSpace(currChar)) { token = m_tokens.substring(m_scanStart, m_curPos); m_state = STATE_LOOKING_FOR_COMMA; } else if (',' == currChar) { token = m_tokens.substring(m_scanStart, m_curPos); m_state = STATE_LOOKING_FOR_TOKEN; } else { m_state = STATE_PARSING_ERROR; throw new SaslException("Invalid token character at position " + m_curPos); } break; case STATE_LOOKING_FOR_COMMA: if (isWhiteSpace(currChar)) break; else if (currChar == ',') m_state = STATE_LOOKING_FOR_TOKEN; else { m_state = STATE_PARSING_ERROR; throw new SaslException("Expected a comma, found '" + currChar + "' at postion " + m_curPos); } break; } m_curPos++; } /* end while loop */ if (token == null) { /* check the ending state */ switch (m_state) { case STATE_SCANNING_TOKEN: token = m_tokens.substring(m_scanStart); m_state = STATE_DONE; break; case STATE_LOOKING_FOR_FIRST_TOKEN: case STATE_LOOKING_FOR_COMMA: break; case STATE_LOOKING_FOR_TOKEN: throw new SaslException("Trialing comma"); } } return token; } /** * This function returns TRUE if the character is a valid token character. * * token = 1* * * separators = "(" | ")" | "<" | ">" | "@" * | "," | ";" | ":" | "\" | <"> * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT * * CTL = * * CHAR = * * @param c character to be validated * * @return True if character is valid Token character else it returns * false */ boolean isValidTokenChar( char c) { if ( ( (c >= '\u0000') && (c <='\u0020') ) || ( (c >= '\u003a') && (c <= '\u0040') ) || ( (c >= '\u005b') && (c <= '\u005d') ) || ('\u002c' == c) || ('\u0025' == c) || ('\u0028' == c) || ('\u0029' == c) || ('\u007b' == c) || ('\u007d' == c) || ('\u007f' == c) ) return false; return true; } /** * This function returns TRUE if the character is linear white space (LWS). * LWS = [CRLF] 1*( SP | HT ) * * @param c character to be validated * * @return True if character is liner whitespace else it returns false */ boolean isWhiteSpace( char c) { if ( ('\t' == c) || // HORIZONTAL TABULATION. ('\n' == c) || // LINE FEED. ('\r' == c) || // CARRIAGE RETURN. ('\u0020' == c) ) return true; return false; } }