1:
38:
39: package ;
40:
41: import ;
42:
43:
48: public class BEREncoder
49: {
50:
51: private byte[] buffer;
52: private int offset;
53: private int[] sequenceOffset;
54: private int sequenceIndex;
55: private boolean utf8;
56:
57:
61: public BEREncoder(boolean utf8)
62: {
63: this(utf8, 1024);
64: }
65:
66:
71: public BEREncoder(boolean utf8, int initialSize)
72: {
73: this.utf8 = utf8;
74: buffer = new byte[initialSize];
75: offset = 0;
76: sequenceOffset = new int[16];
77: sequenceIndex = 0;
78: }
79:
80:
83: public void reset()
84: {
85: for (int i = 0; i < offset; i++)
86: {
87: buffer[i] = 0;
88: }
89: offset = 0;
90: for (int i = 0; i < sequenceIndex; i++)
91: {
92: sequenceOffset[i] = 0;
93: }
94: sequenceIndex = 0;
95: }
96:
97:
100: public int size()
101: {
102: return offset;
103: }
104:
105:
108: public byte[] toByteArray()
109: {
110: byte[] ret = new byte[offset];
111: System.arraycopy(buffer, 0, ret, 0, offset);
112: return ret;
113: }
114:
115:
116:
117:
121: public void append(boolean value)
122: {
123: append(value, BERConstants.BOOLEAN);
124: }
125:
126:
131: public void append(boolean value, int code)
132: {
133: allocate(3);
134: buffer[offset++] = (byte) code;
135: buffer[offset++] = (byte) 1;
136: buffer[offset++] = value ? (byte) 0xff :(byte) 0;
137: }
138:
139:
140:
141:
145: public void append(int value)
146: {
147: append(value, BERConstants.INTEGER);
148: }
149:
150:
155: public void append(int value, int code)
156: {
157: final int mask = 0xff800000;
158: int len = 4;
159: while (((value & mask) == 0 || (value & mask) == mask) && (len > 1))
160: {
161: len--;
162: value <<= 8;
163: }
164: allocate(len + 2);
165: buffer[offset++] = (byte) code;
166: buffer[offset++] = (byte) len;
167: for (; len > 0; len--)
168: {
169: buffer[offset++] = (byte) ((value & 0xff000000) >> 24);
170: }
171: }
172:
173:
174:
175:
176:
177:
178:
179:
183: public void append(byte[] bytes)
184: throws BERException
185: {
186: append(bytes, BERConstants.OCTET_STRING);
187: }
188:
189:
196: public void append(byte[] bytes, int code)
197: throws BERException
198: {
199: int len = (bytes == null) ? 0 : bytes.length;
200: append(bytes, 0, len, code);
201: }
202:
203: void append(byte[] bytes, int off, int len, int code)
204: throws BERException
205: {
206: allocate(len + 5);
207: buffer[offset++] = (byte) code;
208: appendLength(len);
209: if (len > 0)
210: {
211: System.arraycopy(bytes, off, buffer, offset, len);
212: offset += len;
213: }
214: }
215:
216:
220: public void append(String value)
221: throws BERException
222: {
223: append(value, BERConstants.UTF8_STRING);
224: }
225:
226:
231: public void append(String value, int code)
232: throws BERException
233: {
234: byte[] bytes = null;
235: if (value == null)
236: {
237: bytes = new byte[0];
238: }
239: else
240: {
241: String encoding = utf8 ? "UTF-8" : "ISO-8859-1";
242: try
243: {
244: bytes = value.getBytes(encoding);
245: }
246: catch (UnsupportedEncodingException e)
247: {
248: throw new BERException("JVM does not support " + encoding);
249: }
250: }
251: int len = bytes.length;
252: allocate(len + 5);
253: buffer[offset++] = (byte) code;
254: appendLength(len);
255: System.arraycopy(bytes, 0, buffer, offset, len);
256: offset += len;
257: }
258:
259:
260:
261:
264: public void appendNull()
265: {
266: allocate(2);
267: buffer[offset++] = BERConstants.NULL;
268: buffer[offset++] = (byte) 0;
269: }
270:
271:
274: private void allocate(int len)
275: {
276: if (buffer.length - offset < len)
277: {
278: int size = buffer.length;
279: do
280: {
281: size *= 2;
282: }
283: while (size - offset < len);
284: byte[] ret = new byte[size];
285: System.arraycopy(buffer, 0, ret, 0, offset);
286: buffer = ret;
287: }
288: }
289:
290:
293: private void appendLength(int len)
294: throws BERException
295: {
296: if (len < 0x80)
297: {
298: buffer[offset++] = (byte) len;
299: }
300: else if (len < 0x100)
301: {
302: buffer[offset++] = (byte) 0x81;
303: buffer[offset++] = (byte) len;
304: }
305: else if (len < 0x10000)
306: {
307: buffer[offset++] = (byte) 0x82;
308: buffer[offset++] = (byte)(len >> 0x08);
309: buffer[offset++] = (byte)(len & 0xff);
310: }
311: else if (len < 0x1000000)
312: {
313: buffer[offset++] = (byte) 0x83;
314: buffer[offset++] = (byte)(len >> 0x10);
315: buffer[offset++] = (byte)(len >> 0x08);
316: buffer[offset++] = (byte)(len & 0xff);
317: }
318: else
319: {
320: throw new BERException("Data too long: " + len);
321: }
322: }
323:
324:
328: public void appendFilter(String filter)
329: throws BERException
330: {
331: if (filter == null || filter.length() == 0)
332: {
333: throw new BERException("Empty filter expression");
334: }
335: final byte[] bytes;
336: String charset = utf8 ? "UTF-8" : "ISO-8859-1";
337: try
338: {
339: bytes = filter.getBytes(charset);
340: }
341: catch (UnsupportedEncodingException e)
342: {
343: throw new BERException("JVM does not support " + charset);
344: }
345: appendFilter(bytes, 0);
346: }
347:
348: int appendFilter(final byte[] bytes, int off)
349: throws BERException
350: {
351: int depth = 0;
352: while(off < bytes.length)
353: {
354: switch (bytes[off])
355: {
356: case 0x20:
357: off++;
358: break;
359: case 0x28:
360: depth++;
361: off++;
362: break;
363: case 0x29:
364: depth--;
365: if (depth == 0)
366: {
367: return off + 1;
368: }
369: break;
370: case 0x26:
371: off = appendFilterList(bytes, off + 1,
372: BERConstants.FILTER_AND);
373: break;
374: case 0x2c:
375: off = appendFilterList(bytes, off + 1,
376: BERConstants.FILTER_OR);
377: break;
378: case 0x21:
379: off = appendFilterList(bytes, off + 1,
380: BERConstants.FILTER_NOT);
381: break;
382: default:
383: off = appendFilterItem(bytes, off);
384: }
385: }
386: if (depth != 0)
387: {
388:
389: throw new BERException("Unbalanced parentheses");
390: }
391: return off;
392: }
393:
394: int appendFilterList(final byte[] bytes, int off, int code)
395: throws BERException
396: {
397: BEREncoder sequence = new BEREncoder(utf8);
398: while (off < bytes.length && bytes[off] == '(')
399: {
400: off = sequence.appendFilter(bytes, off);
401: }
402: append(sequence.toByteArray(), code);
403: return off;
404: }
405:
406: int appendFilterItem(final byte[] bytes, int off)
407: throws BERException
408: {
409: int ei = indexOf(bytes,(byte) 0x3d, off);
410: if (ei == -1)
411: {
412: throw new BERException("Missing '='");
413: }
414: int end = ei;
415: int code;
416: BEREncoder item = new BEREncoder(utf8);
417: switch (bytes[ei - 1])
418: {
419: case 0x7e:
420: code = BERConstants.FILTER_APPROX;
421: end--;
422: break;
423: case 0x3e:
424: code = BERConstants.FILTER_GREATER;
425: end--;
426: break;
427: case 0x3c:
428: code = BERConstants.FILTER_LESS;
429: end--;
430: break;
431: case 0x3a:
432: code = BERConstants.FILTER_EXTENSIBLE;
433:
434: break;
435: default:
436: int si = indexOf(bytes,(byte) 0x2a, ei + 1);
437: if (si == -1)
438: {
439: code = BERConstants.FILTER_EQUAL;
440: }
441: else
442: {
443: if (ei + 1 == bytes.length || bytes[ei + 2] == 0x29)
444: {
445: code = BERConstants.FILTER_PRESENT;
446: end--;
447: }
448: else
449: {
450:
451: BEREncoder substring = new BEREncoder(utf8);
452: substring.append(bytes, off, end, BERConstants.OCTET_STRING);
453: end = indexOf(bytes,(byte) 0x29, ei + 1);
454: if (end == -1)
455: {
456: throw new BERException("No terminating ')'");
457: }
458: BEREncoder value = new BEREncoder(utf8);
459: value.append(unencode(bytes, ei + 1, end));
460: substring.append(value.toByteArray(), 48);
461: append(substring.toByteArray(),
462: BERConstants.FILTER_SUBSTRING);
463: off = end;
464: return off;
465: }
466: }
467:
468: }
469: item.append(bytes, off,(end - off), BERConstants.OCTET_STRING);
470: end = indexOf(bytes,(byte) 0x29, ei + 1);
471: if (end == -1)
472: {
473: throw new BERException("No terminating ')'");
474: }
475: if (code != BERConstants.FILTER_PRESENT)
476: {
477: item.append(unencode(bytes, ei + 1, end));
478: }
479: append(item.toByteArray(), code);
480: off = end;
481: return off;
482: }
483:
484:
489: static int indexOf(final byte[] bytes, byte c, int off)
490: {
491: for (int i = off; i < bytes.length; i++)
492: {
493: if (bytes[i] == c)
494: {
495: return i;
496: }
497: else if (bytes[i] == 0x29)
498: {
499: return -1;
500: }
501: }
502: return -1;
503: }
504:
505:
511: static byte[] unencode(final byte[] bytes, int off, int end)
512: throws BERException
513: {
514: byte[] buf = new byte[end - off];
515: int pos = 0;
516: int bsi = indexOf(bytes,(byte) 0x5c, off);
517: while(bsi != -1)
518: {
519: if (bsi + 3 > end)
520: {
521: throw new BERException("Illegal filter value encoding");
522: }
523: int l = bsi - off;
524: System.arraycopy(bytes, off, buf, pos, l);
525: pos += l;
526: int c = Character.digit((char) bytes[bsi + 2], 0x10);
527: c += Character.digit((char) bytes[bsi + 1], 0x10) * 0x10;
528: buf[pos++] = (byte) c;
529: off += l + 3;
530: bsi = indexOf(bytes,(byte) 0x5c, off);
531: }
532: int l = end - off;
533: System.arraycopy(bytes, off, buf, pos, l);
534: pos += l;
535: off += l;
536: if (pos != buf.length)
537: {
538: byte[] swap = new byte[pos];
539: System.arraycopy(buf, 0, swap, 0, pos);
540: buf = swap;
541: }
542: return buf;
543: }
544:
545: }