package org.bbssh.crypto;
import java.io.IOException;
import net.rim.device.api.crypto.CryptoInteger;
import org.bbssh.ssh.v2.BigInteger;
import org.bbssh.util.Tools;
/**
* TypesReader.
*
* @author Christian Plattner, plattner@inf.ethz.ch
* @version $Id: TypesReader.java,v 1.6 2006/08/31 20:04:29 cplattne Exp $
*/
public class TypesReader {
byte[] arr;
int pos = 0;
int max = 0;
public TypesReader(byte[] arr) {
this.arr = arr;
pos = 0;
max = arr.length;
}
public TypesReader(byte[] arr, int off) {
this.arr = arr;
this.pos = off;
this.max = arr.length;
if ((pos < 0) || (pos > arr.length))
throw new IllegalArgumentException("Illegal offset.");
}
public TypesReader(byte[] arr, int off, int len) {
this.arr = arr;
this.pos = off;
this.max = off + len;
if ((pos < 0) || (pos > arr.length))
throw new IllegalArgumentException("Illegal offset.");
if ((max < 0) || (max > arr.length))
throw new IllegalArgumentException("Illegal length.");
}
public int readByte() throws IOException {
if (pos >= max)
throw new IOException("Packet too short.");
return (arr[pos++] & 0xff);
}
public byte[] readBytes(int len) throws IOException {
if ((pos + len) > max)
throw new IOException("Packet too short.");
byte[] res = new byte[len];
System.arraycopy(arr, pos, res, 0, len);
pos += len;
return res;
}
public void readBytes(byte[] dst, int off, int len) throws IOException {
if ((pos + len) > max)
throw new IOException("Packet too short.");
System.arraycopy(arr, pos, dst, off, len);
pos += len;
}
public boolean readBoolean() throws IOException {
if (pos >= max)
throw new IOException("Packet too short.");
return (arr[pos++] != 0);
}
public int readUINT32() throws IOException {
if ((pos + 4) > max)
throw new IOException("Packet too short.");
return ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8)
| (arr[pos++] & 0xff);
}
public long readUINT64() throws IOException {
if ((pos + 8) > max)
throw new IOException("Packet too short.");
long high = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8)
| (arr[pos++] & 0xff); /* sign extension may take place - will be shifted away =) */
long low = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8)
| (arr[pos++] & 0xff); /* sign extension may take place - handle below */
return (high << 32) | (low & 0xffffffffl); /* see Java language spec (15.22.1, 5.6.2) */
}
public BigInteger readMPINT() throws IOException {
BigInteger b;
byte raw[] = readByteString();
if (raw.length == 0)
b = BigInteger.ZERO;
else
b = new BigInteger(raw);
return b;
}
public CryptoInteger readTrimmedCryptoIntegerString() throws IOException {
int len = readUINT32();
if ((len + pos) > max)
throw new IOException("Malformed SSH int/string.");
// Remove padding/sign byte
if (len == 257 && arr[pos] == 0) {
pos++;
len --;
}
// NOTE - crappy RIM CryptoInteger implemnetation is limited to 256 bytes
// so it is possible that if we get a 257+ byte value we're going to throw an exception..
if ((len > 256)) {
throw new IOException("int length too long for RIM CryptoInteger: " + len + " bytes - use BigInteger instead.");
}
CryptoInteger ret = new CryptoInteger(arr, pos, len);
pos += len;
return ret;
}
public byte[] readByteString() throws IOException {
int len = readUINT32();
if ((len + pos) > max)
throw new IOException("Malformed SSH byte string.");
byte[] res = new byte[len];
System.arraycopy(arr, pos, res, 0, len);
pos += len;
return res;
}
public String readString(String charsetName) throws IOException {
int len = readUINT32();
if ((len + pos) > max)
throw new IOException("Malformed SSH string.");
String res = (charsetName == null) ? new String(arr, pos, len) : new String(arr, pos, len, charsetName);
pos += len;
return res;
}
public String readString() throws IOException {
int len = readUINT32();
if ((len + pos) > max)
throw new IOException("Malformed SSH string.");
String res = new String(arr, pos, len);
pos += len;
return res;
}
public String[] readNameList() throws IOException {
return Tools.splitString(readString(), ',');
}
public int remain() {
return max - pos;
}
}