blob: 3d3491de92f9dd4773ab2b8a6bd1a0be91985ecd [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/* **************************************************************************
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 ******************************************************************************/
15package com.novell.sasl.client;
16
17import 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 */
23class 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