1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.proxy.utils;
21
22 import java.io.ByteArrayOutputStream;
23 import java.io.UnsupportedEncodingException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.security.sasl.AuthenticationException;
30 import javax.security.sasl.SaslException;
31
32
33
34
35
36
37
38
39 public class StringUtilities {
40
41
42
43
44
45 public static String getDirectiveValue(
46 HashMap<String, String> directivesMap, String directive,
47 boolean mandatory) throws AuthenticationException {
48 String value = directivesMap.get(directive);
49 if (value == null) {
50 if (mandatory) {
51 throw new AuthenticationException("\"" + directive
52 + "\" mandatory directive is missing");
53 } else {
54 return "";
55 }
56 }
57
58 return value;
59 }
60
61
62
63
64 public static String copyDirective(HashMap<String, String> directives,
65 StringBuilder sb, String directive) {
66 String directiveValue = directives.get(directive);
67 if (directiveValue != null) {
68 sb.append(directive).append(" = \"").append(directiveValue).append(
69 "\", ");
70 }
71
72 return directiveValue;
73 }
74
75
76
77
78 public static String copyDirective(HashMap<String, String> src,
79 HashMap<String, String> dst, String directive) {
80 String directiveValue = src.get(directive);
81 if (directiveValue != null) {
82 dst.put(directive, directiveValue);
83 }
84
85 return directiveValue;
86 }
87
88
89
90
91
92
93
94
95
96 public static HashMap<String, String> parseDirectives(byte[] buf)
97 throws SaslException {
98 HashMap<String, String> map = new HashMap<String, String>();
99 boolean gettingKey = true;
100 boolean gettingQuotedValue = false;
101 boolean expectSeparator = false;
102 byte bch;
103
104 ByteArrayOutputStream key = new ByteArrayOutputStream(10);
105 ByteArrayOutputStream value = new ByteArrayOutputStream(10);
106
107 int i = skipLws(buf, 0);
108 while (i < buf.length) {
109 bch = buf[i];
110
111 if (gettingKey) {
112 if (bch == ',') {
113 if (key.size() != 0) {
114 throw new SaslException("Directive key contains a ',':"
115 + key);
116 }
117
118
119 i = skipLws(buf, i + 1);
120 } else if (bch == '=') {
121 if (key.size() == 0) {
122 throw new SaslException("Empty directive key");
123 }
124
125 gettingKey = false;
126 i = skipLws(buf, i + 1);
127
128
129 if (i < buf.length) {
130 if (buf[i] == '"') {
131 gettingQuotedValue = true;
132 ++i;
133 }
134 } else {
135 throw new SaslException("Valueless directive found: "
136 + key.toString());
137 }
138 } else if (isLws(bch)) {
139
140 i = skipLws(buf, i + 1);
141
142
143 if (i < buf.length) {
144 if (buf[i] != '=') {
145 throw new SaslException("'=' expected after key: "
146 + key.toString());
147 }
148 } else {
149 throw new SaslException("'=' expected after key: "
150 + key.toString());
151 }
152 } else {
153 key.write(bch);
154 ++i;
155 }
156 } else if (gettingQuotedValue) {
157
158 if (bch == '\\') {
159
160 ++i;
161 if (i < buf.length) {
162 value.write(buf[i]);
163 ++i;
164 } else {
165
166 throw new SaslException(
167 "Unmatched quote found for directive: "
168 + key.toString() + " with value: "
169 + value.toString());
170 }
171 } else if (bch == '"') {
172
173 ++i;
174 gettingQuotedValue = false;
175 expectSeparator = true;
176 } else {
177 value.write(bch);
178 ++i;
179 }
180 } else if (isLws(bch) || bch == ',') {
181
182 extractDirective(map, key.toString(), value.toString());
183 key.reset();
184 value.reset();
185 gettingKey = true;
186 gettingQuotedValue = expectSeparator = false;
187 i = skipLws(buf, i + 1);
188 } else if (expectSeparator) {
189 throw new SaslException(
190 "Expecting comma or linear whitespace after quoted string: \""
191 + value.toString() + "\"");
192 } else {
193 value.write(bch);
194 ++i;
195 }
196 }
197
198 if (gettingQuotedValue) {
199 throw new SaslException("Unmatched quote found for directive: "
200 + key.toString() + " with value: " + value.toString());
201 }
202
203
204 if (key.size() > 0) {
205 extractDirective(map, key.toString(), value.toString());
206 }
207
208 return map;
209 }
210
211
212
213
214
215
216
217
218
219
220 private static void extractDirective(HashMap<String, String> map,
221 String key, String value) throws SaslException {
222 if (map.get(key) != null) {
223 throw new SaslException("Peer sent more than one " + key
224 + " directive");
225 } else {
226 map.put(key, value);
227 }
228 }
229
230
231
232
233
234
235
236
237
238 public static boolean isLws(byte b) {
239 switch (b) {
240 case 13:
241 case 10:
242 case 32:
243 case 9:
244 return true;
245 }
246
247 return false;
248 }
249
250
251
252
253 private static int skipLws(byte[] buf, int start) {
254 int i;
255
256 for (i = start; i < buf.length; i++) {
257 if (!isLws(buf[i])) {
258 return i;
259 }
260 }
261
262 return i;
263 }
264
265
266
267
268
269
270
271
272
273 public static String stringTo8859_1(String str)
274 throws UnsupportedEncodingException {
275 if (str == null) {
276 return "";
277 } else {
278 return new String(str.getBytes("UTF8"), "8859_1");
279 }
280 }
281
282 public static String getSingleValuedHeader(
283 Map<String, List<String>> headers, String key) {
284 List<String> values = headers.get(key);
285
286 if (values == null) {
287 return null;
288 } else {
289 if (values.size() > 1) {
290 throw new IllegalArgumentException("Header with key [\"" + key
291 + "\"] isn't single valued !");
292 } else {
293 return values.get(0);
294 }
295 }
296 }
297
298 public static void addValueToHeader(Map<String, List<String>> headers,
299 String key, String value, boolean singleValued) {
300 List<String> values = headers.get(key);
301
302 if (values == null) {
303 values = new ArrayList<String>(1);
304 headers.put(key, values);
305 }
306
307 if (singleValued && values.size() == 1) {
308 values.set(0, value);
309 } else {
310 values.add(value);
311 }
312 }
313 }