228 lines
7.2 KiB
Kotlin
228 lines
7.2 KiB
Kotlin
/**
|
|
* Utils.kt
|
|
*
|
|
* Copyright (C) 2011 Eric Butler
|
|
* Copyright (C) 2019 <seil0@mosad.xyz>
|
|
*
|
|
* 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
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|