      1 /**
      2  *  ---------
      3  * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
      4  * |#       #|
      5  * |#       #|  Copyright (c) 1999-2018 CardContact Software & System Consulting
      6  * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
      7  *  ---------
      8  *
      9  *  This file is part of OpenSCDP.
     10  *
     11  *  OpenSCDP is free software; you can redistribute it and/or modify
     12  *  it under the terms of the GNU General Public License version 2 as
     13  *  published by the Free Software Foundation.
     14  *
     15  *  OpenSCDP is distributed in the hope that it will be useful,
     16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18  *  GNU General Public License for more details.
     19  *
     20  *  You should have received a copy of the GNU General Public License
     21  *  along with OpenSCDP; if not, write to the Free Software
     22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     23  *
     24  * @fileoverview Implementation of a ISO 7816-4 file system simulation
     25  */
     26
     27 var APDU                = require('scsh/cardsim/APDU').APDU;
     28 var FCP                 = require('scsh/cardsim/FCP').FCP;
     29 var FSNode              = require('scsh/cardsim/FSNode').FSNode;
     30
     31
     32
     33 /**
     34  * Creates a LinearEF
     35  *
     36  * @class Class implementing linear EFs
     37  * @constructor
     38  * @param {FCP} the file control parameter
     39  * @param {ByteString[]} records the array of records
     40  */
     41 function LinearEF(fcp, records) {
     42 	if (!(fcp instanceof FCP)) {
     43 		throw new GPError("LinearEF", GPError.INVALID_TYPE, APDU.SW_GENERALERROR, "Argument 1 must be of type FCP");
     44 	}
     45 //	print(typeof(records));
     46 	if ((typeof(records) != "undefined") && (records != null) && (typeof(records) != "object")) {
     47 		throw new GPError("LinearEF", GPError.INVALID_TYPE, APDU.SW_GENERALERROR, "Argument 2 must be of type ByteString[]");
     48 	}
     49
     50 	FSNode.call(this, fcp);
     51 	this.records = records;
     52 }
     53
     54 LinearEF.prototype = new FSNode();
     55 LinearEF.prototype.constructor = LinearEF;
     56
     57 exports.LinearEF = LinearEF;
     58
     59
     60
     61 /**
     62  * Reads a record from a linear EF
     63  *
     64  * @param {APDU} apdu the APDU used for reading
     65  * @param {Number} recno the record number
     66  * @param {Number} qualifier the qualifier as encoded in bit b3 - b1 of P1
     67  * @param {Number} length the length in bytes or 0 for all in short APDU or 65536 for all in extended APDUs
     68  * @type ByteString
     69  * @return the data read
     70  */
     71 LinearEF.prototype.readRecord = function(apdu, recno, qualifier, length) {
     72 	if (typeof(recno) != "number") {
     73 		throw new GPError("LinearEF", GPError.INVALID_TYPE, APDU.SW_GENERALERROR, "Record number must be type Number");
     74 	}
     75 	if (typeof(qualifier) != "number") {
     76 		throw new GPError("LinearEF", GPError.INVALID_TYPE, APDU.SW_GENERALERROR, "Qualifier must be type Number");
     77 	}
     78
     79 	if (recno == 0) {
     80 		throw new GPError("LinearEF", GPError.INVALID_DATA, APDU.SW_INCP1P2, "Current record referencing with P1=00 not support");
     81 	}
     82 	recno--;
     83
     84 	if (recno >= this.records.length) {
     85 		throw new GPError("LinearEF", GPError.INVALID_DATA, APDU.SW_RECORDNOTFOUND, "Record number exeeds number of defined records");
     86 	}
     87
     88 	if (qualifier != 4) {
     89 		throw new GPError("LinearEF", GPError.INVALID_DATA, APDU.SW_INCP1P2, "Only absolute record references supported");
     90 	}
     91
     92 	var record = this.records[recno];
     93
     94 	var rlen = length;
     95 	if ((length == 0) || (length == 65536)) {
     96 		rlen = record.length;
     97 		if ((length == 0) && (rlen > 256)) {
     98 			rlen = 256;
     99 		}
    100 	}
    101
    102 	if (rlen > record.length) {
    103 		apdu.setSW(APDU.SW_EOF);
    104 		rlen = record.length;
    105 	} else {
    106 		apdu.setSW(APDU.SW_OK);
    107 	}
    108
    109 	return record.left(rlen);
    110 }
    111