      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 FSNode              = require('scsh/cardsim/FSNode').FSNode;
     29 var FileSystemIdObject  = require('scsh/cardsim/FileSystemIdObject').FileSystemIdObject;
     30
     31
     32
     33 /**
     34  * Creates a Dedicated File (DF)
     35  *
     36  * <p>The constructor supports as argument a list of child elements</p>
     37  *
     38  * @class Class implementing dedicated files
     39  * @constructor
     40  * @param {FCP} the file control parameter
     41  */
     42 function DF(fcp) {
     43 	this.childs = new Array();
     44 	this.fidmap = new Array();
     45 	this.sfimap = new Array();
     46 	this.aidmap = new Array();
     47 	this.meta = new Array();
     48
     49 	FSNode.call(this, fcp);
     50
     51 	if (arguments.length > 1) {
     52 		for (var i = 1; i < arguments.length; i++) {
     53 			var arg = arguments[i];
     54 			this.add(arg);
     55 		}
     56 	}
     57 }
     58
     59 DF.prototype = new FSNode();
     60 DF.prototype.constructor = DF;
     61
     62 exports.DF = DF;
     63
     64
     65 /**
     66  * Adds a new child node to the DF
     67  *
     68  * @param {FSNode} node the node to add
     69  */
     70 DF.prototype.add = function(node) {
     71 	this.childs.push(node);
     72 	node.setParent(this);
     73
     74 	var f = node.getFCP();
     75
     76 	var fid = f.getFID();
     77 	if (fid) {
     78 		if (this.fidmap[fid]) {
     79 			throw new GPError("DF", GPError.INVALID_DATA, APDU.SW_FILEEXISTS, "Duplicate file identifier " + fid);
     80 		}
     81 		this.fidmap[fid] = node;
     82 	}
     83
     84 	if (node.isDF()) {
     85 		var aid = f.getAID();
     86 		if (aid) {
     87 			if (this.aidmap[aid]) {
     88 				throw new GPError("DF", GPError.INVALID_DATA, APDU.SW_FILEEXISTS, "Duplicate application identifier " + aid);
     89 			}
     90 			this.aidmap[aid] = node;
     91 		}
     92 	} else {
     93 		var sfi = f.getSFI();
     94 //		print("Found SFI " + sfi);
     95 		if (typeof(sfi) != "undefined") {
     96 			if (this.sfimap[sfi]) {
     97 				throw new GPError("DF", GPError.INVALID_DATA, APDU.SW_FILEEXISTS, "Duplicate short file identifier " + sfi);
     98 			}
     99 			this.sfimap[sfi] = node;
    100 		}
    101 	}
    102
    103 }
    104
    105
    106
    107 /**
    108  * Add meta information to DF
    109  *
    110  * @param {String} name name of meta information
    111  * @param {Object} value value of meta information
    112  */
    113 DF.prototype.addMeta = function(name, value) {
    114 	this.meta[name] = value;
    115 }
    116
    117
    118
    119 /**
    120  * Add object to DF
    121  *
    122  * @param {Object} o object to be added. Must have property type and id.
    123  */
    124 DF.prototype.addObject = function(o) {
    125 	assert((typeof(o) == "object") && (o instanceof FileSystemIdObject), "Argument must be instance of FileSystemIdObject");
    126 	if (typeof(this.meta[o.getType()]) == "undefined") {
    127 		this.meta[o.getType()] = [];
    128 	}
    129 	this.meta[o.getType()][o.getId()] = o;
    130 }
    131
    132
    133
    134 /**
    135  * Select a file contained in the DF using the file identifier
    136  *
    137  * @param {ByteString} the file identifier
    138  * @type FSNode
    139  * @return the found node or undefined
    140  */
    141 DF.prototype.selectByFID = function(fid) {
    142 	return this.fidmap[fid];
    143 }
    144
    145
    146
    147 /**
    148  * Select a file contained in the DF using the short file identifier
    149  *
    150  * @param {Number} the short file identifier
    151  * @type FSNode
    152  * @return the found node or undefined
    153  */
    154 DF.prototype.selectBySFI = function(sfi) {
    155 	return this.sfimap[sfi];
    156 }
    157
    158
    159
    160 /**
    161  * Select a DF contained in the DF using the application identifier
    162  *
    163  * @param {ByteString} the application identifier
    164  * @type FSNode
    165  * @return the found node or undefined
    166  */
    167 DF.prototype.selectByAID = function(aid) {
    168 	return this.aidmap[aid];
    169 }
    170
    171
    172
    173 /**
    174  * Returns true as this is a DF
    175  *
    176  * @type boolean
    177  * @return true this is a DF
    178  */
    179 DF.prototype.isDF = function() {
    180 	return true;
    181 }
    182
    183
    184
    185 /**
    186  * Dump the file system system recursively starting this this node
    187  *
    188  * @param {String} indent the string to prefix the output with
    189  * @type String
    190  * @return the dump
    191  */
    192 DF.prototype.dump = function(indent) {
    193 	if (typeof(indent) == "undefined") {
    194 		indent = "";
    195 	}
    196 	var str = indent + this.toString() + "\n";
    197
    198 	if (this instanceof DF) {
    199 		for (var i in this.meta) {
    200 			str += indent + "  Meta:" + i + "\n";
    201 			if (typeof(this.meta[i]) == "object") {
    202 				for each (var e in this.meta[i]) {
    203 					if (e instanceof FileSystemIdObject) {
    204 						str += indent + "    " + e.toString() + "\n";
    205 					}
    206 				}
    207 			}
    208 		}
    209 	}
    210
    211 	for (var i = 0; i < this.childs.length; i++) {
    212 		var c = this.childs[i];
    213
    214 		if (c instanceof DF) {
    215 			str += c.dump("  " + indent);
    216 		} else {
    217 			str += "  " + indent + c.toString() + "\n";
    218 		}
    219 	}
    220 	return str;
    221 }
    222