@pagopa/io-react-native-cie 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IoReactNativeCie.podspec +28 -0
- package/LICENSE +201 -0
- package/README.md +406 -0
- package/android/build.gradle +83 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/pagopa/ioreactnativecie/IoReactNativeCieModule.kt +302 -0
- package/android/src/main/java/com/pagopa/ioreactnativecie/IoReactNativeCiePackage.kt +17 -0
- package/android/src/main/java/com/pagopa/ioreactnativecie/cie/Atr.kt +39 -0
- package/android/src/main/java/com/pagopa/ioreactnativecie/cie/CieType.kt +157 -0
- package/ios/CIEType.swift +81 -0
- package/ios/IoReactNativeCie-Bridging-Header.h +2 -0
- package/ios/IoReactNativeCie.mm +43 -0
- package/ios/IoReactNativeCie.swift +227 -0
- package/lib/module/errors.js +2 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/manager/index.js +149 -0
- package/lib/module/manager/index.js.map +1 -0
- package/lib/module/manager/types.js +50 -0
- package/lib/module/manager/types.js.map +1 -0
- package/lib/module/native.js +13 -0
- package/lib/module/native.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/utils/index.js +45 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/errors.d.ts +24 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/manager/index.d.ts +113 -0
- package/lib/typescript/src/manager/index.d.ts.map +1 -0
- package/lib/typescript/src/manager/types.d.ts +83 -0
- package/lib/typescript/src/manager/types.d.ts.map +1 -0
- package/lib/typescript/src/native.d.ts +2 -0
- package/lib/typescript/src/native.d.ts.map +1 -0
- package/lib/typescript/src/utils/index.d.ts +30 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -0
- package/package.json +158 -0
- package/src/errors.ts +32 -0
- package/src/index.ts +14 -0
- package/src/manager/index.ts +167 -0
- package/src/manager/types.ts +94 -0
- package/src/native.ts +18 -0
- package/src/utils/index.ts +42 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.getExtOrDefault = {name ->
|
|
3
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['IoReactNativeCie_' + name]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
dependencies {
|
|
12
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
13
|
+
// noinspection DifferentKotlinGradleVersion
|
|
14
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
apply plugin: "com.android.library"
|
|
20
|
+
apply plugin: "kotlin-android"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def getExtOrIntegerDefault(name) {
|
|
24
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["IoReactNativeCie_" + name]).toInteger()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def supportsNamespace() {
|
|
28
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
29
|
+
def major = parsed[0].toInteger()
|
|
30
|
+
def minor = parsed[1].toInteger()
|
|
31
|
+
|
|
32
|
+
// Namespace support was added in 7.3.0
|
|
33
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
android {
|
|
37
|
+
if (supportsNamespace()) {
|
|
38
|
+
namespace "com.pagopa.ioreactnativecie"
|
|
39
|
+
|
|
40
|
+
sourceSets {
|
|
41
|
+
main {
|
|
42
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
48
|
+
|
|
49
|
+
defaultConfig {
|
|
50
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
51
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
buildTypes {
|
|
55
|
+
release {
|
|
56
|
+
minifyEnabled false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
lintOptions {
|
|
61
|
+
disable "GradleCompatible"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
compileOptions {
|
|
65
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
66
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
repositories {
|
|
71
|
+
mavenCentral()
|
|
72
|
+
google()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
76
|
+
|
|
77
|
+
dependencies {
|
|
78
|
+
implementation "com.facebook.react:react-android"
|
|
79
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
80
|
+
// CIE SDK
|
|
81
|
+
implementation "it.pagopa.io.app.cie:cie:0.1.4"
|
|
82
|
+
}
|
|
83
|
+
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
package com.pagopa.ioreactnativecie
|
|
2
|
+
|
|
3
|
+
import android.util.Base64
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
|
+
import com.facebook.react.bridge.ReactMethod
|
|
8
|
+
import com.facebook.react.bridge.WritableMap
|
|
9
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
10
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
11
|
+
import com.pagopa.ioreactnativecie.cie.Atr
|
|
12
|
+
import it.pagopa.io.app.cie.CieLogger
|
|
13
|
+
import it.pagopa.io.app.cie.CieSDK
|
|
14
|
+
import it.pagopa.io.app.cie.cie.CieAtrCallback
|
|
15
|
+
import it.pagopa.io.app.cie.cie.NfcError
|
|
16
|
+
import it.pagopa.io.app.cie.cie.NfcEvent
|
|
17
|
+
import it.pagopa.io.app.cie.network.NetworkCallback
|
|
18
|
+
import it.pagopa.io.app.cie.network.NetworkError
|
|
19
|
+
import it.pagopa.io.app.cie.nfc.NfcEvents
|
|
20
|
+
import java.net.URL
|
|
21
|
+
|
|
22
|
+
typealias ME = IoReactNativeCieModule.Companion.ModuleException
|
|
23
|
+
|
|
24
|
+
class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
|
|
25
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
26
|
+
|
|
27
|
+
init {
|
|
28
|
+
CieLogger.enabled = BuildConfig.DEBUG
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun getName(): String {
|
|
32
|
+
return NAME
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Lazy value ensures it is initialized with a valid activity when first used.
|
|
37
|
+
*/
|
|
38
|
+
val cieSdk: CieSDK by lazy {
|
|
39
|
+
CieSDK.withContext(currentActivity)
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
@ReactMethod
|
|
43
|
+
fun addListener(eventName: String) {
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@ReactMethod
|
|
47
|
+
fun removeListeners(count: Int) {
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactMethod
|
|
51
|
+
fun hasNfcFeature(promise: Promise) {
|
|
52
|
+
try {
|
|
53
|
+
cieSdk.hasNfcFeature().let {
|
|
54
|
+
promise.resolve(it)
|
|
55
|
+
}
|
|
56
|
+
} catch (e: Exception) {
|
|
57
|
+
ME.UNKNOWN_EXCEPTION.reject(
|
|
58
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@ReactMethod
|
|
64
|
+
fun isNfcEnabled(promise: Promise) {
|
|
65
|
+
try {
|
|
66
|
+
cieSdk.isNfcAvailable().let {
|
|
67
|
+
promise.resolve(it)
|
|
68
|
+
}
|
|
69
|
+
} catch (e: Exception) {
|
|
70
|
+
ME.UNKNOWN_EXCEPTION.reject(
|
|
71
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@ReactMethod
|
|
77
|
+
fun isCieAuthenticationSupported(promise: Promise) {
|
|
78
|
+
cieSdk.isCieAuthenticationSupported().apply {
|
|
79
|
+
promise.resolve(this)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@ReactMethod
|
|
84
|
+
fun openNfcSettings(promise: Promise) {
|
|
85
|
+
try {
|
|
86
|
+
cieSdk.openNfcSettings()
|
|
87
|
+
promise.resolve(null)
|
|
88
|
+
} catch (e: Exception) {
|
|
89
|
+
ME.UNKNOWN_EXCEPTION.reject(
|
|
90
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@ReactMethod
|
|
96
|
+
fun setAlertMessage(key: String, value: String, promise: Promise) {
|
|
97
|
+
// Android does not support alert messages for NFC reading
|
|
98
|
+
promise.resolve(null)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@ReactMethod
|
|
102
|
+
fun setCurrentAlertMessage(value: String, promise: Promise) {
|
|
103
|
+
// Android does not support alert messages for NFC reading
|
|
104
|
+
promise.resolve(null)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@ReactMethod
|
|
108
|
+
fun setCustomIdpUrl(url: String) {
|
|
109
|
+
cieSdk.withCustomIdpUrl(url)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@ReactMethod
|
|
113
|
+
fun startReadingAttributes(
|
|
114
|
+
timeout: Int = 10000,
|
|
115
|
+
promise: Promise,
|
|
116
|
+
) {
|
|
117
|
+
try {
|
|
118
|
+
cieSdk.startReadingCieAtr(timeout, object : NfcEvents {
|
|
119
|
+
override fun event(event: NfcEvent) {
|
|
120
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
121
|
+
.emit(EventType.EVENT.value, WritableNativeMap().apply {
|
|
122
|
+
putString("name", event.name)
|
|
123
|
+
putDouble(
|
|
124
|
+
"progress",
|
|
125
|
+
(event.numeratorForKindOf.toDouble() / NfcEvent.totalKindOfNumeratorEvent.toDouble())
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
override fun error(error: NfcError) {
|
|
131
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
132
|
+
.emit(EventType.ERROR.value, WritableNativeMap().apply {
|
|
133
|
+
putString("name", mapNfcError(error).name)
|
|
134
|
+
error.msg?.let { putString("message", it) }
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
}, object : CieAtrCallback {
|
|
139
|
+
override fun onSuccess(atr: ByteArray) {
|
|
140
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
141
|
+
.emit(EventType.ATTRIBUTES_SUCCESS.value, WritableNativeMap().apply {
|
|
142
|
+
putString("base64", Base64.encodeToString(atr, Base64.DEFAULT))
|
|
143
|
+
putString("type", Atr(atr).getCieType().name)
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
override fun onError(error: NfcError) {
|
|
148
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
149
|
+
.emit(EventType.ERROR.value, WritableNativeMap().apply {
|
|
150
|
+
putString("name", mapNfcError(error).name)
|
|
151
|
+
error.msg?.let { putString("message", it) }
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
promise.resolve(null)
|
|
156
|
+
} catch (e: Exception) {
|
|
157
|
+
ME.UNKNOWN_EXCEPTION.reject(
|
|
158
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@ReactMethod
|
|
164
|
+
fun startReading(
|
|
165
|
+
pin: String,
|
|
166
|
+
authenticationUrl: String,
|
|
167
|
+
timeout: Int = 10000,
|
|
168
|
+
promise: Promise,
|
|
169
|
+
) {
|
|
170
|
+
try {
|
|
171
|
+
cieSdk.setPin(pin)
|
|
172
|
+
} catch (e: Exception) {
|
|
173
|
+
ME.PIN_REGEX_NOT_VALID.reject(
|
|
174
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
175
|
+
)
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
cieSdk.withUrl(URL(authenticationUrl).toString())
|
|
181
|
+
} catch (e: Exception) {
|
|
182
|
+
ME.INVALID_AUTH_URL.reject(promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty()))
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
cieSdk.startReading(timeout, object : NfcEvents {
|
|
188
|
+
override fun event(event: NfcEvent) {
|
|
189
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
190
|
+
.emit(EventType.EVENT.value, WritableNativeMap().apply {
|
|
191
|
+
putString("name", event.name)
|
|
192
|
+
putDouble(
|
|
193
|
+
"progress", (event.numerator.toDouble() / NfcEvent.totalNumeratorEvent.toDouble())
|
|
194
|
+
)
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override fun error(error: NfcError) {
|
|
199
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
200
|
+
.emit(EventType.ERROR.value, WritableNativeMap().apply {
|
|
201
|
+
putString("name", mapNfcError(error).name)
|
|
202
|
+
error.msg?.let { putString("msg", it) }
|
|
203
|
+
error.numberOfAttempts?.let { putInt("attempts", it) }
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
}, object : NetworkCallback {
|
|
208
|
+
override fun onSuccess(url: String) {
|
|
209
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
210
|
+
.emit(EventType.SUCCESS.value, url)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
override fun onError(networkError: NetworkError) {
|
|
214
|
+
this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
215
|
+
.emit(EventType.ERROR.value, WritableNativeMap().apply {
|
|
216
|
+
putString("name", mapNetworkError(networkError).name)
|
|
217
|
+
networkError.msg?.let { putString("message", it) }
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
promise.resolve(null)
|
|
222
|
+
} catch (e: Exception) {
|
|
223
|
+
ME.UNKNOWN_EXCEPTION.reject(
|
|
224
|
+
promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@ReactMethod
|
|
230
|
+
fun stopReading() {
|
|
231
|
+
cieSdk.stopNFCListening()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fun mapNfcError(error: NfcError): ErrorType {
|
|
235
|
+
return when (error) {
|
|
236
|
+
NfcError.NOT_A_CIE -> ErrorType.NOT_A_CIE
|
|
237
|
+
NfcError.TAG_LOST -> ErrorType.TAG_LOST
|
|
238
|
+
NfcError.APDU_ERROR -> ErrorType.APDU_ERROR
|
|
239
|
+
NfcError.EXTENDED_APDU_NOT_SUPPORTED -> ErrorType.APDU_ERROR
|
|
240
|
+
NfcError.WRONG_PIN -> ErrorType.WRONG_PIN
|
|
241
|
+
NfcError.PIN_BLOCKED -> ErrorType.CARD_BLOCKED
|
|
242
|
+
else -> ErrorType.GENERIC_ERROR
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
fun mapNetworkError(error: NetworkError): ErrorType {
|
|
247
|
+
return when (error) {
|
|
248
|
+
NetworkError.NO_INTERNET_CONNECTION -> ErrorType.NO_INTERNET_CONNECTION
|
|
249
|
+
NetworkError.CERTIFICATE_EXPIRED -> ErrorType.CERTIFICATE_EXPIRED
|
|
250
|
+
NetworkError.CERTIFICATE_REVOKED -> ErrorType.CERTIFICATE_REVOKED
|
|
251
|
+
NetworkError.AUTHENTICATION_ERROR -> ErrorType.AUTHENTICATION_ERROR
|
|
252
|
+
else -> ErrorType.GENERIC_ERROR
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
companion object {
|
|
257
|
+
const val NAME = "IoReactNativeCie"
|
|
258
|
+
const val ERROR_USER_INFO_KEY = "error"
|
|
259
|
+
|
|
260
|
+
enum class EventType(val value: String) {
|
|
261
|
+
EVENT("onEvent"),
|
|
262
|
+
ERROR("onError"),
|
|
263
|
+
ATTRIBUTES_SUCCESS("onAttributesSuccess"),
|
|
264
|
+
SUCCESS("onSuccess")
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
enum class ErrorType {
|
|
268
|
+
NOT_A_CIE,
|
|
269
|
+
TAG_LOST,
|
|
270
|
+
APDU_ERROR,
|
|
271
|
+
WRONG_PIN,
|
|
272
|
+
CARD_BLOCKED,
|
|
273
|
+
NO_INTERNET_CONNECTION,
|
|
274
|
+
CERTIFICATE_EXPIRED,
|
|
275
|
+
CERTIFICATE_REVOKED,
|
|
276
|
+
AUTHENTICATION_ERROR,
|
|
277
|
+
GENERIC_ERROR,
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
enum class ModuleException(
|
|
281
|
+
val ex: Exception
|
|
282
|
+
) {
|
|
283
|
+
PIN_REGEX_NOT_VALID(Exception("PIN_REGEX_NOT_VALID")),
|
|
284
|
+
INVALID_AUTH_URL(Exception("INVALID_AUTH_URL")),
|
|
285
|
+
UNKNOWN_EXCEPTION(Exception("UNKNOWN_EXCEPTION"));
|
|
286
|
+
|
|
287
|
+
fun reject(
|
|
288
|
+
promise: Promise, vararg args: Pair<String, String>
|
|
289
|
+
) {
|
|
290
|
+
exMap(*args).let {
|
|
291
|
+
promise.reject(it.first, ex.message, it.second)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private fun exMap(vararg args: Pair<String, String>): Pair<String, WritableMap> {
|
|
296
|
+
val writableMap = WritableNativeMap()
|
|
297
|
+
args.forEach { writableMap.putString(it.first, it.second) }
|
|
298
|
+
return Pair(this.ex.message ?: "UNKNOWN", writableMap)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.pagopa.ioreactnativecie
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IoReactNativeCiePackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
+
return listOf(IoReactNativeCieModule(reactContext))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
15
|
+
return emptyList()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.pagopa.ioreactnativecie.cie
|
|
2
|
+
|
|
3
|
+
import it.pagopa.io.app.cie.CieLogger
|
|
4
|
+
|
|
5
|
+
class Atr(private val atr: ByteArray) {
|
|
6
|
+
fun getCieType(): CieType {
|
|
7
|
+
CieLogger.i("ATR_MAIN:", this.atr.toHexString())
|
|
8
|
+
CieType.entries.forEach {
|
|
9
|
+
CieLogger.i("ATR_OTHE:", it.atr.toHexString())
|
|
10
|
+
if (it.atr.isSubsetInOrder(this.atr))
|
|
11
|
+
return it
|
|
12
|
+
}
|
|
13
|
+
return CieType.UNKNOWN
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private fun ByteArray.toHexString(): String {
|
|
17
|
+
return joinToString(separator = " ") { byte ->
|
|
18
|
+
"0x%02X".format(byte)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private fun ByteArray.isSubsetInOrder(second: ByteArray): Boolean {
|
|
23
|
+
if (this.size > second.size) return false
|
|
24
|
+
var indexSecond = 0
|
|
25
|
+
for (element in this) {
|
|
26
|
+
// Find the element in the second array starting from the current index
|
|
27
|
+
while (indexSecond < second.size && second[indexSecond] != element) {
|
|
28
|
+
indexSecond++
|
|
29
|
+
}
|
|
30
|
+
// If we reach the end of the second array without finding the element, return false
|
|
31
|
+
if (indexSecond == second.size) {
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
// Increment the index for the next iteration
|
|
35
|
+
indexSecond++
|
|
36
|
+
}
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
package com.pagopa.ioreactnativecie.cie
|
|
2
|
+
|
|
3
|
+
/**Returns Cie Manufacturer*/
|
|
4
|
+
enum class CieType(val atr: ByteArray) {
|
|
5
|
+
NXP(
|
|
6
|
+
byteArrayOf(
|
|
7
|
+
0x80.toByte(),
|
|
8
|
+
0x00,
|
|
9
|
+
0x43,
|
|
10
|
+
0x01,
|
|
11
|
+
0xB8.toByte(),
|
|
12
|
+
0x46,
|
|
13
|
+
0x04,
|
|
14
|
+
0x10,
|
|
15
|
+
0x10,
|
|
16
|
+
0x10,
|
|
17
|
+
0x10,
|
|
18
|
+
0x47,
|
|
19
|
+
0x03,
|
|
20
|
+
0x94.toByte(),
|
|
21
|
+
0x01,
|
|
22
|
+
0x80.toByte()
|
|
23
|
+
)
|
|
24
|
+
),
|
|
25
|
+
GEMALTO(
|
|
26
|
+
byteArrayOf(
|
|
27
|
+
0x49, 0x61, 0x73, 0x45, 0x63, 0x63, 0x52, 0x6F, 0x6F, 0x74
|
|
28
|
+
)
|
|
29
|
+
),
|
|
30
|
+
GEMALTO_2(
|
|
31
|
+
byteArrayOf(
|
|
32
|
+
0x47, 0x03, 0x94.toByte(), 0x41, 0xC0.toByte()
|
|
33
|
+
)
|
|
34
|
+
),
|
|
35
|
+
ACTALIS(
|
|
36
|
+
byteArrayOf(
|
|
37
|
+
0x80.toByte(),
|
|
38
|
+
0x00,
|
|
39
|
+
0x43,
|
|
40
|
+
0x01,
|
|
41
|
+
0xB8.toByte(),
|
|
42
|
+
0x46,
|
|
43
|
+
0x04,
|
|
44
|
+
0x10,
|
|
45
|
+
0x10,
|
|
46
|
+
0x10,
|
|
47
|
+
0x10,
|
|
48
|
+
0x47,
|
|
49
|
+
0x03,
|
|
50
|
+
0x94.toByte(),
|
|
51
|
+
0x01,
|
|
52
|
+
0xE0.toByte(),
|
|
53
|
+
0x7F,
|
|
54
|
+
0x66,
|
|
55
|
+
0x08,
|
|
56
|
+
0x02,
|
|
57
|
+
0x02,
|
|
58
|
+
0x04,
|
|
59
|
+
0xD6.toByte(),
|
|
60
|
+
0x02,
|
|
61
|
+
0x02,
|
|
62
|
+
0x07,
|
|
63
|
+
0xE3.toByte(),
|
|
64
|
+
0xE0.toByte(),
|
|
65
|
+
0x10,
|
|
66
|
+
0x02,
|
|
67
|
+
0x02,
|
|
68
|
+
0x01,
|
|
69
|
+
0x04,
|
|
70
|
+
0x02,
|
|
71
|
+
0x02,
|
|
72
|
+
0x00,
|
|
73
|
+
0xE6.toByte(),
|
|
74
|
+
0x02,
|
|
75
|
+
0x02,
|
|
76
|
+
0x00,
|
|
77
|
+
0xE6.toByte(),
|
|
78
|
+
0x02.toByte(),
|
|
79
|
+
0x02,
|
|
80
|
+
0x00,
|
|
81
|
+
0xE6.toByte(),
|
|
82
|
+
0x78,
|
|
83
|
+
0x08,
|
|
84
|
+
0x06,
|
|
85
|
+
0x06,
|
|
86
|
+
0x2B,
|
|
87
|
+
0x81.toByte(),
|
|
88
|
+
0x22,
|
|
89
|
+
0xF8.toByte(),
|
|
90
|
+
0x78,
|
|
91
|
+
0x02
|
|
92
|
+
)
|
|
93
|
+
),
|
|
94
|
+
ST(
|
|
95
|
+
byteArrayOf(
|
|
96
|
+
0x80.toByte(),
|
|
97
|
+
0x00,
|
|
98
|
+
0x43,
|
|
99
|
+
0x01,
|
|
100
|
+
0xB9.toByte(),
|
|
101
|
+
0x46,
|
|
102
|
+
0x04,
|
|
103
|
+
0x00,
|
|
104
|
+
0x00,
|
|
105
|
+
0x00,
|
|
106
|
+
0x10,
|
|
107
|
+
0x47,
|
|
108
|
+
0x03,
|
|
109
|
+
0x94.toByte(),
|
|
110
|
+
0x01,
|
|
111
|
+
0x81.toByte(),
|
|
112
|
+
0x4F,
|
|
113
|
+
0x0C,
|
|
114
|
+
0xA0.toByte(),
|
|
115
|
+
0x00,
|
|
116
|
+
0x00,
|
|
117
|
+
0x00,
|
|
118
|
+
0x95.toByte(),
|
|
119
|
+
0x00,
|
|
120
|
+
0x00,
|
|
121
|
+
0x00,
|
|
122
|
+
0x00,
|
|
123
|
+
0x8A.toByte(),
|
|
124
|
+
0x00,
|
|
125
|
+
0x01,
|
|
126
|
+
0xE0.toByte(),
|
|
127
|
+
0x10,
|
|
128
|
+
0x02,
|
|
129
|
+
0x02,
|
|
130
|
+
0x00,
|
|
131
|
+
0xFF.toByte(),
|
|
132
|
+
0x02,
|
|
133
|
+
0x02,
|
|
134
|
+
0x00,
|
|
135
|
+
0xFF.toByte(),
|
|
136
|
+
0x02,
|
|
137
|
+
0x02,
|
|
138
|
+
0x01,
|
|
139
|
+
0x00,
|
|
140
|
+
0x02,
|
|
141
|
+
0x02,
|
|
142
|
+
0x01,
|
|
143
|
+
0x00,
|
|
144
|
+
0x78,
|
|
145
|
+
0x08,
|
|
146
|
+
0x06,
|
|
147
|
+
0x06,
|
|
148
|
+
0x2B,
|
|
149
|
+
0x81.toByte(),
|
|
150
|
+
0x22,
|
|
151
|
+
0xF8.toByte(),
|
|
152
|
+
0x78,
|
|
153
|
+
0x02
|
|
154
|
+
)
|
|
155
|
+
),
|
|
156
|
+
UNKNOWN(byteArrayOf())
|
|
157
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
enum CIEType: String, Sendable {
|
|
4
|
+
case CIE_Unknown = "UNKNOWN"
|
|
5
|
+
case CIE_Gemalto = "GEMALTO"
|
|
6
|
+
case CIE_Gemalto2 = "GEMALTO_2"
|
|
7
|
+
case CIE_NXP = "NXP"
|
|
8
|
+
case CIE_ST = "ST"
|
|
9
|
+
case CIE_Actalis = "ACTALIS"
|
|
10
|
+
|
|
11
|
+
static func fromATR(_ atr: [UInt8]) -> CIEType {
|
|
12
|
+
let Gemalto_ATR: [UInt8] = [ 0x49, 0x61, 0x73, 0x45, 0x63, 0x63, 0x52, 0x6F, 0x6F, 0x74 ]
|
|
13
|
+
let NXP_ATR: [UInt8] = [0x80, 0x00, 0x43, 0x01, 0xB8, 0x46, 0x04, 0x10, 0x10, 0x10, 0x10, 0x47, 0x03, 0x94 ]
|
|
14
|
+
let Gemalto2_ATR: [UInt8] = [ 0x47, 0x03, 0x94, 0x41, 0xC0 ]
|
|
15
|
+
let ST_ATR: [UInt8] = [ 0x80, 0x00, 0x43, 0x01, 0xB9, 0x46, 0x04, 0x00, 0x00, 0x00, 0x10, 0x47, 0x03, 0x94, 0x01, 0x81, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x01, 0xE0, 0x10, 0x02, 0x02, 0x00, 0xFF, 0x02, 0x02, 0x00, 0xFF, 0x02, 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x00, 0x78, 0x08, 0x06 , 0x06 , 0x2B , 0x81 , 0x22 , 0xF8 , 0x78, 0x02, 0x82, 0x02, 0x90, 0x00 ]
|
|
16
|
+
let Actalis_ATR: [UInt8] = [0x80, 0x00, 0x43, 0x01, 0xB8, 0x46, 0x04, 0x10, 0x10, 0x10, 0x10, 0x47, 0x03, 0x94, 0x01, 0xE0, 0x7F, 0x66, 0x08, 0x02, 0x02, 0x04, 0xD6, 0x02, 0x02, 0x07, 0xE3, 0xE0, 0x10, 0x02, 0x02, 0x01, 0x04, 0x02, 0x02, 0x00, 0xE6, 0x02, 0x02, 0x00, 0xE6, 0x02, 0x02, 0x00, 0xE6, 0x78, 0x08, 0x06, 0x06, 0x2B, 0x81, 0x22, 0xF8, 0x78, 0x02 ]
|
|
17
|
+
|
|
18
|
+
if #available(iOS 16.0, *) {
|
|
19
|
+
if atr.contains(Actalis_ATR) {
|
|
20
|
+
return .CIE_Actalis
|
|
21
|
+
}
|
|
22
|
+
if atr.contains(ST_ATR) {
|
|
23
|
+
return .CIE_ST
|
|
24
|
+
}
|
|
25
|
+
if atr.contains(NXP_ATR) {
|
|
26
|
+
return .CIE_NXP
|
|
27
|
+
}
|
|
28
|
+
if atr.contains(Gemalto2_ATR) {
|
|
29
|
+
return .CIE_Gemalto2
|
|
30
|
+
}
|
|
31
|
+
if atr.contains(Gemalto_ATR) {
|
|
32
|
+
return .CIE_Gemalto
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
let atrStr = atr.hexEncodedString
|
|
37
|
+
if atrStr.contains(Actalis_ATR.hexEncodedString) {
|
|
38
|
+
return .CIE_Actalis
|
|
39
|
+
}
|
|
40
|
+
if atrStr.contains(ST_ATR.hexEncodedString) {
|
|
41
|
+
return .CIE_ST
|
|
42
|
+
}
|
|
43
|
+
if atrStr.contains(NXP_ATR.hexEncodedString) {
|
|
44
|
+
return .CIE_NXP
|
|
45
|
+
}
|
|
46
|
+
if atrStr.contains(Gemalto2_ATR.hexEncodedString) {
|
|
47
|
+
return .CIE_Gemalto
|
|
48
|
+
}
|
|
49
|
+
if atrStr.contains(Gemalto_ATR.hexEncodedString) {
|
|
50
|
+
return .CIE_Gemalto
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return .CIE_Unknown
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
extension Data {
|
|
59
|
+
struct HexEncodingOptions: OptionSet {
|
|
60
|
+
public let rawValue: Int
|
|
61
|
+
|
|
62
|
+
public init(rawValue: Int) {
|
|
63
|
+
self.rawValue = rawValue
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
func hexEncodedString(options: HexEncodingOptions = []) -> String {
|
|
70
|
+
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
|
|
71
|
+
return map { String(format: format, $0) }.joined()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
extension Array<UInt8> {
|
|
77
|
+
|
|
78
|
+
var hexEncodedString: String {
|
|
79
|
+
return Data(self).hexEncodedString()
|
|
80
|
+
}
|
|
81
|
+
}
|