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 package org.apache.hc.client5.http.impl.auth;
29
30 import java.util.ArrayList;
31 import java.util.BitSet;
32 import java.util.List;
33
34 import org.apache.hc.client5.http.auth.AuthChallenge;
35 import org.apache.hc.client5.http.auth.ChallengeType;
36 import org.apache.hc.core5.http.NameValuePair;
37 import org.apache.hc.core5.http.ParseException;
38 import org.apache.hc.core5.http.message.BasicNameValuePair;
39 import org.apache.hc.core5.http.message.ParserCursor;
40 import org.apache.hc.core5.http.message.TokenParser;
41 import org.apache.hc.core5.util.TextUtils;
42
43
44
45
46
47
48 public class AuthChallengeParser {
49
50 public static final AuthChallengeParserth/AuthChallengeParser.html#AuthChallengeParser">AuthChallengeParser INSTANCE = new AuthChallengeParser();
51
52 private final TokenParser tokenParser = TokenParser.INSTANCE;
53
54 private final static char BLANK = ' ';
55 private final static char COMMA_CHAR = ',';
56 private final static char EQUAL_CHAR = '=';
57
58
59
60 private static final BitSet TERMINATORS = TokenParser.INIT_BITSET(BLANK, EQUAL_CHAR, COMMA_CHAR);
61 private static final BitSet DELIMITER = TokenParser.INIT_BITSET(COMMA_CHAR);
62 private static final BitSet SPACE = TokenParser.INIT_BITSET(BLANK);
63
64 static class ChallengeInt {
65
66 final String schemeName;
67 final List<NameValuePair> params;
68
69 ChallengeInt(final String schemeName) {
70 this.schemeName = schemeName;
71 this.params = new ArrayList<>();
72 }
73
74 @Override
75 public String toString() {
76 return "ChallengeInternal{" +
77 "schemeName='" + schemeName + '\'' +
78 ", params=" + params +
79 '}';
80 }
81
82 }
83
84
85
86
87
88
89
90
91
92 public List<AuthChallenge> parse(
93 final ChallengeType challengeType, final CharSequence buffer, final ParserCursor cursor) throws ParseException {
94 tokenParser.skipWhiteSpace(buffer, cursor);
95 if (cursor.atEnd()) {
96 throw new ParseException("Malformed auth challenge");
97 }
98 final List<ChallengeInt> internalChallenges = new ArrayList<>();
99 final String schemeName = tokenParser.parseToken(buffer, cursor, SPACE);
100 if (TextUtils.isBlank(schemeName)) {
101 throw new ParseException("Malformed auth challenge");
102 }
103 ChallengeInt current = new ChallengeInt(schemeName);
104 while (current != null) {
105 internalChallenges.add(current);
106 current = parseChallenge(buffer, cursor, current);
107 }
108 final List<AuthChallenge> challenges = new ArrayList<>(internalChallenges.size());
109 for (final ChallengeInt internal : internalChallenges) {
110 final List<NameValuePair> params = internal.params;
111 String token68 = null;
112 if (params.size() == 1) {
113 final NameValuePair param = params.get(0);
114 if (param.getValue() == null) {
115 token68 = param.getName();
116 params.clear();
117 }
118 }
119 challenges.add(
120 new AuthChallenge(challengeType, internal.schemeName, token68, !params.isEmpty() ? params : null));
121 }
122 return challenges;
123 }
124
125 ChallengeInt parseChallenge(
126 final CharSequence buffer,
127 final ParserCursor cursor,
128 final ChallengeInt currentChallenge) throws ParseException {
129 for (;;) {
130 tokenParser.skipWhiteSpace(buffer, cursor);
131 if (cursor.atEnd()) {
132 return null;
133 }
134 final String token = parseToken(buffer, cursor);
135 if (TextUtils.isBlank(token)) {
136 throw new ParseException("Malformed auth challenge");
137 }
138 tokenParser.skipWhiteSpace(buffer, cursor);
139
140
141 if (cursor.atEnd()) {
142
143 currentChallenge.params.add(new BasicNameValuePair(token, null));
144 } else {
145 char ch = buffer.charAt(cursor.getPos());
146 if (ch == EQUAL_CHAR) {
147 cursor.updatePos(cursor.getPos() + 1);
148 final String value = tokenParser.parseValue(buffer, cursor, DELIMITER);
149 tokenParser.skipWhiteSpace(buffer, cursor);
150 if (!cursor.atEnd()) {
151 ch = buffer.charAt(cursor.getPos());
152 if (ch == COMMA_CHAR) {
153 cursor.updatePos(cursor.getPos() + 1);
154 }
155 }
156 currentChallenge.params.add(new BasicNameValuePair(token, value));
157 } else if (ch == COMMA_CHAR) {
158 cursor.updatePos(cursor.getPos() + 1);
159 currentChallenge.params.add(new BasicNameValuePair(token, null));
160 } else {
161
162 if (currentChallenge.params.isEmpty()) {
163 throw new ParseException("Malformed auth challenge");
164 }
165 return new ChallengeInt(token);
166 }
167 }
168 }
169 }
170
171 String parseToken(final CharSequence buf, final ParserCursor cursor) {
172 final StringBuilder dst = new StringBuilder();
173 while (!cursor.atEnd()) {
174 int pos = cursor.getPos();
175 char current = buf.charAt(pos);
176 if (TERMINATORS.get(current)) {
177
178 if (current == EQUAL_CHAR) {
179
180
181 if (pos + 1 < cursor.getUpperBound() && buf.charAt(pos + 1) != EQUAL_CHAR) {
182 break;
183 }
184 do {
185 dst.append(current);
186 pos++;
187 cursor.updatePos(pos);
188 if (cursor.atEnd()) {
189 break;
190 }
191 current = buf.charAt(pos);
192 } while (current == EQUAL_CHAR);
193 } else {
194 break;
195 }
196 } else {
197 dst.append(current);
198 cursor.updatePos(pos + 1);
199 }
200 }
201 return dst.toString();
202 }
203
204 }