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