📄 berinputstream.java
字号:
/** * * BERInputStream : An implementation of the SerializationManager class that takes * an InputStream and can then be used as a parameter to a codec instance. * The data from the input stream will then be decoded according to the * basic encoding rules. * * @author Ian Ibbotson ( ibbo@k-int.com ) * @version $Id: BERInputStream.java,v 1.10 2001/01/18 14:48:05 ianibbo Exp $ * @see com.k_int.codec.runtime.SerializationManager * * Copyright: Copyright (C) 2000, Knowledge Integration Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the license, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite * 330, Boston, MA 02111-1307, USA. * * */package com.k_int.codec.runtime;import java.math.BigInteger;import java.util.Vector;import java.util.Stack;import java.io.OutputStream;import java.io.InputStream;import java.io.BufferedInputStream;import java.io.StringWriter;import java.io.ByteArrayInputStream;public class BERInputStream implements SerializationManager{ Stack encoding_info = new Stack(); public int tag_class = -1; public int tag_value = -1; public int next_tag_class = -1; public int next_tag_number = -1; public boolean next_is_constructed = false; public boolean next_is_indefinite = false; public int next_length = -1; public boolean is_constructed = false; BufferedInputStream in = null; private base_codec codec_hint = null; public BERInputStream(InputStream from) { this.in = new BufferedInputStream(from); } // Methods from SerializationManager public int getDirection() { return DIRECTION_DECODE; } // Return length of tag encoding public int tag_codec(boolean is_constructed) throws java.io.IOException { // We expect to find the tag (tag_class, tag_value) on the input stream, if so, decode the length // octets also, if not, return -1 // First thing to to is to check that there is actually some more data in this PDU // So, if we are in the middle of decoding something if ( encoding_info.size() > 0 ) { // But there is no more data if ( !moreData() ) { // debug("tag_codec returning -1 whilst expecting ("+tag_class+","+tag_value+") because there is no more data in the constructed type\n"); tag_class = -1; return -1; } } if ( next_tag_class < 0 ) { // Peek at the next tag decodeNextTag(); } // debug("Looking for "+tag_class+" "+tag_value+" next = "+next_tag_class+" "+next_tag_number+"\n"); if ( ( next_tag_class == tag_class ) && ( next_tag_number == tag_value ) ) { // Convert this to log4j // debug("["+next_tag_class+","+next_tag_number+"] cons="+next_is_constructed+" len="+next_length+" is indef:"+next_is_indefinite+"\n"); // Set up to read next tag class next_tag_class = -1; tag_class = -1; // We have a match, so return enc len return next_length; } else { // Did not find the expected tag, reset next tag tag_class = -1; } return -1; } private void decodeNextTag() throws java.io.IOException { byte c = (byte)read(); c &= 0xFF; next_tag_class = c & 0xC0; next_is_constructed = (c & 0x20) != 0; // System.err.println("First byte of tag is "+c); next_tag_number = c & 0x1F; // If there are multiple octets to encode the tag if (next_tag_number == 0x1F) { next_tag_number = 0; do { c = (byte)read(); // Shift value 7 bits left next_tag_number = next_tag_number << 7; // Merge with the octets we just got next_tag_number = ( next_tag_number | ( c & 0x7F ) ); } while ((c & 0x80) != 0); } next_length = decodeLengthOctets(); // debug("decodeNextTag reports next is class:"+next_tag_class+" tag:"+next_tag_number+" len:"+next_length+"\n"); } private int decodeLengthOctets() throws java.io.IOException { int datalen; byte lenpart = (byte)read(); // System.err.println("First len octet is "+lenpart); if ((lenpart & 0x80) == 0) // If bit 8 is 0 { // Single octet length encoding // System.err.println("Single octet length encoding"); datalen = lenpart; next_is_indefinite=false; } else if ( ( lenpart & 0x7F ) == 0 ) // Otherwise we are multiple octets (Maybe 0, which = indefinite) { // System.err.println("Indefinite length encoding"); next_is_indefinite=true; datalen=0; } else { next_is_indefinite=false; // System.err.println("Multiple octet length encoding ("+(lenpart & 0x7F )+"octets)"); lenpart &= 0x7F; datalen = 0; while (lenpart-- > 0) datalen = (datalen << 8) | ((byte)read() & 0xFF); } return datalen; } public String octetstring_codec(Object instance, boolean is_constructed) throws java.io.IOException { String retval = null; // Indefinite length encoding only allowed for constructed types, primitive length 0 must mean // 0 contents octets if ( ( next_length == 0 ) && ( next_is_constructed ) ) { // debug("Indefinite length encoding of octetstring\n"); StringWriter w = new StringWriter(); byte current_octet = (byte)read(); byte next_octet = (byte)read(); while ( ( current_octet != 0 ) && ( next_octet != 0 ) ) { w.write(current_octet); current_octet = next_octet; next_octet = (byte)read(); } retval = w.toString(); } else { // debug("definite length encoding of octetstring ("+next_length+")\n"); byte[] data = new byte[next_length]; int bytes_left_to_read = next_length; int offset = 0; // We may need to call read repeatedly until we have all the data. while ( bytes_left_to_read > 0 ) { int bytes_read = read(data,offset,bytes_left_to_read); bytes_left_to_read -= bytes_read; offset += bytes_read; // debug("Read "+bytes_read+" of "+next_length+" leaving "+bytes_left_to_read+" Next bytes will be at "+offset); } retval = new String(data); } // debug("octetstring_codec returns "+retval+" length="+next_length+"\n"); return retval; } public Boolean boolean_codec(Object instance, boolean is_constructed) throws java.io.IOException { Boolean retval = null; byte val = (byte)read(); if ( val != 0x00) retval = Boolean.TRUE; else retval = Boolean.FALSE; // debug("boolean_codec returns "+retval+" length="+next_length+"\n"); return retval; } public BigInteger integer_codec(Object instance, boolean is_constructed) throws java.io.IOException { byte[] data = new byte[next_length]; int bytes_left_to_read = next_length; int offset = 0; // We may need to call read repeatedly until we have all the data. while ( bytes_left_to_read > 0 ) { int bytes_read = read(data,offset,bytes_left_to_read); bytes_left_to_read -= bytes_read; offset += bytes_read; } // debug("integer returns "+new BigInteger(data)+"\n"); // debug("integer_codec returns ... length="+next_length+"\n"); return new BigInteger(data); } public int[] oid_codec(Object instance, boolean is_constructed) throws java.io.IOException { // System.err.println("Decoding OID, length = "+next_length); int[] retval = new int[next_length+1]; byte[] decode_buffer = new byte[next_length]; int pos=2; int bytes_left_to_read = next_length; int offset = 0; // We may need to call read repeatedly until we have all the data. while ( bytes_left_to_read > 0 ) { int bytes_read = read(decode_buffer,offset,bytes_left_to_read); bytes_left_to_read -= bytes_read; offset += bytes_read; } ByteArrayInputStream bais = new ByteArrayInputStream(decode_buffer); byte octet = (byte)bais.read(); if ( octet >= 80 ) { retval[0]=2; retval[1]=octet-80; } else if ( octet >= 40 ) { retval[0]=1; retval[1]=octet-40; } else { retval[0]=0; retval[1]=octet; } // Split first octet into first 2 elements of OID while ( bais.available() > 0 ) { retval[pos++] = decodeBase128Int(bais); } int[] result = new int[pos]; System.arraycopy(retval,0,result,0,pos); // debug("oid_codec returns "+result+" length="+next_length+"\n"); return result; } public byte[] any_codec(Object instance, boolean is_constructed) throws java.io.IOException { byte[] data = null; if ( ( next_length > 0 ) && ( next_is_constructed ) ) { // debug("definite length encoding of octetstring ("+next_length+")\n"); data = new byte[next_length]; int bytes_left_to_read = next_length; int offset = 0; // We may need to call read repeatedly until we have all the data. while ( bytes_left_to_read > 0 ) { int bytes_read = read(data,offset,bytes_left_to_read); bytes_left_to_read -= bytes_read; offset += bytes_read; // debug("Read "+bytes_read+" of "+next_length+" leaving "+bytes_left_to_read+" Next bytes will be at "+offset); } } else if ( next_length == 0 ) { // Indefinite length encoding // debug("Indefinite length encoding of any data...."); StringWriter w = new StringWriter(); byte current_octet = (byte)read(); byte next_octet = (byte)read(); while ( ( current_octet != 0 ) && ( next_octet != 0 ) ) { w.write(current_octet); current_octet = next_octet; next_octet = (byte)read(); } data = w.toString().getBytes(); } else throw new java.io.IOException("Problem decoding any"); // debug("any returns ... length="+next_length+"\n"); return data; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -