1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.internal.transport.sshd.proxy;
44
45 import java.util.ArrayList;
46 import java.util.Iterator;
47 import java.util.List;
48
49
50
51
52
53
54
55
56 public final class HttpParser {
57
58
59
60
61 public static class ParseException extends Exception {
62
63 private static final long serialVersionUID = -1634090143702048640L;
64
65 }
66
67 private HttpParser() {
68
69 }
70
71
72
73
74
75
76
77
78
79
80 public static StatusLine parseStatusLine(String line)
81 throws ParseException {
82
83 int firstBlank = line.indexOf(' ');
84 if (firstBlank < 0) {
85 throw new ParseException();
86 }
87 int secondBlank = line.indexOf(' ', firstBlank + 1);
88 if (secondBlank < 0) {
89
90
91 secondBlank = line.length();
92 }
93 int resultCode;
94 try {
95 resultCode = Integer.parseUnsignedInt(
96 line.substring(firstBlank + 1, secondBlank));
97 } catch (NumberFormatException e) {
98 throw new ParseException();
99 }
100
101 String reason = "";
102 if (secondBlank < line.length()) {
103 reason = line.substring(secondBlank + 1);
104 }
105 return new StatusLine(line.substring(0, firstBlank), resultCode,
106 reason);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public static List<AuthenticationChallenge> getAuthenticationHeaders(
122 List<String> reply, String authenticationHeader) {
123 List<AuthenticationChallenge> challenges = new ArrayList<>();
124 Iterator<String> lines = reply.iterator();
125
126 lines.next();
127 StringBuilder value = null;
128 while (lines.hasNext()) {
129 String line = lines.next();
130 if (line.isEmpty()) {
131 break;
132 }
133 if (Character.isWhitespace(line.charAt(0))) {
134
135 if (value == null) {
136
137 continue;
138 }
139
140 int i = skipWhiteSpace(line, 1);
141 value.append(' ').append(line, i, line.length());
142 continue;
143 }
144 if (value != null) {
145 parseChallenges(challenges, value.toString());
146 value = null;
147 }
148 int firstColon = line.indexOf(':');
149 if (firstColon > 0 && authenticationHeader
150 .equalsIgnoreCase(line.substring(0, firstColon + 1))) {
151 value = new StringBuilder(line.substring(firstColon + 1));
152 }
153 }
154 if (value != null) {
155 parseChallenges(challenges, value.toString());
156 }
157 return challenges;
158 }
159
160 private static void parseChallenges(
161 List<AuthenticationChallenge> challenges,
162 String header) {
163
164
165
166
167
168 int length = header.length();
169 for (int i = 0; i < length;) {
170 int start = skipWhiteSpace(header, i);
171 int end = scanToken(header, start);
172 if (end <= start) {
173 break;
174 }
175 AuthenticationChallenge challenge = new AuthenticationChallenge(
176 header.substring(start, end));
177 challenges.add(challenge);
178 i = parseChallenge(challenge, header, end);
179 }
180 }
181
182 private static int parseChallenge(AuthenticationChallenge challenge,
183 String header, int from) {
184 int length = header.length();
185 boolean first = true;
186 for (int start = from; start <= length; first = false) {
187
188
189
190
191 start = skipWhiteSpace(header, start);
192 int end = scanToken(header, start);
193 if (end == start) {
194
195 if (start < header.length() && header.charAt(start) == ',') {
196 return start + 1;
197 }
198 return start;
199 }
200 int next = skipWhiteSpace(header, end);
201
202 if (next >= length || header.charAt(next) != '=') {
203 if (first) {
204
205 challenge.setToken(header.substring(start, end));
206 if (next < length && header.charAt(next) == ',') {
207 next++;
208 }
209 return next;
210 } else {
211
212
213 return start;
214 }
215 }
216 int nextStart = skipWhiteSpace(header, next + 1);
217 if (nextStart >= length) {
218 if (next == end) {
219
220
221 challenge.setToken(header.substring(start, end + 1));
222 } else {
223
224 challenge.addArgument(header.substring(start, end), null);
225 }
226 return nextStart;
227 }
228 if (nextStart == end + 1 && header.charAt(nextStart) == '=') {
229
230 end = nextStart + 1;
231 while (end < length && header.charAt(end) == '=') {
232 end++;
233 }
234 challenge.setToken(header.substring(start, end));
235 end = skipWhiteSpace(header, end);
236 if (end < length && header.charAt(end) == ',') {
237 end++;
238 }
239 return end;
240 }
241 if (header.charAt(nextStart) == ',') {
242 if (next == end) {
243
244
245 challenge.setToken(header.substring(start, end + 1));
246 return nextStart + 1;
247 } else {
248
249 challenge.addArgument(header.substring(start, end), null);
250 start = nextStart + 1;
251 }
252 } else {
253 if (header.charAt(nextStart) == '"') {
254 int nextEnd[] = { nextStart + 1 };
255 String value = scanQuotedString(header, nextStart + 1,
256 nextEnd);
257 challenge.addArgument(header.substring(start, end), value);
258 start = nextEnd[0];
259 } else {
260 int nextEnd = scanToken(header, nextStart);
261 challenge.addArgument(header.substring(start, end),
262 header.substring(nextStart, nextEnd));
263 start = nextEnd;
264 }
265 start = skipWhiteSpace(header, start);
266 if (start < length && header.charAt(start) == ',') {
267 start++;
268 }
269 }
270 }
271 return length;
272 }
273
274 private static int skipWhiteSpace(String header, int i) {
275 int length = header.length();
276 while (i < length && Character.isWhitespace(header.charAt(i))) {
277 i++;
278 }
279 return i;
280 }
281
282 private static int scanToken(String header, int from) {
283 int length = header.length();
284 int i = from;
285 while (i < length) {
286 char c = header.charAt(i);
287 switch (c) {
288 case '!':
289 case '#':
290 case '$':
291 case '%':
292 case '&':
293 case '\'':
294 case '*':
295 case '+':
296 case '-':
297 case '.':
298 case '^':
299 case '_':
300 case '`':
301 case '|':
302 case '0':
303 case '1':
304 case '2':
305 case '3':
306 case '4':
307 case '5':
308 case '6':
309 case '7':
310 case '8':
311 case '9':
312 i++;
313 break;
314 default:
315 if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
316 i++;
317 break;
318 }
319 return i;
320 }
321 }
322 return i;
323 }
324
325 private static String scanQuotedString(String header, int from, int[] to) {
326 StringBuilder result = new StringBuilder();
327 int length = header.length();
328 boolean quoted = false;
329 int i = from;
330 while (i < length) {
331 char c = header.charAt(i++);
332 if (quoted) {
333 result.append(c);
334 quoted = false;
335 } else if (c == '\\') {
336 quoted = true;
337 } else if (c == '"') {
338 break;
339 } else {
340 result.append(c);
341 }
342 }
343 to[0] = i;
344 return result.toString();
345 }
346 }