?? ber.java.svn-base
字號:
}
}
}
public static final void encodeUnsignedInt64(OutputStream os, byte type, long value)
throws IOException
{
int len;
/*
* Truncate "unnecessary" bytes off of the most significant end of this
* 2's complement integer. There should be no sequence of 9
* consecutive 1's or 0's at the most significant end of the
* integer.
*/
for (len = 8; len > 1; len--) {
if (((value >> (8 * (len - 1))) & 0xFF) != 0) {
break;
}
}
if ((( value >> (8 * (len -1))) & 0x080) !=0) {
len++;
}
encodeHeader(os, type, len);
if (len == 9) {
os.write(0);
len--;
}
for (int x=0; x<len; x++) {
os.write((int) (value >> (8 * ((len - 1) - x) & LENMASK)));
}
}
/**
* Decodes a ASN.1 length.
* @param is
* an <code>InputStream</code>
* @return
* the decoded length.
* @throws IOException
*/
public static final int decodeLength(BERInputStream is)
throws IOException
{
return decodeLength(is, true);
}
/**
* Decodes a ASN.1 length.
* @param is
* an <code>InputStream</code>
* @param checkLength
* if <code>false</code> length check is always suppressed.
* @return
* the decoded length.
* @throws IOException
*/
public static final int decodeLength(BERInputStream is, boolean checkLength)
throws IOException
{
int length = 0;
int lengthbyte = is.read();
if ((lengthbyte & ASN_LONG_LEN) > 0) {
lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
if (lengthbyte == 0){
throw new IOException("Indefinite lengths are not supported");
}
if (lengthbyte > 4){
throw new IOException("Data length > 4 bytes are not supported!");
}
for (int i=0; i<lengthbyte; i++) {
int l = is.read() & 0xFF;
length |= (l << (8*((lengthbyte-1)-i)));
}
if (length < 0) {
throw new IOException("SNMP does not support data lengths > 2^31");
}
}
else { /* short asnlength */
length = lengthbyte & 0xFF;
}
/**
* If activated we do a length check here: length > is.available() -> throw
* exception
*/
if (checkLength) {
checkLength(is, length);
}
return length;
}
/**
* Decodes an ASN.1 header for an object with the ID and
* length specified.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* This only works on data types < 30, i.e. no extension octets.
* The maximum length is 0xFFFF;
*
* @param is
* the BERInputStream to decode.
* @param type
* returns the type of the object at the current position in the input
* stream.
* @param checkLength
* if <code>false</code> length check is always suppressed.
* @return
* the decoded length of the object.
* @throws IOException
*/
public static final int decodeHeader(BERInputStream is, MutableByte type,
boolean checkLength)
throws IOException
{
/* this only works on data types < 30, i.e. no extension octets */
byte t = (byte)is.read();
if ((t & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) {
throw new IOException("Cannot process extension IDs"+
getPositionMessage(is));
}
type.setValue(t);
return decodeLength(is, checkLength);
}
/**
* Decodes an ASN.1 header for an object with the ID and
* length specified.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* This only works on data types < 30, i.e. no extension octets.
* The maximum length is 0xFFFF;
*
* @param is
* the BERInputStream to decode.
* @param type
* returns the type of the object at the current position in the input
* stream.
* @return
* the decoded length of the object.
* @throws IOException
*/
public static final int decodeHeader(BERInputStream is, MutableByte type)
throws IOException
{
return decodeHeader(is, type, true);
}
public static final int decodeInteger(BERInputStream is, MutableByte type)
throws IOException
{
int length;
int value = 0;
type.setValue((byte)is.read());
if ((type.value != 0x02) && (type.value != 0x43) &&
(type.value != 0x41)) {
throw new IOException("Wrong ASN.1 type. Not an integer: "+type.value+
getPositionMessage(is));
}
length = decodeLength(is);
if (length > 4) {
throw new IOException("Length greater than 32bit are not supported "+
" for integers: "+getPositionMessage(is));
}
int b = is.read() & 0xFF;
if ((b & 0x80) > 0) {
value = -1; /* integer is negative */
}
while (length-- > 0) {
value = (value << 8) | b;
if (length > 0) {
b = is.read();
}
}
return value;
}
private static String getPositionMessage(BERInputStream is) {
return " at position "+is.getPosition();
}
public static final long decodeUnsignedInteger(BERInputStream is, MutableByte type)
throws IOException
{
int length;
long value = 0;
// get the type
type.setValue((byte)is.read());
if ((type.value != 0x02) && (type.value != 0x43) &&
(type.value != 0x41) && (type.value != 0x42) &&
(type.value != 0x47)) {
throw new IOException("Wrong ASN.1 type. Not an unsigned integer: "+
type.value+
getPositionMessage(is));
}
// pick up the len
length = decodeLength(is);
// check for legal uint size
int b = is.read();
if ((length > 5) || ((length > 4) && (b != 0x00))) {
throw new IOException("Only 32bit unsigned integers are supported"+
getPositionMessage(is));
}
// check for leading 0 octet
if (b == 0x00) {
if (length > 1) {
b = is.read();
}
length--;
}
// calculate the value
for (int i=0; i<length; i++) {
value = (value << 8) | (b & 0xFF);
if (i+1<length) {
b = is.read();
}
}
return value;
}
public static final byte[] decodeString(BERInputStream is, MutableByte type)
throws IOException
{
/*
* ASN.1 octet string ::= primstring | cmpdstring
* primstring ::= 0x04 asnlength byte {byte}*
* cmpdstring ::= 0x24 asnlength string {string}*
* ipaddress ::= 0x40 4 byte byte byte byte
*/
// get the type
type.setValue((byte)is.read());
if ((type.value != BER.OCTETSTRING) && (type.value != 0x24) &&
(type.value != BER.IPADDRESS) && (type.value != BER.OPAQUE) &&
(type.value != BER.BITSTRING) &&
(type.value != 0x45)) {
throw new IOException("Wrong ASN.1 type. Not a string: "+type.value+
getPositionMessage(is));
}
int length = decodeLength(is);
byte[] value = new byte[length];
int pos = 0;
while ((pos < length) && (is.available()>0)) {
int read = is.read(value);
if (read > 0) {
pos += read;
}
else if (read < 0) {
throw new IOException("Wrong string length "+read+" < "+length);
}
}
return value;
}
public static final int[] decodeOID(BERInputStream is, MutableByte type)
throws IOException
{
/*
* ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
* subidentifier ::= {leadingbyte}* lastbyte
* leadingbyte ::= 1 7bitvalue
* lastbyte ::= 0 7bitvalue
*/
int subidentifier;
int length;
// get the type
type.setValue((byte)is.read());
if (type.value != 0x06) {
throw new IOException("Wrong type. Not an OID: "+type.value+
getPositionMessage(is));
}
length = decodeLength(is);
int[] oid = new int[length+2];
/* Handle invalid object identifier encodings of the form 06 00 robustly */
if (length == 0) {
oid[0] = oid[1] = 0;
}
int pos = 1;
while (length > 0){
subidentifier = 0;
int b;
do { /* shift and add in low order 7 bits */
int next = is.read();
if (next < 0) {
throw new IOException("Unexpected end of input stream" +
getPositionMessage(is));
}
b = next & 0xFF;
subidentifier = (subidentifier << 7) + (b & ~ASN_BIT8);
length--;
} while ((length > 0) && ((b & ASN_BIT8) != 0)); /* last byte has high bit clear */
oid[pos++] = subidentifier;
}
/*
* The first two subidentifiers are encoded into the first component
* with the value (X * 40) + Y, where:
* X is the value of the first subidentifier.
* Y is the value of the second subidentifier.
*/
subidentifier = oid[1];
if (subidentifier == 0x2B){
oid[0] = 1;
oid[1] = 3;
}
else {
oid[1] = (subidentifier % 40);
oid[0] = ((subidentifier - oid[1]) / 40);
}
if (pos < 2) {
pos = 2;
}
int[] value = new int[pos];
System.arraycopy(oid, 0, value, 0, pos);
return value;
}
public static final void decodeNull(BERInputStream is, MutableByte type)
throws IOException
{
// get the type
type.setValue((byte)(is.read() & 0xFF));
if ((type.value != (byte)0x05) && (type.value != (byte)0x80) &&
(type.value != (byte)0x81) && (type.value != (byte)0x82)) {
throw new IOException("Wrong ASN.1 type. Is not null: " + type.value+
getPositionMessage(is));
}
int length = decodeLength(is);
if (length != 0) {
throw new IOException("Invalid Null encoding, length is not zero: "+
length+getPositionMessage(is));
}
}
public static final long decodeUnsignedInt64(BERInputStream is, MutableByte type)
throws IOException
{
// get the type
type.setValue((byte)is.read());
if ((type.value != 0x02) && (type.value != 0x46)) {
throw new IOException("Wrong type. Not an integer 64: "+type.value+
getPositionMessage(is));
}
int length = decodeLength(is);
int b = is.read() & 0xFF;
if (length > 9) {
throw new IOException("Invalid 64bit unsigned integer length: "+length+
getPositionMessage(is));
}
// check for leading 0 octet
if (b == 0x00) {
if (length > 1) {
b = is.read();
}
length--;
}
long value = 0;
// calculate the value
for (int i=0; i<length; i++) {
value = (value << 8) | (b & 0xFF);
if (i+1<length) {
b = is.read();
}
}
return value;
}
/**
* Gets the SEQUENCE length checking mode.
* @return
* <code>true</code> if the length of a parsed SEQUENCE should be checked
* against the real length of the objects parsed.
*/
public static boolean isCheckSequenceLength() {
return checkSequenceLength;
}
/**
* Sets the application wide SEQUENCE length checking mode.
* @param checkSequenceLen
* specifies whether he length of a parsed SEQUENCE should be checked
* against the real length of the objects parsed.
*/
public static void setCheckSequenceLength(boolean checkSequenceLen) {
checkSequenceLength = checkSequenceLen;
}
public static void checkSequenceLength(int expectedLength,
BERSerializable sequence)
throws IOException
{
if ((isCheckSequenceLength()) &&
(expectedLength != sequence.getBERPayloadLength())) {
throw new IOException("The actual length of the SEQUENCE object "+
sequence.getClass().getName()+
" is "+sequence.getBERPayloadLength()+", but "+
expectedLength+" was expected");
}
}
public static void checkSequenceLength(int expectedLength, int actualLength,
BERSerializable sequence)
throws IOException
{
if ((isCheckSequenceLength()) &&
(expectedLength != actualLength)) {
throw new IOException("The actual length of the SEQUENCE object "+
sequence.getClass().getName()+
" is "+actualLength+", but "+
expectedLength+" was expected");
}
}
/**
* Checks whether the length of that was encoded is also available from the
* stream.
*
* @param is InputStream
* @param length int
* @throws IOException
* if the bytes that are given in length cannot be read from the input
* stream (without blocking).
*/
private static void checkLength(BERInputStream is, int length) throws
IOException {
if (!checkValueLength) {
return;
}
if ((length < 0) || (length > is.getAvailableBytes())) {
throw new IOException("The encoded length "+
length+
" exceeds the number of bytes left in input"+
getPositionMessage(is)+
" which actually is "+is.getAvailableBytes());
}
}
public boolean isCheckValueLength() {
return checkValueLength;
}
public void setCheckValueLength(boolean checkValueLength) {
BER.checkValueLength = checkValueLength;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -