-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathExtensions.kt
More file actions
137 lines (120 loc) · 5.01 KB
/
Copy pathExtensions.kt
File metadata and controls
137 lines (120 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package com.freeraspreactnative.utils
import android.content.pm.PackageInfo
import android.util.Base64
import android.util.Log
import com.aheaditec.talsec_security.security.api.MalwareScanScope
import com.aheaditec.talsec_security.security.api.ReasonMode
import com.aheaditec.talsec_security.security.api.ScopeType
import com.aheaditec.talsec_security.security.api.SuspiciousAppDetectionConfig
import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableArray
import com.freeraspreactnative.exceptions.TalsecException
import com.freeraspreactnative.models.RNPackageInfo
import com.freeraspreactnative.models.RNSuspiciousAppInfo
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.json.JSONException
internal fun ReadableMap.getMapThrowing(key: String): ReadableMap {
return this.getMap(key) ?: throw TalsecException("Key missing in configuration: $key")
}
internal fun ReadableMap.getStringThrowing(key: String): String {
return this.getString(key) ?: throw TalsecException("Key missing in configuration: $key")
}
internal fun ReadableMap.getBooleanSafe(key: String, defaultValue: Boolean = true): Boolean {
if (this.hasKey(key)) {
return this.getBoolean(key)
}
return defaultValue
}
internal inline fun <reified T> ReadableArray.toPrimitiveArray(): Array<T> {
val output = mutableListOf<T>()
for (i in 0 until this.size()) {
val element: T? = when (T::class) {
String::class -> this.getString(i) as T?
Int::class -> this.getInt(i) as T?
Double::class -> this.getDouble(i) as T?
Boolean::class -> this.getBoolean(i) as T?
else -> throw JSONException("Cannot parse JSON array - unsupported type")
}
element?.let(output::add)
}
return output.toTypedArray()
}
internal fun ReadableMap.getArraySafe(key: String): Array<String> {
if (this.hasKey(key)) {
val inputArray = this.getArray(key)!!
return inputArray.toPrimitiveArray()
}
return arrayOf()
}
internal fun ReadableMap.getNestedArraySafe(key: String): Array<Array<String>> {
val outArray = mutableListOf<Array<String>>()
if (this.hasKey(key)) {
val inputArray = this.getArray(key)!!
for (i in 0 until inputArray.size()) {
inputArray.getArray(i)?.let { outArray.add(it.toPrimitiveArray()) }
}
}
return outArray.toTypedArray()
}
/**
* Converts the Talsec's SuspiciousAppInfo to React Native equivalent
*/
internal fun SuspiciousAppInfo.toRNSuspiciousAppInfo(context: ReactContext): RNSuspiciousAppInfo {
return RNSuspiciousAppInfo(
packageInfo = this.packageInfo.toRNPackageInfo(context),
reasons = this.reasons,
permissions = this.permissions
)
}
/**
* Converts the Android's PackageInfo to React Native equivalent
*/
internal fun PackageInfo.toRNPackageInfo(context: ReactContext): RNPackageInfo {
return RNPackageInfo(
packageName = this.packageName,
appName = Utils.getAppName(context, this.applicationInfo),
version = this.versionName,
appIcon = null, // this requires heavier computations, so appIcon has to be retrieved separately
installerStore = Utils.getInstallationSource(context, this.packageName)
)
}
internal fun ReadableMap.toScanScope(): MalwareScanScope {
val scanScope = ScopeType.valueOf(getStringThrowing("scanScope"))
val trustedInstallSources = getArraySafe("trustedInstallSources").toList().ifEmpty { null }
return MalwareScanScope(scanScope, trustedInstallSources)
}
internal fun ReadableMap.toSuspiciousAppDetectionConfig(): SuspiciousAppDetectionConfig {
val packageNames = getArraySafe("packageNames").toSet().ifEmpty { null }
val hashes = getArraySafe("hashes").toSet().ifEmpty { null }
val requestedPermissions = getNestedArraySafe("requestedPermissions").map { it.toSet() }.toSet().ifEmpty { null }
val grantedPermissions = getNestedArraySafe("grantedPermissions").map { it.toSet() }.toSet().ifEmpty { null }
val scanScope = getMapThrowing("scanScope").toScanScope()
val reasonMode = ReasonMode.valueOf(getStringThrowing("reasonMode"))
return SuspiciousAppDetectionConfig(packageNames, hashes, requestedPermissions, grantedPermissions, scanScope, reasonMode)
}
/**
* Convert the Talsec's SuspiciousAppInfo to base64-encoded json array,
* which can be then sent to React Native
*/
internal fun MutableList<SuspiciousAppInfo>.toEncodedWritableArray(context: ReactContext): WritableArray {
val output = Arguments.createArray()
this.forEach { suspiciousAppInfo ->
val rnSuspiciousAppInfo = suspiciousAppInfo.toRNSuspiciousAppInfo(context)
try {
val encodedAppInfo =
Base64.encodeToString(
Json.encodeToString(rnSuspiciousAppInfo).toByteArray(),
Base64.DEFAULT
)
output.pushString(encodedAppInfo)
} catch (e: Exception) {
Log.e("Talsec", "Could not serialize suspicious app data: ${e.message}")
}
}
return output
}