Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/com/sun/jndi/ldap/BerEncoder.java
41161 views
1
/*
2
* Copyright (c) 1999, 2013, 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 com.sun.jndi.ldap;
27
28
import java.io.UnsupportedEncodingException;
29
30
/**
31
* A BER encoder.
32
*
33
* @author Jagane Sundar
34
* @author Scott Seligman
35
* @author Vincent Ryan
36
*/
37
public final class BerEncoder extends Ber {
38
39
private int curSeqIndex;
40
private int seqOffset[];
41
private static final int INITIAL_SEQUENCES = 16;
42
private static final int DEFAULT_BUFSIZE = 1024;
43
44
// When buf is full, expand its size by the following factor.
45
private static final int BUF_GROWTH_FACTOR = 8;
46
47
/**
48
* Creates a BER buffer for encoding.
49
*/
50
public BerEncoder() {
51
this(DEFAULT_BUFSIZE);
52
}
53
54
/**
55
* Creates a BER buffer of a specified size for encoding.
56
* Specify the initial bufsize. Buffer will be expanded as needed.
57
* @param bufsize The number of bytes for the buffer.
58
*/
59
public BerEncoder(int bufsize) {
60
buf = new byte[bufsize];
61
this.bufsize = bufsize;
62
offset = 0;
63
64
seqOffset = new int[INITIAL_SEQUENCES];
65
curSeqIndex = 0;
66
}
67
68
/**
69
* Resets encoder to state when newly constructed. Zeros out
70
* internal data structures.
71
*/
72
public void reset() {
73
while (offset > 0) {
74
buf[--offset] = 0;
75
}
76
while (curSeqIndex > 0) {
77
seqOffset[--curSeqIndex] = 0;
78
}
79
}
80
81
// ------------------ Accessor methods ------------
82
83
/**
84
* Gets the number of encoded bytes in this BER buffer.
85
*/
86
public int getDataLen() {
87
return offset;
88
}
89
90
/**
91
* Gets the buffer that contains the BER encoding. Throws an
92
* exception if unmatched beginSeq() and endSeq() pairs were
93
* encountered. Not entire buffer contains encoded bytes.
94
* Use getDataLen() to determine number of encoded bytes.
95
* Use getBuffer(true) to get rid of excess bytes in array.
96
* @throws IllegalStateException If buffer contains unbalanced sequence.
97
*/
98
public byte[] getBuf() {
99
if (curSeqIndex != 0) {
100
throw new IllegalStateException("BER encode error: Unbalanced SEQUENCEs.");
101
}
102
return buf; // shared buffer, be careful to use this method.
103
}
104
105
/**
106
* Gets the buffer that contains the BER encoding, trimming unused bytes.
107
*
108
* @throws IllegalStateException If buffer contains unbalanced sequence.
109
*/
110
public byte[] getTrimmedBuf() {
111
int len = getDataLen();
112
byte[] trimBuf = new byte[len];
113
114
System.arraycopy(getBuf(), 0, trimBuf, 0, len);
115
return trimBuf;
116
}
117
118
// -------------- encoding methods -------------
119
120
/**
121
* Begin encoding a sequence with a tag.
122
*/
123
public void beginSeq(int tag) {
124
125
// Double the size of the SEQUENCE array if it overflows
126
if (curSeqIndex >= seqOffset.length) {
127
int[] seqOffsetTmp = new int[seqOffset.length * 2];
128
129
for (int i = 0; i < seqOffset.length; i++) {
130
seqOffsetTmp[i] = seqOffset[i];
131
}
132
seqOffset = seqOffsetTmp;
133
}
134
135
encodeByte(tag);
136
seqOffset[curSeqIndex] = offset;
137
138
// Save space for sequence length.
139
// %%% Currently we save enough space for sequences up to 64k.
140
// For larger sequences we'll need to shift the data to the right
141
// in endSeq(). If we could instead pad the length field with
142
// zeros, it would be a big win.
143
ensureFreeBytes(3);
144
offset += 3;
145
146
curSeqIndex++;
147
}
148
149
/**
150
* Terminate a BER sequence.
151
*/
152
public void endSeq() throws EncodeException {
153
curSeqIndex--;
154
if (curSeqIndex < 0) {
155
throw new IllegalStateException("BER encode error: Unbalanced SEQUENCEs.");
156
}
157
158
int start = seqOffset[curSeqIndex] + 3; // index beyond length field
159
int len = offset - start;
160
161
if (len <= 0x7f) {
162
shiftSeqData(start, len, -2);
163
buf[seqOffset[curSeqIndex]] = (byte) len;
164
} else if (len <= 0xff) {
165
shiftSeqData(start, len, -1);
166
buf[seqOffset[curSeqIndex]] = (byte) 0x81;
167
buf[seqOffset[curSeqIndex] + 1] = (byte) len;
168
} else if (len <= 0xffff) {
169
buf[seqOffset[curSeqIndex]] = (byte) 0x82;
170
buf[seqOffset[curSeqIndex] + 1] = (byte) (len >> 8);
171
buf[seqOffset[curSeqIndex] + 2] = (byte) len;
172
} else if (len <= 0xffffff) {
173
shiftSeqData(start, len, 1);
174
buf[seqOffset[curSeqIndex]] = (byte) 0x83;
175
buf[seqOffset[curSeqIndex] + 1] = (byte) (len >> 16);
176
buf[seqOffset[curSeqIndex] + 2] = (byte) (len >> 8);
177
buf[seqOffset[curSeqIndex] + 3] = (byte) len;
178
} else {
179
throw new EncodeException("SEQUENCE too long");
180
}
181
}
182
183
/**
184
* Shifts contents of buf in the range [start,start+len) a specified amount.
185
* Positive shift value means shift to the right.
186
*/
187
private void shiftSeqData(int start, int len, int shift) {
188
if (shift > 0) {
189
ensureFreeBytes(shift);
190
}
191
System.arraycopy(buf, start, buf, start + shift, len);
192
offset += shift;
193
}
194
195
/**
196
* Encode a single byte.
197
*/
198
public void encodeByte(int b) {
199
ensureFreeBytes(1);
200
buf[offset++] = (byte) b;
201
}
202
203
/*
204
private void deleteByte() {
205
offset--;
206
}
207
*/
208
209
210
/*
211
* Encodes an int.
212
*<blockquote><pre>
213
* BER integer ::= 0x02 berlength byte {byte}*
214
*</pre></blockquote>
215
*/
216
public void encodeInt(int i) {
217
encodeInt(i, 0x02);
218
}
219
220
/**
221
* Encodes an int and a tag.
222
*<blockquote><pre>
223
* BER integer w tag ::= tag berlength byte {byte}*
224
*</pre></blockquote>
225
*/
226
public void encodeInt(int i, int tag) {
227
int mask = 0xff800000;
228
int intsize = 4;
229
230
while( (((i & mask) == 0) || ((i & mask) == mask)) && (intsize > 1) ) {
231
intsize--;
232
i <<= 8;
233
}
234
235
encodeInt(i, tag, intsize);
236
}
237
238
//
239
// encodes an int using numbytes for the actual encoding.
240
//
241
private void encodeInt(int i, int tag, int intsize) {
242
243
//
244
// integer ::= 0x02 asnlength byte {byte}*
245
//
246
247
if (intsize > 4) {
248
throw new IllegalArgumentException("BER encode error: INTEGER too long.");
249
}
250
251
ensureFreeBytes(2 + intsize);
252
253
buf[offset++] = (byte) tag;
254
buf[offset++] = (byte) intsize;
255
256
int mask = 0xff000000;
257
258
while (intsize-- > 0) {
259
buf[offset++] = (byte) ((i & mask) >> 24);
260
i <<= 8;
261
}
262
}
263
264
/**
265
* Encodes a boolean.
266
*<blockquote><pre>
267
* BER boolean ::= 0x01 0x01 {0xff|0x00}
268
*</pre></blockquote>
269
*/
270
public void encodeBoolean(boolean b) {
271
encodeBoolean(b, ASN_BOOLEAN);
272
}
273
274
275
/**
276
* Encodes a boolean and a tag
277
*<blockquote><pre>
278
* BER boolean w TAG ::= tag 0x01 {0xff|0x00}
279
*</pre></blockquote>
280
*/
281
public void encodeBoolean(boolean b, int tag) {
282
ensureFreeBytes(3);
283
284
buf[offset++] = (byte) tag;
285
buf[offset++] = 0x01;
286
buf[offset++] = b ? (byte) 0xff : (byte) 0x00;
287
}
288
289
/**
290
* Encodes a string.
291
*<blockquote><pre>
292
* BER string ::= 0x04 strlen byte1 byte2...
293
*</pre></blockquote>
294
* The string is converted into bytes using UTF-8 or ISO-Latin-1.
295
*/
296
public void encodeString(String str, boolean encodeUTF8)
297
throws EncodeException {
298
encodeString(str, ASN_OCTET_STR, encodeUTF8);
299
}
300
301
/**
302
* Encodes a string and a tag.
303
*<blockquote><pre>
304
* BER string w TAG ::= tag strlen byte1 byte2...
305
*</pre></blockquote>
306
*/
307
public void encodeString(String str, int tag, boolean encodeUTF8)
308
throws EncodeException {
309
310
encodeByte(tag);
311
312
int i = 0;
313
int count;
314
byte[] bytes = null;
315
316
if (str == null) {
317
count = 0;
318
} else if (encodeUTF8) {
319
try {
320
bytes = str.getBytes("UTF8");
321
count = bytes.length;
322
} catch (UnsupportedEncodingException e) {
323
throw new EncodeException("UTF8 not available on platform");
324
}
325
} else {
326
try {
327
bytes = str.getBytes("8859_1");
328
count = bytes.length;
329
} catch (UnsupportedEncodingException e) {
330
throw new EncodeException("8859_1 not available on platform");
331
}
332
}
333
334
encodeLength(count);
335
336
ensureFreeBytes(count);
337
while (i < count) {
338
buf[offset++] = bytes[i++];
339
}
340
}
341
342
/**
343
* Encodes a portion of an octet string and a tag.
344
*/
345
public void encodeOctetString(byte tb[], int tag, int tboffset, int length)
346
throws EncodeException {
347
348
encodeByte(tag);
349
encodeLength(length);
350
351
if (length > 0) {
352
ensureFreeBytes(length);
353
System.arraycopy(tb, tboffset, buf, offset, length);
354
offset += length;
355
}
356
}
357
358
/**
359
* Encodes an octet string and a tag.
360
*/
361
public void encodeOctetString(byte tb[], int tag) throws EncodeException {
362
encodeOctetString(tb, tag, 0, tb.length);
363
}
364
365
private void encodeLength(int len) throws EncodeException {
366
ensureFreeBytes(4); // worst case
367
368
if (len < 128) {
369
buf[offset++] = (byte) len;
370
} else if (len <= 0xff) {
371
buf[offset++] = (byte) 0x81;
372
buf[offset++] = (byte) len;
373
} else if (len <= 0xffff) {
374
buf[offset++] = (byte) 0x82;
375
buf[offset++] = (byte) (len >> 8);
376
buf[offset++] = (byte) (len & 0xff);
377
} else if (len <= 0xffffff) {
378
buf[offset++] = (byte) 0x83;
379
buf[offset++] = (byte) (len >> 16);
380
buf[offset++] = (byte) (len >> 8);
381
buf[offset++] = (byte) (len & 0xff);
382
} else {
383
throw new EncodeException("string too long");
384
}
385
}
386
387
/**
388
* Encodes an array of strings.
389
*/
390
public void encodeStringArray(String strs[], boolean encodeUTF8)
391
throws EncodeException {
392
if (strs == null)
393
return;
394
for (int i = 0; i < strs.length; i++) {
395
encodeString(strs[i], encodeUTF8);
396
}
397
}
398
/*
399
private void encodeNull() {
400
401
//
402
// NULL ::= 0x05 0x00
403
//
404
encodeByte(0x05);
405
encodeByte(0x00);
406
}
407
*/
408
409
/**
410
* Ensures that there are at least "len" unused bytes in "buf".
411
* When more space is needed "buf" is expanded by a factor of
412
* BUF_GROWTH_FACTOR, then "len" bytes are added if "buf" still
413
* isn't large enough.
414
*/
415
private void ensureFreeBytes(int len) {
416
if (bufsize - offset < len) {
417
int newsize = bufsize * BUF_GROWTH_FACTOR;
418
if (newsize - offset < len) {
419
newsize += len;
420
}
421
byte newbuf[] = new byte[newsize];
422
// Only copy bytes in the range [0, offset)
423
System.arraycopy(buf, 0, newbuf, 0, offset);
424
425
buf = newbuf;
426
bufsize = newsize;
427
}
428
}
429
}
430
431