14 changed files with 980 additions and 1107 deletions
@ -1,268 +0,0 @@
|
||||
/* |
||||
* Utils.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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; |
||||
|
||||
import android.app.Activity; |
||||
import android.app.AlertDialog; |
||||
import android.content.DialogInterface; |
||||
import android.util.Log; |
||||
import android.view.WindowManager; |
||||
|
||||
import com.codebutler.farebot.card.desfire.DesfireException; |
||||
import com.codebutler.farebot.card.desfire.DesfireFileSettings; |
||||
import com.codebutler.farebot.card.desfire.DesfireProtocol; |
||||
|
||||
import org.w3c.dom.Node; |
||||
|
||||
import java.io.StringWriter; |
||||
import java.util.List; |
||||
|
||||
import javax.xml.transform.OutputKeys; |
||||
import javax.xml.transform.Result; |
||||
import javax.xml.transform.Source; |
||||
import javax.xml.transform.Transformer; |
||||
import javax.xml.transform.TransformerFactory; |
||||
import javax.xml.transform.dom.DOMSource; |
||||
import javax.xml.transform.stream.StreamResult; |
||||
|
||||
public class Utils { |
||||
|
||||
private static final String TAG = Utils.class.getName(); |
||||
|
||||
public static void showError (final Activity activity, Exception ex) { |
||||
Log.e(activity.getClass().getName(), ex.getMessage(), ex); |
||||
new AlertDialog.Builder(activity) |
||||
.setMessage(Utils.getErrorMessage(ex)) |
||||
.show(); |
||||
} |
||||
|
||||
public static void showErrorAndFinish (final Activity activity, Exception ex) { |
||||
try { |
||||
Log.e(activity.getClass().getName(), Utils.getErrorMessage(ex)); |
||||
ex.printStackTrace(); |
||||
|
||||
new AlertDialog.Builder(activity) |
||||
.setMessage(Utils.getErrorMessage(ex)) |
||||
.setCancelable(false) |
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { |
||||
public void onClick(DialogInterface arg0, int arg1) { |
||||
activity.finish(); |
||||
} |
||||
}) |
||||
.show(); |
||||
} catch (WindowManager.BadTokenException unused) { |
||||
/* Ignore... happens if the activity was destroyed */ |
||||
} |
||||
} |
||||
|
||||
public static String getHexString (byte[] b) throws Exception { |
||||
String result = ""; |
||||
for (int i=0; i < b.length; i++) { |
||||
result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 ); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public static String getHexString (byte[] b, String defaultResult) { |
||||
try { |
||||
return getHexString(b); |
||||
} catch (Exception ex) { |
||||
return defaultResult; |
||||
} |
||||
} |
||||
|
||||
public static byte[] hexStringToByteArray (String s) { |
||||
if ((s.length() % 2) != 0) { |
||||
throw new IllegalArgumentException("Bad input string: " + s); |
||||
} |
||||
|
||||
int len = s.length(); |
||||
byte[] data = new byte[len / 2]; |
||||
for (int i = 0; i < len; i += 2) { |
||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) |
||||
+ Character.digit(s.charAt(i+1), 16)); |
||||
} |
||||
return data; |
||||
} |
||||
|
||||
/* |
||||
public static byte[] intToByteArray(int value) { |
||||
return new byte[] { |
||||
(byte)(value >>> 24), |
||||
(byte)(value >>> 16), |
||||
(byte)(value >>> 8), |
||||
(byte)value}; |
||||
} |
||||
*/ |
||||
|
||||
public static int byteArrayToInt(byte[] b) { |
||||
return byteArrayToInt(b, 0); |
||||
} |
||||
|
||||
public static int byteArrayToInt(byte[] b, int offset) { |
||||
return byteArrayToInt(b, offset, b.length); |
||||
} |
||||
|
||||
public static int byteArrayToInt(byte[] b, int offset, int length) { |
||||
return (int) byteArrayToLong(b, offset, length); |
||||
} |
||||
|
||||
public static long byteArrayToLong(byte[] b, int offset, int length) { |
||||
if (b.length < length) |
||||
throw new IllegalArgumentException("length must be less than or equal to b.length"); |
||||
|
||||
long value = 0; |
||||
for (int i = 0; i < length; i++) { |
||||
int shift = (length - 1 - i) * 8; |
||||
value += (b[i + offset] & 0x000000FF) << shift; |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
public static byte[] byteArraySlice(byte[] b, int offset, int length) { |
||||
byte[] ret = new byte[length]; |
||||
for (int i = 0; i < length; i++) |
||||
ret[i] = b[offset+i]; |
||||
return ret; |
||||
} |
||||
|
||||
public static String xmlNodeToString (Node node) throws Exception { |
||||
// The amount of code required to do simple things in Java is incredible.
|
||||
Source source = new DOMSource(node); |
||||
StringWriter stringWriter = new StringWriter(); |
||||
Result result = new StreamResult(stringWriter); |
||||
TransformerFactory factory = TransformerFactory.newInstance(); |
||||
Transformer transformer = factory.newTransformer(); |
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); |
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); |
||||
transformer.setURIResolver(null); |
||||
transformer.transform(source, result); |
||||
return stringWriter.getBuffer().toString(); |
||||
} |
||||
|
||||
public static String getErrorMessage (Throwable ex) { |
||||
String errorMessage = ex.getLocalizedMessage(); |
||||
if (errorMessage == null) |
||||
errorMessage = ex.getMessage(); |
||||
if (errorMessage == null) |
||||
errorMessage = ex.toString(); |
||||
|
||||
if (ex.getCause() != null) { |
||||
String causeMessage = ex.getCause().getLocalizedMessage(); |
||||
if (causeMessage == null) |
||||
causeMessage = ex.getCause().getMessage(); |
||||
if (causeMessage == null) |
||||
causeMessage = ex.getCause().toString(); |
||||
|
||||
if (causeMessage != null) |
||||
errorMessage += ": " + causeMessage; |
||||
} |
||||
|
||||
return errorMessage; |
||||
} |
||||
|
||||
|
||||
public static <T> T findInList(List<T> list, Matcher<T> matcher) { |
||||
for (T item : list) { |
||||
if (matcher.matches(item)) { |
||||
return item; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static interface Matcher<T> { |
||||
public boolean matches(T t); |
||||
} |
||||
|
||||
public static int convertBCDtoInteger(byte data) { |
||||
return (((data & (char)0xF0) >> 4) * 10) + ((data & (char)0x0F)); |
||||
} |
||||
|
||||
public static int getBitsFromInteger(int buffer, int iStartBit, int iLength) { |
||||
return (buffer >> (iStartBit)) & ((char)0xFF >> (8 - iLength)); |
||||
} |
||||
|
||||
/* Based on function from mfocGUI by 'Huuf' (http://www.huuf.info/OV/) */ |
||||
public static int getBitsFromBuffer(byte[] buffer, int iStartBit, int iLength) { |
||||
int iEndBit = iStartBit + iLength - 1; |
||||
int iSByte = iStartBit / 8; |
||||
int iSBit = iStartBit % 8; |
||||
int iEByte = iEndBit / 8; |
||||
int iEBit = iEndBit % 8; |
||||
|
||||
if (iSByte == iEByte) { |
||||
return (int)(((char)buffer[iEByte] >> (7 - iEBit)) & ((char)0xFF >> (8 - iLength))); |
||||
} else { |
||||
int uRet = (((char)buffer[iSByte] & (char)((char)0xFF >> iSBit)) << (((iEByte - iSByte - 1) * 8) + (iEBit + 1))); |
||||
|
||||
for (int i = iSByte + 1; i < iEByte; i++) { |
||||
uRet |= (((char)buffer[i] & (char)0xFF) << (((iEByte - i - 1) * 8) + (iEBit + 1))); |
||||
} |
||||
|
||||
uRet |= (((char)buffer[iEByte] & (char)0xFF)) >> (7 - iEBit); |
||||
|
||||
return uRet; |
||||
} |
||||
} |
||||
|
||||
|
||||
public static DesfireFileSettings selectAppFile(DesfireProtocol tag, int appID, int fileID) { |
||||
try { |
||||
tag.selectApp(appID); |
||||
} catch (DesfireException e) { |
||||
Log.w(TAG,"App not found"); |
||||
return null; |
||||
} |
||||
try { |
||||
return tag.getFileSettings(fileID); |
||||
} catch (DesfireException e) { |
||||
Log.w(TAG,"File not found"); |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public static boolean arrayContains(int[] arr, int item) { |
||||
for (int i: arr) |
||||
if (i==item) |
||||
return true; |
||||
return false; |
||||
} |
||||
|
||||
public static boolean containsAppFile(DesfireProtocol tag, int appID, int fileID) { |
||||
try { |
||||
tag.selectApp(appID); |
||||
} catch (DesfireException e) { |
||||
Log.w(TAG,"App not found"); |
||||
Log.w(TAG, e); |
||||
return false; |
||||
} |
||||
try { |
||||
return arrayContains(tag.getFileList(),fileID); |
||||
} catch (DesfireException e) { |
||||
Log.w(TAG,"File not found"); |
||||
Log.w(TAG, e); |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,226 @@
|
||||
/* |
||||
* Utils.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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 |
||||
|
||||
import android.app.Activity |
||||
import android.app.AlertDialog |
||||
import android.util.Log |
||||
import android.view.WindowManager |
||||
import com.codebutler.farebot.card.desfire.DesfireException |
||||
import com.codebutler.farebot.card.desfire.DesfireFileSettings |
||||
import com.codebutler.farebot.card.desfire.DesfireProtocol |
||||
import org.w3c.dom.Node |
||||
import java.io.StringWriter |
||||
import javax.xml.transform.OutputKeys |
||||
import javax.xml.transform.TransformerFactory |
||||
import javax.xml.transform.dom.DOMSource |
||||
import javax.xml.transform.stream.StreamResult |
||||
import kotlin.experimental.and |
||||
|
||||
class Utils { |
||||
|
||||
companion object { |
||||
private val TAG = Utils::class.java.name |
||||
|
||||
@Suppress("unused") |
||||
fun showError(activity: Activity, ex: Exception) { |
||||
Log.e(activity.javaClass.name, ex.message, ex) |
||||
AlertDialog.Builder(activity) |
||||
.setMessage(getErrorMessage(ex)) |
||||
.show() |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun showErrorAndFinish(activity: Activity, ex: Exception) { |
||||
try { |
||||
Log.e(activity.javaClass.name, getErrorMessage(ex)) |
||||
ex.printStackTrace() |
||||
|
||||
AlertDialog.Builder(activity) |
||||
.setMessage(getErrorMessage(ex)) |
||||
.setCancelable(false) |
||||
.setPositiveButton(android.R.string.ok) { _, _ -> activity.finish() } |
||||
.show() |
||||
} catch (unused: WindowManager.BadTokenException) { |
||||
/* Ignore... happens if the activity was destroyed */ |
||||
} |
||||
|
||||
} |
||||
|
||||
@Throws(Exception::class) |
||||
fun getHexString(b: ByteArray): String { |
||||
var result = "" |
||||
for (i in b.indices) { |
||||
result += ((b[i] and 0xff.toByte()) + 0x100).toString(16).substring(1) |
||||
} |
||||
return result |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun getHexString(b: ByteArray, defaultResult: String): String { |
||||
return try { |
||||
getHexString(b) |
||||
} catch (ex: Exception) { |
||||
defaultResult |
||||
} |
||||
|
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun hexStringToByteArray(s: String): ByteArray { |
||||
if (s.length % 2 != 0) { |
||||
throw IllegalArgumentException("Bad input string: $s") |
||||
} |
||||
|
||||
val len = s.length |
||||
val data = ByteArray(len / 2) |
||||
var i = 0 |
||||
while (i < len) { |
||||
data[i / 2] = ((Character.digit(s[i], 16) shl 4) + Character.digit(s[i + 1], 16)).toByte() |
||||
i += 2 |
||||
} |
||||
return data |
||||
} |
||||
|
||||
@JvmOverloads |
||||
fun byteArrayToInt(b: ByteArray, offset: Int = 0, length: Int = b.size): Int { |
||||
return byteArrayToLong(b, offset, length).toInt() |
||||
} |
||||
|
||||
fun byteArrayToLong(b: ByteArray, offset: Int, length: Int): Long { |
||||
if (b.size < length) |
||||
throw IllegalArgumentException("length must be less than or equal to b.length") |
||||
|
||||
var value: Long = 0 |
||||
for (i in 0 until length) { |
||||
val shift = (length - 1 - i) * 8 |
||||
value += ((b[i + offset].toInt() and 0x000000FF).toLong() shl shift) |
||||
} |
||||
|
||||
return value |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun byteArraySlice(b: ByteArray, offset: Int, length: Int): ByteArray { |
||||
val ret = ByteArray(length) |
||||
for (i in 0 until length) |
||||
ret[i] = b[offset + i] |
||||
return ret |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
@Throws(Exception::class) |
||||
fun xmlNodeToString(node: Node): String { |
||||
// The amount of code required to do simple things in Java is incredible. |
||||
val source = DOMSource(node) |
||||
val stringWriter = StringWriter() |
||||
val result = StreamResult(stringWriter) |
||||
val factory = TransformerFactory.newInstance() |
||||
val transformer = factory.newTransformer() |
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes") |
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2") |
||||
transformer.uriResolver = null |
||||
transformer.transform(source, result) |
||||
return stringWriter.buffer.toString() |
||||
} |
||||
|
||||
fun getErrorMessage(ex: Throwable): String { |
||||
var errorMessage: String? = ex.localizedMessage |
||||
if (errorMessage == null) |
||||
errorMessage = ex.message |
||||
if (errorMessage == null) |
||||
errorMessage = ex.toString() |
||||
|
||||
if (ex.cause != null) { |
||||
var causeMessage: String? = ex.cause!!.localizedMessage |
||||
if (causeMessage == null) |
||||
causeMessage = ex.cause!!.message |
||||
if (causeMessage == null) |
||||
causeMessage = ex.cause.toString() |
||||
|
||||
errorMessage += ": $causeMessage" |
||||
} |
||||
|
||||
return errorMessage |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun <T> findInList(list: List<T>, matcher: Matcher<T>): T? { |
||||
for (item in list) { |
||||
if (matcher.matches(item)) { |
||||
return item |
||||
} |
||||
} |
||||
return null |
||||
} |
||||
|
||||
interface Matcher<T> { |
||||
fun matches(t: T): Boolean |
||||
} |
||||
|
||||
fun selectAppFile(tag: DesfireProtocol, appID: Int, fileID: Int): DesfireFileSettings? { |
||||
try { |
||||
tag.selectApp(appID) |
||||
} catch (e: DesfireException) { |
||||
Log.w(TAG, "App not found") |
||||
return null |
||||
} |
||||
|
||||
return try { |
||||
tag.getFileSettings(fileID) |
||||
} catch (e: DesfireException) { |
||||
Log.w(TAG, "File not found") |
||||
null |
||||
} |
||||
|
||||
} |
||||
|
||||
fun arrayContains(arr: IntArray, item: Int): Boolean { |
||||
for (i in arr) |
||||
if (i == item) |
||||
return true |
||||
return false |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
fun containsAppFile(tag: DesfireProtocol, appID: Int, fileID: Int): Boolean { |
||||
try { |
||||
tag.selectApp(appID) |
||||
} catch (e: DesfireException) { |
||||
Log.w(TAG, "App not found") |
||||
Log.w(TAG, e) |
||||
return false |
||||
} |
||||
|
||||
return try { |
||||
arrayContains(tag.fileList, fileID) |
||||
} catch (e: DesfireException) { |
||||
Log.w(TAG, "File not found") |
||||
Log.w(TAG, e) |
||||
false |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
} |
@ -1,77 +0,0 @@
|
||||
/* |
||||
* DesfireApplication.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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; |
||||
|
||||
public class DesfireApplication implements Parcelable { |
||||
private int mId; |
||||
private DesfireFile[] mFiles; |
||||
|
||||
public DesfireApplication (int id, DesfireFile[] files) { |
||||
mId = id; |
||||
mFiles = files; |
||||
} |
||||
|
||||
public int getId () { |
||||
return mId; |
||||
} |
||||
|
||||
public DesfireFile[] getFiles () { |
||||
return mFiles; |
||||
} |
||||
|
||||
public DesfireFile getFile (int fileId) { |
||||
for (DesfireFile file : mFiles) { |
||||
if (file.getId() == fileId) |
||||
return file; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static final Parcelable.Creator<DesfireApplication> CREATOR = new Parcelable.Creator<DesfireApplication>() { |
||||
public DesfireApplication createFromParcel(Parcel source) { |
||||
int id = source.readInt(); |
||||
|
||||
DesfireFile[] files = new DesfireFile[source.readInt()]; |
||||
source.readTypedArray(files, DesfireFile.CREATOR); |
||||
|
||||
return new DesfireApplication(id, files); |
||||
} |
||||
|
||||
public DesfireApplication[] newArray (int size) { |
||||
return new DesfireApplication[size]; |
||||
} |
||||
}; |
||||
|
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
parcel.writeInt(mId); |
||||
parcel.writeInt(mFiles.length); |
||||
parcel.writeTypedArray(mFiles, flags); |
||||
} |
||||
|
||||
public int describeContents () { |
||||
return 0; |
||||
} |
||||
} |
@ -1,13 +0,0 @@
|
||||
package com.codebutler.farebot.card.desfire; |
||||
|
||||
/** |
||||
* Created by Jakob Wenzel on 16.11.13. |
||||
*/ |
||||
public class DesfireException extends Exception { |
||||
public DesfireException(String message) { |
||||
super(message); |
||||
} |
||||
public DesfireException(Throwable cause) { |
||||
super(cause); |
||||
} |
||||
} |
@ -0,0 +1,9 @@
|
||||
package com.codebutler.farebot.card.desfire |
||||
|
||||
/** |
||||
* Created by Jakob Wenzel on 16.11.13. |
||||
*/ |
||||
class DesfireException : Exception { |
||||
constructor(message: String) : super(message) {} |
||||
constructor(cause: Throwable) : super(cause) {} |
||||
} |
@ -1,135 +0,0 @@
|
||||
/* |
||||
* DesfireFile.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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 org.apache.commons.lang3.ArrayUtils; |
||||
|
||||
import android.os.Parcel; |
||||
import android.os.Parcelable; |
||||
|
||||
import com.codebutler.farebot.card.desfire.DesfireFileSettings.RecordDesfireFileSettings; |
||||
|
||||
public class DesfireFile implements Parcelable { |
||||
private int mId; |
||||
private DesfireFileSettings mSettings; |
||||
private byte[] mData; |
||||
|
||||
public static DesfireFile create (int fileId, DesfireFileSettings fileSettings, byte[] fileData) { |
||||
if (fileSettings instanceof RecordDesfireFileSettings) |
||||
return new RecordDesfireFile(fileId, fileSettings, fileData); |
||||
else |
||||
return new DesfireFile(fileId, fileSettings, fileData); |
||||
} |
||||
|
||||
private DesfireFile (int fileId, DesfireFileSettings fileSettings, byte[] fileData) { |
||||
mId = fileId; |
||||
mSettings = fileSettings; |
||||
mData = fileData; |
||||
} |
||||
|
||||
public DesfireFileSettings getFileSettings () { |
||||
return mSettings; |
||||
} |
||||
|
||||
public int getId () { |
||||
return mId; |
||||
} |
||||
|
||||
public byte[] getData () { |
||||
return mData; |
||||
} |
||||
|
||||
public static final Parcelable.Creator<DesfireFile> CREATOR = new Parcelable.Creator<DesfireFile>() { |
||||
public DesfireFile createFromParcel(Parcel source) { |
||||
int fileId = source.readInt(); |
||||
|
||||
boolean isError = (source.readInt() == 1); |
||||
|
||||
if (!isError) { |
||||
DesfireFileSettings fileSettings = (DesfireFileSettings) source.readParcelable(DesfireFileSettings.class.getClassLoader()); |
||||
int dataLength = source.readInt(); |
||||
byte[] fileData = new byte[dataLength]; |
||||
source.readByteArray(fileData); |
||||
|
||||
return DesfireFile.create(fileId, fileSettings, fileData); |
||||
} else { |
||||
return new InvalidDesfireFile(fileId, source.readString()); |
||||
} |
||||
} |
||||
|
||||
public DesfireFile[] newArray (int size) { |
||||
return new DesfireFile[size]; |
||||
} |
||||
}; |
||||
|
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
parcel.writeInt(mId); |
||||
if (this instanceof InvalidDesfireFile) { |
||||
parcel.writeInt(1); |
||||
parcel.writeString(((InvalidDesfireFile)this).getErrorMessage()); |
||||
} else { |
||||
parcel.writeInt(0); |
||||
parcel.writeParcelable(mSettings, 0); |
||||
parcel.writeInt(mData.length); |
||||
parcel.writeByteArray(mData); |
||||
} |
||||
} |
||||
|
||||
public int describeContents () { |
||||
return 0; |
||||
} |
||||
|
||||
public static class RecordDesfireFile extends DesfireFile { |
||||
private DesfireRecord[] mRecords; |
||||
|
||||
private RecordDesfireFile (int fileId, DesfireFileSettings fileSettings, byte[] fileData) { |
||||
super(fileId, fileSettings, fileData); |
||||
|
||||
RecordDesfireFileSettings settings = (RecordDesfireFileSettings) fileSettings; |
||||
|
||||
DesfireRecord[] records = new DesfireRecord[settings.curRecords]; |
||||
for (int i = 0; i < settings.curRecords; i++) { |
||||
int offset = settings.recordSize * i; |
||||
records[i] = new DesfireRecord(ArrayUtils.subarray(getData(), offset, offset + settings.recordSize)); |
||||
} |
||||
mRecords = records; |
||||
} |
||||
|
||||
public DesfireRecord[] getRecords () { |
||||
return mRecords; |
||||
} |
||||
} |
||||
|
||||
public static class InvalidDesfireFile extends DesfireFile { |
||||
private String mErrorMessage; |
||||
|
||||
public InvalidDesfireFile (int fileId, String errorMessage) { |
||||
super(fileId, null, new byte[0]); |
||||
mErrorMessage = errorMessage; |
||||
} |
||||
|
||||
public String getErrorMessage () { |
||||
return mErrorMessage; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,103 @@
|
||||
/** |
||||
* DesfireFile.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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.card.desfire.DesfireFileSettings.RecordDesfireFileSettings |
||||
import org.apache.commons.lang3.ArrayUtils |
||||
|
||||
|
||||
open class DesfireFile private constructor(val id: Int, private val fileSettings: DesfireFileSettings?, val data: ByteArray) : |
||||
Parcelable { |
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) { |
||||
parcel.writeInt(id) |
||||
if (this is InvalidDesfireFile) { |
||||
parcel.writeInt(1) |
||||
parcel.writeString(this.errorMessage) |
||||
} else { |
||||
parcel.writeInt(0) |
||||
parcel.writeParcelable(fileSettings, 0) |
||||
parcel.writeInt(data.size) |
||||
parcel.writeByteArray(data) |
||||
} |
||||
} |
||||
|
||||
override fun describeContents(): Int { |
||||
return 0 |
||||
} |
||||
|
||||
class RecordDesfireFile(fileId: Int, fileSettings: DesfireFileSettings, fileData: ByteArray) : |
||||
DesfireFile(fileId, fileSettings, fileData) { |
||||
private val records: Array<DesfireRecord?> |
||||
|
||||
init { |
||||
|
||||
val settings = fileSettings as RecordDesfireFileSettings |
||||
|
||||
val records = arrayOfNulls<DesfireRecord>(settings.curRecords) |
||||
for (i in 0 until settings.curRecords) { |
||||
val offset = settings.recordSize * i |
||||
records[i] = DesfireRecord(ArrayUtils.subarray(data, offset, offset + settings.recordSize)) |
||||
} |
||||
this.records = records |
||||
} |
||||
} |
||||
|
||||
class InvalidDesfireFile(fileId: Int, val errorMessage: String?) : DesfireFile(fileId, null, ByteArray(0)) |
||||
|
||||
companion object { |
||||
|
||||
fun create(fileId: Int, fileSettings: DesfireFileSettings, fileData: ByteArray): DesfireFile { |
||||
return (fileSettings as? RecordDesfireFileSettings)?.let { RecordDesfireFile(fileId, it, fileData) } |
||||
?: DesfireFile(fileId, fileSettings, fileData) |
||||
} |
||||
|
||||
@Suppress("unused") |
||||
@JvmField |
||||
val CREATOR: Parcelable.Creator<DesfireFile> = object : Parcelable.Creator<DesfireFile> { |
||||
override fun createFromParcel(source: Parcel): DesfireFile { |
||||
val fileId = source.readInt() |
||||
|
||||
val isError = source.readInt() == 1 |
||||
|
||||
return if (!isError) { |
||||
val fileSettings = |
||||
source.readParcelable<Parcelable>(DesfireFileSettings::class.java.classLoader) as DesfireFileSettings |
||||
val dataLength = source.readInt() |
||||
val fileData = ByteArray(dataLength) |
||||
source.readByteArray(fileData) |
||||
|
||||
create(fileId, fileSettings, fileData) |
||||
} else { |
||||
InvalidDesfireFile(fileId, source.readString()) |
||||
} |
||||
} |
||||
|
||||
override fun newArray(size: Int): Array<DesfireFile?> { |
||||
return arrayOfNulls(size) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,241 +0,0 @@
|
||||
/* |
||||
* DesfireFileSettings.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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 java.io.ByteArrayInputStream; |
||||
|
||||
import org.apache.commons.lang3.ArrayUtils; |
||||
|
||||
import android.os.Parcel; |
||||
import android.os.Parcelable; |
||||
|
||||
import com.codebutler.farebot.Utils; |
||||
|
||||
public abstract class DesfireFileSettings implements Parcelable { |
||||
public final byte fileType; |
||||
public final byte commSetting; |
||||
public final byte[] accessRights; |
||||
|
||||
/* DesfireFile Types */ |
||||
static final byte STANDARD_DATA_FILE = (byte) 0x00; |
||||
static final byte BACKUP_DATA_FILE = (byte) 0x01; |
||||
static final byte VALUE_FILE = (byte) 0x02; |
||||
static final byte LINEAR_RECORD_FILE = (byte) 0x03; |
||||
static final byte CYCLIC_RECORD_FILE = (byte) 0x04; |
||||
|
||||
public static DesfireFileSettings Create (byte[] data) throws DesfireException { |
||||
byte fileType = (byte) data[0]; |
||||
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(data); |
||||
|
||||
if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE) |
||||
return new StandardDesfireFileSettings(stream); |
||||
else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE) |
||||
return new RecordDesfireFileSettings(stream); |
||||
else if (fileType == VALUE_FILE) |
||||
return new ValueDesfireFileSettings(stream); |
||||
else |
||||
throw new DesfireException("Unknown file type: " + Integer.toHexString(fileType)); |
||||
} |
||||
|
||||
private DesfireFileSettings (ByteArrayInputStream stream) { |
||||
fileType = (byte) stream.read(); |
||||
commSetting = (byte) stream.read(); |
||||
|
||||
accessRights = new byte[2]; |
||||
stream.read(accessRights, 0, accessRights.length); |
||||
} |
||||
|
||||
private DesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights) { |
||||
this.fileType = fileType; |
||||
this.commSetting = commSetting; |
||||
this.accessRights = accessRights; |
||||
} |
||||
|
||||
public String getFileTypeName () { |
||||
switch (fileType) { |
||||
case STANDARD_DATA_FILE: |
||||
return "Standard"; |
||||
case BACKUP_DATA_FILE: |
||||
return "Backup"; |
||||
case VALUE_FILE: |
||||
return "Value"; |
||||
case LINEAR_RECORD_FILE: |
||||
return "Linear Record"; |
||||
case CYCLIC_RECORD_FILE: |
||||
return "Cyclic Record"; |
||||
default: |
||||
return "Unknown"; |
||||
} |
||||
} |
||||
|
||||
public static final Parcelable.Creator<DesfireFileSettings> CREATOR = new Parcelable.Creator<DesfireFileSettings>() { |
||||
public DesfireFileSettings createFromParcel(Parcel source) { |
||||
byte fileType = source.readByte(); |
||||
byte commSetting = source.readByte(); |
||||
byte[] accessRights = new byte[source.readInt()]; |
||||
source.readByteArray(accessRights); |
||||
|
||||
if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE) { |
||||
int fileSize = source.readInt(); |
||||
return new StandardDesfireFileSettings(fileType, commSetting, accessRights, fileSize); |
||||
} else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE) { |
||||
int recordSize = source.readInt(); |
||||
int maxRecords = source.readInt(); |
||||
int curRecords = source.readInt(); |
||||
return new RecordDesfireFileSettings(fileType, commSetting, accessRights, recordSize, maxRecords, curRecords); |
||||
} else { |
||||
return new UnsupportedDesfireFileSettings(fileType); |
||||
} |
||||
} |
||||
|
||||
public DesfireFileSettings[] newArray(int size) { |
||||
return new DesfireFileSettings[size]; |
||||
} |
||||
}; |
||||
|
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
parcel.writeByte(fileType); |
||||
parcel.writeByte(commSetting); |
||||
parcel.writeInt(accessRights.length); |
||||
parcel.writeByteArray(accessRights); |
||||
} |
||||
|
||||
public int describeContents () { |
||||
return 0; |
||||
} |
||||
|
||||
public static class StandardDesfireFileSettings extends DesfireFileSettings { |
||||
public final int fileSize; |
||||
|
||||
private StandardDesfireFileSettings (ByteArrayInputStream stream) { |
||||
super(stream); |
||||
byte[] buf = new byte[3]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
fileSize = Utils.byteArrayToInt(buf); |
||||
} |
||||
|
||||
StandardDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int fileSize) { |
||||
super(fileType, commSetting, accessRights); |
||||
this.fileSize = fileSize; |
||||
} |
||||
|
||||
@Override |
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
super.writeToParcel(parcel, flags); |
||||
parcel.writeInt(fileSize); |
||||
} |
||||
} |
||||
|
||||
public static class RecordDesfireFileSettings extends DesfireFileSettings { |
||||
public final int recordSize; |
||||
public final int maxRecords; |
||||
public final int curRecords; |
||||
|
||||
public RecordDesfireFileSettings(ByteArrayInputStream stream) { |
||||
super(stream); |
||||
|
||||
byte[] buf = new byte[3]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
recordSize = Utils.byteArrayToInt(buf); |
||||
|
||||
buf = new byte[3]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
maxRecords = Utils.byteArrayToInt(buf); |
||||
|
||||
buf = new byte[3]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
curRecords = Utils.byteArrayToInt(buf); |
||||
} |
||||
|
||||
RecordDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int recordSize, int maxRecords, int curRecords) { |
||||
super(fileType, commSetting, accessRights); |
||||
this.recordSize = recordSize; |
||||
this.maxRecords = maxRecords; |
||||
this.curRecords = curRecords; |
||||
} |
||||
|
||||
@Override |
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
super.writeToParcel(parcel, flags); |
||||
parcel.writeInt(recordSize); |
||||
parcel.writeInt(maxRecords); |
||||
parcel.writeInt(curRecords); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
public static class ValueDesfireFileSettings extends DesfireFileSettings { |
||||
public final int lowerLimit; |
||||
public final int upperLimit; |
||||
public final int value; |
||||
public final byte limitedCreditEnabled; |
||||
|
||||
public ValueDesfireFileSettings(ByteArrayInputStream stream) { |
||||
super(stream); |
||||
|
||||
byte[] buf = new byte[4]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
lowerLimit = Utils.byteArrayToInt(buf); |
||||
|
||||
buf = new byte[4]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
upperLimit = Utils.byteArrayToInt(buf); |
||||
|
||||
buf = new byte[4]; |
||||
stream.read(buf, 0, buf.length); |
||||
ArrayUtils.reverse(buf); |
||||
value = Utils.byteArrayToInt(buf); |
||||
|
||||
|
||||
buf = new byte[1]; |
||||
stream.read(buf, 0, buf.length); |
||||
limitedCreditEnabled = buf[0]; |
||||
|
||||
//http://www.skyetek.com/docs/m2/desfire.pdf
|
||||
//http://neteril.org/files/M075031_desfire.pdf
|
||||
} |
||||
|
||||
@Override |
||||
public void writeToParcel (Parcel parcel, int flags) { |
||||
super.writeToParcel(parcel, flags); |
||||
parcel.writeInt(lowerLimit); |
||||
parcel.writeInt(upperLimit); |
||||
parcel.writeInt(value); |
||||
parcel.writeByte(limitedCreditEnabled); |
||||
} |
||||
} |
||||
public static class UnsupportedDesfireFileSettings extends DesfireFileSettings { |
||||
public UnsupportedDesfireFileSettings(byte fileType) { |
||||
super(fileType, Byte.MIN_VALUE, new byte[0]); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,247 @@
|
||||
/* |
||||
* DesfireFileSettings.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,173 +0,0 @@
|
||||
/* |
||||
* DesfireManufacturingData.java |
||||
* |
||||
* Copyright (C) 2011 Eric Butler |
||||
* |
||||
* 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.w3c.dom.Element; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
|
||||
public class DesfireManufacturingData implements Parcelable { |
||||
public final int hwVendorID; |
||||
public final int hwType; |
||||
public final int hwSubType; |
||||
public final int hwMajorVersion; |
||||
public final int hwMinorVersion; |
||||
public final int hwStorageSize; |
||||
public final int hwProtocol; |
||||
|
||||
public final int swVendorID; |
||||
public final int swType; |
||||
public final int swSubType; |
||||
public final int swMajorVersion; |
||||