Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/javax/naming/ldap/Rfc2253Parser.java
41159 views
1
/*
2
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package javax.naming.ldap;
27
28
import java.util.List;
29
import java.util.ArrayList;
30
31
import javax.naming.InvalidNameException;
32
33
/*
34
* RFC2253Parser implements a recursive descent parser for a single DN.
35
*/
36
final class Rfc2253Parser {
37
38
private final String name; // DN being parsed
39
private final char[] chars; // characters in LDAP name being parsed
40
private final int len; // length of "chars"
41
private int cur = 0; // index of first unconsumed char in "chars"
42
43
/*
44
* Given an LDAP DN in string form, returns a parser for it.
45
*/
46
Rfc2253Parser(String name) {
47
this.name = name;
48
len = name.length();
49
chars = name.toCharArray();
50
}
51
52
/*
53
* Parses the DN, returning a List of its RDNs.
54
*/
55
// public List<Rdn> getDN() throws InvalidNameException {
56
57
List<Rdn> parseDn() throws InvalidNameException {
58
cur = 0;
59
60
// ArrayList<Rdn> rdns =
61
// new ArrayList<Rdn>(len / 3 + 10); // leave room for growth
62
63
ArrayList<Rdn> rdns =
64
new ArrayList<>(len / 3 + 10); // leave room for growth
65
66
if (len == 0) {
67
return rdns;
68
}
69
70
rdns.add(doParse(new Rdn()));
71
while (cur < len) {
72
if (chars[cur] == ',' || chars[cur] == ';') {
73
++cur;
74
rdns.add(0, doParse(new Rdn()));
75
} else {
76
throw new InvalidNameException("Invalid name: " + name);
77
}
78
}
79
return rdns;
80
}
81
82
/*
83
* Parses the DN, if it is known to contain a single RDN.
84
*/
85
Rdn parseRdn() throws InvalidNameException {
86
return parseRdn(new Rdn());
87
}
88
89
/*
90
* Parses the DN, if it is known to contain a single RDN.
91
*/
92
Rdn parseRdn(Rdn rdn) throws InvalidNameException {
93
rdn = doParse(rdn);
94
if (cur < len) {
95
throw new InvalidNameException("Invalid RDN: " + name);
96
}
97
return rdn;
98
}
99
100
/*
101
* Parses the next RDN and returns it. Throws an exception if
102
* none is found. Leading and trailing whitespace is consumed.
103
*/
104
private Rdn doParse(Rdn rdn) throws InvalidNameException {
105
106
while (cur < len) {
107
consumeWhitespace();
108
String attrType = parseAttrType();
109
consumeWhitespace();
110
if (cur >= len || chars[cur] != '=') {
111
throw new InvalidNameException("Invalid name: " + name);
112
}
113
++cur; // consume '='
114
consumeWhitespace();
115
String value = parseAttrValue();
116
consumeWhitespace();
117
118
rdn.put(attrType, Rdn.unescapeValue(value));
119
if (cur >= len || chars[cur] != '+') {
120
break;
121
}
122
++cur; // consume '+'
123
}
124
rdn.sort();
125
return rdn;
126
}
127
128
/*
129
* Returns the attribute type that begins at the next unconsumed
130
* char. No leading whitespace is expected.
131
* This routine is more generous than RFC 2253. It accepts
132
* attribute types composed of any nonempty combination of Unicode
133
* letters, Unicode digits, '.', '-', and internal space characters.
134
*/
135
private String parseAttrType() throws InvalidNameException {
136
137
final int beg = cur;
138
while (cur < len) {
139
char c = chars[cur];
140
if (Character.isLetterOrDigit(c) ||
141
c == '.' ||
142
c == '-' ||
143
c == ' ') {
144
++cur;
145
} else {
146
break;
147
}
148
}
149
// Back out any trailing spaces.
150
while ((cur > beg) && (chars[cur - 1] == ' ')) {
151
--cur;
152
}
153
154
if (beg == cur) {
155
throw new InvalidNameException("Invalid name: " + name);
156
}
157
return new String(chars, beg, cur - beg);
158
}
159
160
/*
161
* Returns the attribute value that begins at the next unconsumed
162
* char. No leading whitespace is expected.
163
*/
164
private String parseAttrValue() throws InvalidNameException {
165
166
if (cur < len && chars[cur] == '#') {
167
return parseBinaryAttrValue();
168
} else if (cur < len && chars[cur] == '"') {
169
return parseQuotedAttrValue();
170
} else {
171
return parseStringAttrValue();
172
}
173
}
174
175
private String parseBinaryAttrValue() throws InvalidNameException {
176
final int beg = cur;
177
++cur; // consume '#'
178
while ((cur < len) &&
179
Character.isLetterOrDigit(chars[cur])) {
180
++cur;
181
}
182
return new String(chars, beg, cur - beg);
183
}
184
185
private String parseQuotedAttrValue() throws InvalidNameException {
186
187
final int beg = cur;
188
++cur; // consume '"'
189
190
while ((cur < len) && chars[cur] != '"') {
191
if (chars[cur] == '\\') {
192
++cur; // consume backslash, then what follows
193
}
194
++cur;
195
}
196
if (cur >= len) { // no closing quote
197
throw new InvalidNameException("Invalid name: " + name);
198
}
199
++cur; // consume closing quote
200
201
return new String(chars, beg, cur - beg);
202
}
203
204
private String parseStringAttrValue() throws InvalidNameException {
205
206
final int beg = cur;
207
int esc = -1; // index of the most recently escaped character
208
209
while ((cur < len) && !atTerminator()) {
210
if (chars[cur] == '\\') {
211
++cur; // consume backslash, then what follows
212
esc = cur;
213
}
214
++cur;
215
}
216
if (cur > len) { // 'twas backslash followed by nothing
217
throw new InvalidNameException("Invalid name: " + name);
218
}
219
220
// Trim off (unescaped) trailing whitespace.
221
int end;
222
for (end = cur; end > beg; end--) {
223
if (!isWhitespace(chars[end - 1]) || (esc == end - 1)) {
224
break;
225
}
226
}
227
return new String(chars, beg, end - beg);
228
}
229
230
private void consumeWhitespace() {
231
while ((cur < len) && isWhitespace(chars[cur])) {
232
++cur;
233
}
234
}
235
236
/*
237
* Returns true if next unconsumed character is one that terminates
238
* a string attribute value.
239
*/
240
private boolean atTerminator() {
241
return (cur < len &&
242
(chars[cur] == ',' ||
243
chars[cur] == ';' ||
244
chars[cur] == '+'));
245
}
246
247
/*
248
* Best guess as to what RFC 2253 means by "whitespace".
249
*/
250
private static boolean isWhitespace(char c) {
251
return (c == ' ' || c == '\r');
252
}
253
}
254
255