package sos.passportapplet;
/**
* This class saves a log of the instruction sent to the passport as follows:
*
* [session nr byte] [length of data byte] [data] ...
*
* The data is a sequence of the instruction bytes, special cases:
*
* SELECT_FILE: followed by the file identifier (2 bytes)
*
* When the same instruction is called consequtively, only one is recorded,
* but this byte is followed by FF <nr of consequtive calls>
*
* FIXME: When the log exceeds log.length, the counter is wrapped, but this
* breaks the format.
*
* @author ceesb
*
*/
class Log {
private byte[] log;
private short sessionBase;
private short sessionOffset;
private short sessions;
private short insCount;
private short prevIns;
boolean enabled;
Log(FileSystem filesystem) {
filesystem.createFile(FileSystem.SOS_LOG_FID, (short) 128);
log = filesystem.getFile(FileSystem.SOS_LOG_FID);
}
private void writeLogByte(byte b) {
writeLogByteNoUpdate(b);
sessionOffset++;
sessionOffset %= log.length;
}
private void writeLogByteNoUpdate(byte b) {
log[(byte) ((sessionBase + sessionOffset) & 0xff)] = b;
log[(byte) (sessionBase + 1)] = (byte) (sessionOffset & 0xff);
}
public void enabled(boolean v) {
enabled = v;
}
public void newSession() {
if (!enabled) {
return;
}
sessionBase = sessionOffset;
sessionOffset = 0;
writeLogByteNoUpdate((byte) (sessions++ & 0xff));
sessionOffset = 2;
}
public void insByte(byte ins) {
if (!enabled) {
return;
}
if(ins == prevIns) {
writeLogByte((byte)0xff);
writeLogByte((byte)(++insCount & 0xff));
sessionOffset -= 2;
}
else if(insCount > 0) {
sessionOffset += 2;
insCount = 0;
writeLogByte(ins);
}
else {
writeLogByte(ins);
}
prevIns = ins;
}
public void selectFile(short fid) {
if (!enabled) {
return;
}
writeLogByte((byte) ((fid >>> 8) & 0xff));
writeLogByte((byte) (fid & 0xff));
}
}