[Impressum] [E-Mail]

package generated.javacard.copycardMoneySecure.copycard;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;

public abstract class SimpleComm extends Applet {

	public final static byte INIT_INSTRUCTION = 4;

	public final static byte RESUME_INSTRUCTION = 6;

	public final static short ENCBUF_MAXLEN = 28;

	public final static short DECBUF_MAXLEN = 28;

	public final static short APDU_MAXLEN = 255;

	public final static short OUTMSG_MAXLEN = 254;

	protected static Coding coding;

	protected SimpleComm comm;
	private Message inmsg;
	private static Message outmsg;
	protected byte[] encodebuffer; //buffer to encode messages
	protected byte[] decodebuffer; //buffer to decode messages
	private short len = 0;

	//bytes we've already sent/received
	private static short encbuf_sentlen = 0;
	private static short decbuf_receivedlen = 0;

	/**
	 * called by JCRE
	 */
	public void process(APDU apdu) {
		if (selectingApplet())
			return;
		short expected = apdu.setIncomingAndReceive();
		if (expected == 0)
			stop();
		byte ins = apdu.getBuffer()[ISO7816.OFFSET_INS];

		if (ins == RESUME_INSTRUCTION) {
			if (encbuf_sentlen < len)
				sendAPDU(apdu, (short) (len - encbuf_sentlen));
			return;
		}

		//Buffer boundaries shouldn't be overstepped
		if ((short) (decbuf_receivedlen + expected) > DECBUF_MAXLEN) {
			decbuf_receivedlen = 0;
			ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
			return;
		}

		//Handle long APDUs
		Util.arrayCopy(apdu.getBuffer(), ISO7816.OFFSET_CDATA, decodebuffer,
				decbuf_receivedlen, expected);
		decbuf_receivedlen += expected;
		if (apdu.getBuffer()[ISO7816.OFFSET_P1] == 1)
			return;

		if (ins == INIT_INSTRUCTION) {
			appletInitialization(decodebuffer, (short) 0);
			decbuf_receivedlen = 0;
			return;
		}

		Store.reset();
		outmsg = null;
		inmsg = coding.decodeMessage(decodebuffer, (short) 0,
				decbuf_receivedlen);
		decbuf_receivedlen = 0;

		comm.process(inmsg);
		if (outmsg != null) {
			len = coding.encode((Codeable) outmsg, encodebuffer);
			encbuf_sentlen = 0;
			sendAPDU(apdu, len);
		}
	}

	private void sendAPDU(APDU apdu, short rem_len) {
		byte[] buffer = apdu.getBuffer();
		short sendLen = 0;
		if (rem_len > OUTMSG_MAXLEN) {
			buffer[0] = 1;
			Util.arrayCopy(encodebuffer, encbuf_sentlen, buffer, (short) 1,
					OUTMSG_MAXLEN);
			encbuf_sentlen += OUTMSG_MAXLEN;
			sendLen = APDU_MAXLEN;
		} else {
			buffer[0] = 0;
			Util.arrayCopy(encodebuffer, encbuf_sentlen, buffer, (short) 1,
					rem_len);
			encbuf_sentlen = len;
			sendLen = (short) (rem_len + 1);
		}
		apdu.setOutgoingAndSend((short) 0, sendLen);
	}

	public abstract void process(Message msg);
	public abstract void appletInitialization(byte[] buf, short offset);

	protected static void sendMsg(Message msg) {
		outmsg = msg;
	}

	/**
	 * Method to stop processing, signals an ISOError to the JCVM
	 */
	protected void stop() {
		ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
	}

	/**
	 * Constructor. Registers the applet
	 */
	public SimpleComm() {
		comm = this;
		coding = Coding.getInstance();
		//LONGAPDU
		encodebuffer = new byte[ENCBUF_MAXLEN];
		decodebuffer = new byte[DECBUF_MAXLEN];
		Store.initAll();
		register();
	}

	/**
	 * called by Java Card virtual machine.
	 */
	public static void install(byte[] bArray, short bOffset, byte bLength) {
		new Copycard();
	}
}