2019-08-30 14:17:07 +02:00
/ * *
* DesfireFileSettings . kt
2019-08-19 12:42:56 +02:00
*
* Copyright ( C ) 2011 Eric Butler
2019-08-30 14:17:07 +02:00
* Copyright ( C ) 2019 < seil0 @mosad . xyz >
2019-08-19 12:42:56 +02:00
*
* Authors :
* Eric Butler < eric @codebutler . com >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
package com.codebutler.farebot.card.desfire
import android.os.Parcel
import android.os.Parcelable
import com.codebutler.farebot.Utils
import org.apache.commons.lang3.ArrayUtils
import java.io.ByteArrayInputStream
abstract class DesfireFileSettings : Parcelable {
private val fileType : Byte
private val commSetting : Byte
private val accessRights : ByteArray
@Suppress ( " unused " )
val fileTypeName : String
get ( ) {
return when ( fileType ) {
STANDARD _DATA _FILE -> " Standard "
BACKUP _DATA _FILE -> " Backup "
VALUE _FILE -> " Value "
LINEAR _RECORD _FILE -> " Linear Record "
CYCLIC _RECORD _FILE -> " Cyclic Record "
else -> " Unknown "
}
}
private constructor ( stream : ByteArrayInputStream ) {
fileType = stream . read ( ) . toByte ( )
commSetting = stream . read ( ) . toByte ( )
accessRights = ByteArray ( 2 )
stream . read ( accessRights , 0 , accessRights . size )
}
private constructor ( fileType : Byte , commSetting : Byte , accessRights : ByteArray ) {
this . fileType = fileType
this . commSetting = commSetting
this . accessRights = accessRights
}
override fun writeToParcel ( parcel : Parcel , flags : Int ) {
parcel . writeByte ( fileType )
parcel . writeByte ( commSetting )
parcel . writeInt ( accessRights . size )
parcel . writeByteArray ( accessRights )
}
override fun describeContents ( ) : Int {
return 0
}
class StandardDesfireFileSettings : DesfireFileSettings {
private val fileSize : Int
internal constructor ( stream : ByteArrayInputStream ) : super ( stream ) {
val buf = ByteArray ( 3 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
fileSize = Utils . byteArrayToInt ( buf )
}
internal constructor (
fileType : Byte ,
commSetting : Byte ,
accessRights : ByteArray ,
fileSize : Int
) : super ( fileType , commSetting , accessRights ) {
this . fileSize = fileSize
}
override fun writeToParcel ( parcel : Parcel , flags : Int ) {
super . writeToParcel ( parcel , flags )
parcel . writeInt ( fileSize )
}
}
class RecordDesfireFileSettings : DesfireFileSettings {
private val maxRecords : Int
val recordSize : Int
val curRecords : Int
constructor ( stream : ByteArrayInputStream ) : super ( stream ) {
var buf = ByteArray ( 3 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
recordSize = Utils . byteArrayToInt ( buf )
buf = ByteArray ( 3 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
maxRecords = Utils . byteArrayToInt ( buf )
buf = ByteArray ( 3 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
curRecords = Utils . byteArrayToInt ( buf )
}
internal constructor (
fileType : Byte ,
commSetting : Byte ,
accessRights : ByteArray ,
recordSize : Int ,
maxRecords : Int ,
curRecords : Int
) : super ( fileType , commSetting , accessRights ) {
this . recordSize = recordSize
this . maxRecords = maxRecords
this . curRecords = curRecords
}
override fun writeToParcel ( parcel : Parcel , flags : Int ) {
super . writeToParcel ( parcel , flags )
parcel . writeInt ( recordSize )
parcel . writeInt ( maxRecords )
parcel . writeInt ( curRecords )
}
}
class ValueDesfireFileSettings ( stream : ByteArrayInputStream ) : DesfireFileSettings ( stream ) {
private val lowerLimit : Int
private val upperLimit : Int
val value : Int
private val limitedCreditEnabled : Byte
init {
var buf = ByteArray ( 4 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
lowerLimit = Utils . byteArrayToInt ( buf )
buf = ByteArray ( 4 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
upperLimit = Utils . byteArrayToInt ( buf )
buf = ByteArray ( 4 )
stream . read ( buf , 0 , buf . size )
ArrayUtils . reverse ( buf )
value = Utils . byteArrayToInt ( buf )
buf = ByteArray ( 1 )
stream . read ( buf , 0 , buf . size )
limitedCreditEnabled = buf [ 0 ]
//http://www.skyetek.com/docs/m2/desfire.pdf
//http://neteril.org/files/M075031_desfire.pdf
}
override fun writeToParcel ( parcel : Parcel , flags : Int ) {
super . writeToParcel ( parcel , flags )
parcel . writeInt ( lowerLimit )
parcel . writeInt ( upperLimit )
parcel . writeInt ( value )
parcel . writeByte ( limitedCreditEnabled )
}
}
class UnsupportedDesfireFileSettings ( fileType : Byte ) :
DesfireFileSettings ( fileType , java . lang . Byte . MIN _VALUE , ByteArray ( 0 ) )
companion object {
/* DesfireFile Types */
internal const val STANDARD _DATA _FILE = 0x00 . toByte ( )
internal const val BACKUP _DATA _FILE = 0x01 . toByte ( )
internal const val VALUE _FILE = 0x02 . toByte ( )
internal const val LINEAR _RECORD _FILE = 0x03 . toByte ( )
internal const val CYCLIC _RECORD _FILE = 0x04 . toByte ( )
@Throws ( DesfireException :: class )
fun create ( data : ByteArray ) : DesfireFileSettings {
val fileType = data [ 0 ]
val stream = ByteArrayInputStream ( data )
return if ( fileType == STANDARD _DATA _FILE || fileType == BACKUP _DATA _FILE )
StandardDesfireFileSettings ( stream )
else if ( fileType == LINEAR _RECORD _FILE || fileType == CYCLIC _RECORD _FILE )
RecordDesfireFileSettings ( stream )
else if ( fileType == VALUE _FILE )
ValueDesfireFileSettings ( stream )
else
throw DesfireException ( " Unknown file type: " + Integer . toHexString ( fileType . toInt ( ) ) )
}
@Suppress ( " unused " )
@JvmField
val CREATOR : Parcelable . Creator < DesfireFileSettings > = object : Parcelable . Creator < DesfireFileSettings > {
override fun createFromParcel ( source : Parcel ) : DesfireFileSettings {
val fileType = source . readByte ( )
val commSetting = source . readByte ( )
val accessRights = ByteArray ( source . readInt ( ) )
source . readByteArray ( accessRights )
if ( fileType == STANDARD _DATA _FILE || fileType == BACKUP _DATA _FILE ) {
val fileSize = source . readInt ( )
return StandardDesfireFileSettings ( fileType , commSetting , accessRights , fileSize )
} else if ( fileType == LINEAR _RECORD _FILE || fileType == CYCLIC _RECORD _FILE ) {
val recordSize = source . readInt ( )
val maxRecords = source . readInt ( )
val curRecords = source . readInt ( )
return RecordDesfireFileSettings (
fileType ,
commSetting ,
accessRights ,
recordSize ,
maxRecords ,
curRecords
)
} else {
return UnsupportedDesfireFileSettings ( fileType )
}
}
override fun newArray ( size : Int ) : Array < DesfireFileSettings ? > {
return arrayOfNulls ( size )
}
}
}
}