• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TokenParser( String tokens)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      */
parseToken()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      */
isValidTokenChar( char c)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      */
isWhiteSpace( char c)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