mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 07:57:30 +00:00
Implement IP2Country
This commit is contained in:
parent
0a9f1f0e23
commit
51f0374109
@ -8,6 +8,7 @@ buildscript {
|
||||
ext.rss_parser_version = "2.0.4"
|
||||
ext.google_services_version = "4.3.3"
|
||||
ext.firebase_messaging_version = "18.0.0"
|
||||
ext.opencsv_version = "4.6"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@ -188,6 +189,7 @@ dependencies {
|
||||
implementation "com.jakewharton.rxbinding3:rxbinding:3.1.0"
|
||||
implementation "com.github.tbruyelle:rxpermissions:0.10.2"
|
||||
implementation "com.github.ybq:Android-SpinKit:1.4.0"
|
||||
implementation "com.opencsv:opencsv:$opencsv_version"
|
||||
}
|
||||
|
||||
def canonicalVersionCode = 52
|
||||
|
116
src/org/thoughtcrime/securesms/loki/utilities/IP2Country.kt
Normal file
116
src/org/thoughtcrime/securesms/loki/utilities/IP2Country.kt
Normal file
@ -0,0 +1,116 @@
|
||||
package org.thoughtcrime.securesms.loki.utilities
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.util.Log
|
||||
import com.opencsv.CSVReader
|
||||
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileReader
|
||||
|
||||
class IP2Country private constructor(private val context: Context) {
|
||||
private val pathsBuiltEventReceiver: BroadcastReceiver
|
||||
private val countryNamesCache = mutableMapOf<String, String>()
|
||||
|
||||
private val ipv4Table by lazy {
|
||||
loadFile("geolite2_country_blocks_ipv4.csv")
|
||||
}
|
||||
|
||||
private val countryNamesTable by lazy {
|
||||
loadFile("geolite2_country_locations_english.csv")
|
||||
}
|
||||
|
||||
// region Initialization
|
||||
companion object {
|
||||
|
||||
public lateinit var shared: IP2Country
|
||||
|
||||
public fun configureIfNeeded(context: Context) {
|
||||
if (::shared.isInitialized) { return; }
|
||||
shared = IP2Country(context)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
preloadCountriesIfNeeded()
|
||||
pathsBuiltEventReceiver = object : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
preloadCountriesIfNeeded()
|
||||
}
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(pathsBuiltEventReceiver, IntentFilter("pathsBuilt"))
|
||||
}
|
||||
|
||||
// TODO: Deinit?
|
||||
// endregion
|
||||
|
||||
// region Implementation
|
||||
private fun loadFile(fileName: String): File {
|
||||
val directory = File(context.applicationInfo.dataDir)
|
||||
val file = File(directory, fileName)
|
||||
if (directory.list().contains(fileName)) { return file }
|
||||
val inputStream = context.assets.open("csv/$fileName")
|
||||
val outputStream = FileOutputStream(file)
|
||||
val buffer = ByteArray(1024)
|
||||
while (true) {
|
||||
val count = inputStream.read(buffer)
|
||||
if (count < 0) { break }
|
||||
outputStream.write(buffer, 0, count)
|
||||
}
|
||||
inputStream.close()
|
||||
outputStream.close()
|
||||
return file
|
||||
}
|
||||
|
||||
private fun getCountry(ip: String): String {
|
||||
var truncatedIP = ip
|
||||
fun getCountryInternal(): String {
|
||||
val country = countryNamesCache[ip]
|
||||
if (country != null) { return country }
|
||||
val ipv4TableReader = CSVReader(FileReader(ipv4Table.absoluteFile))
|
||||
val countryNamesTableReader = CSVReader(FileReader(ipv4Table.absoluteFile))
|
||||
var ipv4TableLine = ipv4TableReader.readNext()
|
||||
while (ipv4TableLine != null) {
|
||||
if (!ipv4TableLine[0].startsWith(truncatedIP)) {
|
||||
ipv4TableLine = ipv4TableReader.readNext()
|
||||
continue
|
||||
}
|
||||
val countryID = ipv4TableLine[1]
|
||||
var countryNamesTableLine = countryNamesTableReader.readNext()
|
||||
while (countryNamesTableLine != null) {
|
||||
if (countryNamesTableLine[0] != countryID) {
|
||||
countryNamesTableLine = countryNamesTableReader.readNext()
|
||||
continue
|
||||
}
|
||||
@Suppress("NAME_SHADOWING") val country = countryNamesTableLine[5]
|
||||
countryNamesCache[ip] = country
|
||||
return country
|
||||
}
|
||||
}
|
||||
if (truncatedIP.contains(".") && !truncatedIP.endsWith(".")) { // The fuzziest we want to go is xxx.x
|
||||
truncatedIP.dropLast(1)
|
||||
if (truncatedIP.endsWith(".")) { truncatedIP.dropLast(1) }
|
||||
return getCountryInternal()
|
||||
} else {
|
||||
return "Unknown Country"
|
||||
}
|
||||
}
|
||||
return getCountryInternal()
|
||||
}
|
||||
|
||||
private fun preloadCountriesIfNeeded() {
|
||||
Thread {
|
||||
val path = OnionRequestAPI.paths.firstOrNull() ?: return@Thread
|
||||
path.forEach { snode ->
|
||||
getCountry(snode.ip) // Preload if needed
|
||||
}
|
||||
Log.d("Loki", "Finished preloading onion request path countries.")
|
||||
}.start()
|
||||
}
|
||||
// endregion
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user