History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/jndi/ldap/BerEncoder.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/jndi/ldap/BerEncoder.java+429−0
@@ -0,0 +1,429 @@
1/*
2 * Copyright (c) 1999, 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
26package com.sun.jndi.ldap;
27
28import java.io.UnsupportedEncodingException;
29
30/**
31 * A BER encoder.
32 *
33 * @author Jagane Sundar
34 * @author Scott Seligman
35 * @author Vincent Ryan
36 */
37public 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;
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}