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