Home | History | Annotate | Download | only in client
      1 /* **************************************************************************
      2  * $OpenLDAP: /com/novell/sasl/client/TokenParser.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
      3  *
      4  * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
      5  *
      6  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
      7  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
      8  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
      9  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
     10  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
     11  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
     12  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
     13  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
     14  ******************************************************************************/
     15 package com.novell.sasl.client;
     16 
     17 import org.apache.harmony.javax.security.sasl.*;
     18 /**
     19  * The TokenParser class will parse individual tokens from a list of tokens that
     20  * are a directive value for a DigestMD5 authentication.The tokens are separated
     21  * commas.
     22  */
     23 class TokenParser extends Object
     24 {
     25     private static final int STATE_LOOKING_FOR_FIRST_TOKEN = 1;
     26     private static final int STATE_LOOKING_FOR_TOKEN       = 2;
     27     private static final int STATE_SCANNING_TOKEN          = 3;
     28     private static final int STATE_LOOKING_FOR_COMMA       = 4;
     29     private static final int STATE_PARSING_ERROR           = 5;
     30     private static final int STATE_DONE                    = 6;
     31 
     32     private int        m_curPos;
     33     private int     m_scanStart;
     34     private int     m_state;
     35     private String  m_tokens;
     36 
     37 
     38     TokenParser(
     39         String tokens)
     40     {
     41         m_tokens = tokens;
     42         m_curPos = 0;
     43         m_scanStart = 0;
     44         m_state =  STATE_LOOKING_FOR_FIRST_TOKEN;
     45     }
     46 
     47     /**
     48      * This function parses the next token from the tokens string and returns
     49      * it as a string. If there are no more tokens a null reference is returned.
     50      *
     51      * @return  the parsed token or a null reference if there are no more
     52      * tokens
     53      *
     54      * @exception  SASLException if an error occurs while parsing
     55      */
     56     String parseToken() throws SaslException
     57     {
     58         char    currChar;
     59         String  token = null;
     60 
     61 
     62         if (m_state == STATE_DONE)
     63             return null;
     64 
     65         while (m_curPos < m_tokens.length() && (token == null))
     66         {
     67             currChar = m_tokens.charAt(m_curPos);
     68             switch (m_state)
     69             {
     70             case STATE_LOOKING_FOR_FIRST_TOKEN:
     71             case STATE_LOOKING_FOR_TOKEN:
     72                 if (isWhiteSpace(currChar))
     73                 {
     74                     break;
     75                 }
     76                 else if (isValidTokenChar(currChar))
     77                 {
     78                     m_scanStart = m_curPos;
     79                     m_state = STATE_SCANNING_TOKEN;
     80                 }
     81                 else
     82                 {
     83                     m_state = STATE_PARSING_ERROR;
     84                     throw new SaslException("Invalid token character at position " + m_curPos);
     85                 }
     86                 break;
     87 
     88             case STATE_SCANNING_TOKEN:
     89                 if (isValidTokenChar(currChar))
     90                 {
     91                     break;
     92                 }
     93                 else if (isWhiteSpace(currChar))
     94                 {
     95                     token = m_tokens.substring(m_scanStart, m_curPos);
     96                     m_state = STATE_LOOKING_FOR_COMMA;
     97                 }
     98                 else if (',' == currChar)
     99                 {
    100                     token = m_tokens.substring(m_scanStart, m_curPos);
    101                     m_state = STATE_LOOKING_FOR_TOKEN;
    102                 }
    103                 else
    104                 {
    105                     m_state = STATE_PARSING_ERROR;
    106                     throw new SaslException("Invalid token character at position " + m_curPos);
    107                 }
    108                 break;
    109 
    110 
    111             case STATE_LOOKING_FOR_COMMA:
    112                 if (isWhiteSpace(currChar))
    113                     break;
    114                 else if (currChar == ',')
    115                     m_state = STATE_LOOKING_FOR_TOKEN;
    116                 else
    117                 {
    118                     m_state = STATE_PARSING_ERROR;
    119                     throw new SaslException("Expected a comma, found '" +
    120                                             currChar + "' at postion " +
    121                                             m_curPos);
    122                 }
    123                 break;
    124             }
    125             m_curPos++;
    126         } /* end while loop */
    127 
    128         if (token == null)
    129         {    /* check the ending state */
    130             switch (m_state)
    131             {
    132             case STATE_SCANNING_TOKEN:
    133                 token = m_tokens.substring(m_scanStart);
    134                 m_state = STATE_DONE;
    135                 break;
    136 
    137             case STATE_LOOKING_FOR_FIRST_TOKEN:
    138             case STATE_LOOKING_FOR_COMMA:
    139                 break;
    140 
    141             case STATE_LOOKING_FOR_TOKEN:
    142                 throw new SaslException("Trialing comma");
    143             }
    144         }
    145 
    146         return token;
    147     }
    148 
    149     /**
    150      * This function returns TRUE if the character is a valid token character.
    151      *
    152      *     token          = 1*<any CHAR except CTLs or separators>
    153      *
    154      *      separators     = "(" | ")" | "<" | ">" | "@"
    155      *                     | "," | ";" | ":" | "\" | <">
    156      *                     | "/" | "[" | "]" | "?" | "="
    157      *                     | "{" | "}" | SP | HT
    158      *
    159      *      CTL            = <any US-ASCII control character
    160      *                       (octets 0 - 31) and DEL (127)>
    161      *
    162      *      CHAR           = <any US-ASCII character (octets 0 - 127)>
    163      *
    164      * @param c  character to be validated
    165      *
    166      * @return True if character is valid Token character else it returns
    167      * false
    168      */
    169     boolean isValidTokenChar(
    170         char c)
    171     {
    172         if ( ( (c >= '\u0000') && (c <='\u0020') ) ||
    173              ( (c >= '\u003a') && (c <= '\u0040') ) ||
    174              ( (c >= '\u005b') && (c <= '\u005d') ) ||
    175              ('\u002c' == c) ||
    176              ('\u0025' == c) ||
    177              ('\u0028' == c) ||
    178              ('\u0029' == c) ||
    179              ('\u007b' == c) ||
    180              ('\u007d' == c) ||
    181              ('\u007f' == c) )
    182             return false;
    183 
    184         return true;
    185     }
    186 
    187     /**
    188      * This function returns TRUE if the character is linear white space (LWS).
    189      *         LWS = [CRLF] 1*( SP | HT )
    190      *
    191      * @param c  character to be validated
    192      *
    193      * @return True if character is liner whitespace else it returns false
    194      */
    195     boolean isWhiteSpace(
    196         char c)
    197     {
    198         if ( ('\t' == c) || // HORIZONTAL TABULATION.
    199              ('\n' == c) || // LINE FEED.
    200              ('\r' == c) || // CARRIAGE RETURN.
    201              ('\u0020' == c) )
    202             return true;
    203 
    204         return false;
    205     }
    206 
    207 }
    208 
    209