001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.satsa.acl;
028:
029: import java.io.IOException;
030: import java.util.Vector;
031: import com.sun.satsa.util.*;
032: import com.sun.satsa.util.pkcs15.*;
033: import javax.microedition.io.ConnectionNotFoundException;
034:
035: /**
036: * This class provides interface to card file system.
037: */
038: public class AclFileSystem extends FileSystemAbstract {
039:
040: /** Constant defines size of the card buffer */
041: private static final int CARD_BUFFER = 64;
042: /** Constant defines parameters P1, P2 in the apdu command */
043: private static final int P1_P2 = 0x0200;
044:
045: /** Internal buffer for ATR */
046: private byte[] ATR;
047: /** variable defines the unit size in the INS_READ command */
048: private int unitSize = 1;
049: /** DIR file object */
050: public DIRF DIR;
051:
052: /**
053: * Constructs new AclFileSystem object.
054: * @param apdu connection to be used by this object.
055: */
056: public AclFileSystem(Connection apdu) throws IOException {
057: super (apdu);
058: ATR = apdu.getATR();
059: /* Get FCI from previous operation */
060: byte[] prevFCI = apdu.getFCI();
061: /*
062: * It is assumed that in case of work with application the FCI
063: * contains successfull result of the selectApplication operation,
064: * i.e. 0x9000. In case of work with the card file system the FCI
065: * array will contain actual FCI of the master file and length of the
066: * array will be > 2
067: */
068: if (prevFCI.length > 2) {
069: parseATR();
070: apdu.setUnitSize(unitSize);
071: try {
072: DIR = new DIRF(this );
073: DIR.load();
074: } catch (TLVException te) {
075: throw new IOException("Wrong file TLV structure");
076: } catch (IOException ie) {
077: throw new IOException("Wrong DIR file");
078: }
079: } else {
080: apdu.setUnitSize(unitSize);
081: }
082: apdu.setCLAbyte((byte) 0);
083: }
084:
085: /**
086: * Parses the ATR.
087: * At the moment defines a unit size only
088: */
089: private void parseATR() {
090: for (int i = ATR.length - 1; i > 0; i--) {
091: if (((ATR[i] & 0xF0) == 0x70) && ((ATR[i] & 0x0F) >= 2)) {
092: unitSize = (1 << (ATR[i + 2] & 0x07)) / 2;
093: break;
094: }
095: }
096: }
097:
098: /**
099: * Selects file by ID.
100: * @param id file ID
101: * @throws IOException if IOError occurs
102: */
103: public void select(short id) throws IOException {
104:
105: byte[] data = apdu.resetCommand().putShort(id).sendCommand(
106: INS_SELECT, P1_P2);
107:
108: isEFSelected = false;
109: currentFileSize = 0;
110:
111: if (data.length == 2) {
112: return; // FCI is empty
113: }
114:
115: /* parse FCI */
116: if (Utils.getU2(data, data.length - 2) != 0x9000) {
117: throw new IOException("Bad FCI");
118: }
119:
120: isEFSelected = true;
121: }
122:
123: /**
124: * Reads the current EF.
125: * @return array that contains EF body.
126: * @throws IOException if IO error occurs
127: */
128: public byte[] readFile() throws IOException {
129: byte[] data = readData(0, currentFileSize, 0);
130: return data;
131: }
132:
133: /**
134: * Reads part of selected file.
135: * @param offset the offset into data buffer where data should be
136: * placed
137: * @param length read data length (is not used in this class)
138: * @param fileOffset file data offset
139: * @throws IOException if IO error occurs
140: * @return data byte array of the data
141: */
142: public byte[] readData(int offset, int length /* NOT USED */,
143: int fileOffset) throws IOException {
144: Vector v = new Vector();
145: int len = CARD_BUFFER;
146: int readLength = 0;
147: while (true) {
148: byte[] result = apdu.resetCommand().sendCommand(INS_READ,
149: fileOffset / unitSize, len, false);
150: int lastSW = ((result[result.length - 2] & 0xff) << 8)
151: | (result[result.length - 1] & 0xff);
152: if (lastSW != 0x9000) {
153: break;
154: }
155: v.addElement(result);
156: offset += len;
157: fileOffset += len;
158: readLength += result.length - 2;
159: if (result.length - 2 < len) {
160: break;
161: }
162: }
163: byte[] data = new byte[readLength];
164: offset = 0;
165: for (int i = 0; i < v.size(); i++) {
166: byte[] r = (byte[]) v.elementAt(i);
167: System.arraycopy(r, 0, data, offset, r.length - 2);
168: offset += r.length - 2;
169: }
170: currentFileSize = readLength;
171: return data;
172: }
173: }
|