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+
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;
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+}