Commit 6c1970fe authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch 'master' of https://git.frostnerd.com/PublicAndroidApps/smokescreen into translations

parents 2b954d55 9cd14b49
Pipeline #5833 passed with stages
in 1 minute and 15 seconds
......@@ -120,7 +120,7 @@ dependencies {
implementation 'com.frostnerd.utilskt:preferences:1.5.16' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.28' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.159' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.162' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.18' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.1.5' // https://git.frostnerd.com/AndroidUtils/Adapters
......
......@@ -212,8 +212,8 @@
android:exported="false"/>
<service
android:name=".service.StartStopTileService"
android:label="@string/quicksettings_start_text"
android:icon="@drawable/ic_play"
android:label="@string/app_name"
android:icon="@drawable/ic_mainnotification"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
......
......@@ -56,6 +56,20 @@ class PinActivity: BaseActivity() {
return context.getPreferences().enablePin && (intent == null || !intent.getBooleanExtra("pin_validated", false))
}
fun openAppIntent(context: Context, extras:Bundle? = null):Intent {
return if(shouldValidatePin(context, null)) {
val intent = Intent(context, PinActivity::class.java)
if(intent.extras != null) intent.putExtra("extras", extras)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("pin_type", PinType.APP)
intent
} else {
Intent(context, MainActivity::class.java).apply {
if(extras != null) putExtras(extras)
}
}
}
fun askForPin(context: Context, pinType: PinType, extras:Bundle? = null) {
val intent = Intent(context, PinActivity::class.java)
if(intent.extras != null) intent.putExtra("extras", extras)
......
......@@ -178,17 +178,19 @@ class SpeedTestActivity : BaseActivity() {
runOnUiThread {
startTest.text = "0/${testsLeft.size}"
}
var highestLatency = 500
testsLeft.forEach { pendingTest ->
if(testJob?.isCancelled == false) {
pendingTest.started = true
log("Running SpeedTest for ${pendingTest.server.name}")
val res = DnsSpeedTest(pendingTest.server, 500, 750) { line ->
val res = DnsSpeedTest(pendingTest.server, highestLatency, highestLatency+250) { line ->
log(line)
}.runTest(3)
if (res != null) pendingTest.latency = res
else pendingTest.error = true
highestLatency = kotlin.math.max(highestLatency, ((pendingTest.latency ?: 0)*1.25).toInt())
testResults!!.sortBy {
it.latency ?: Integer.MAX_VALUE
}
......
......@@ -69,6 +69,21 @@ interface DnsRuleDao {
@Query("SELECT COUNT(*) FROM DnsRule")
fun getCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1")
fun getActiveCount(): Long
@Query("SELECT host FROM DnsRule WHERE type=255 AND isWildcard=0 AND target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1) ORDER BY RANDOM() LIMIT :count")
fun getRandomNonWildcardWhitelistEntries(count:Int):List<String>
@Query("SELECT COUNT(*) FROM DnsRule WHERE isWildcard=1 AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWildcardCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE isWildcard=1 AND target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWildcardWhitelistCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWhitelistCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE stagingType=0")
fun getNonStagedCount(): Long
......@@ -81,7 +96,7 @@ interface DnsRuleDao {
@Query("SELECT CASE WHEN :type=28 THEN IFNULL(ipv6Target, target) ELSE target END FROM DnsRule d1 WHERE d1.host=:host AND d1.target != '' AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND (SELECT COUNT(*) FROM DnsRule d2 WHERE d2.target='' AND d2.host=:host AND (d2.type = :type OR d2.type=255) AND (d2.importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0)))=0 AND isWildcard=0 LIMIT 1")
fun findRuleTarget(host: String, type: Record.TYPE, useUserRules:Boolean): String?
@Query("SELECT * FROM DnsRule where host=:host AND type=255 AND isWildcard=0 AND target='' AND (importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
@Query("SELECT * FROM DnsRule where host=:host AND type=255 AND isWildcard=0 AND target='' AND (importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1) LIMIT 1")
fun findNonWildcardWhitelistEntry(host:String, useUserRules:Boolean):List<DnsRule>
@Query("SELECT * FROM DnsRule d1 WHERE ((:includeWhitelistEntries=1 AND d1.target == '') OR (:includeNonWhitelistEntries=1 AND d1.target!='')) AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND :host LIKE host AND isWildcard=1")
......
......@@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.database.entities.DnsRule
import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.util.MaxSizeMap
import kotlinx.android.synthetic.main.dialog_create_dnsrule.view.*
import org.minidns.record.Record
import java.net.Inet4Address
......@@ -35,7 +36,7 @@ class DnsRuleDialog(context: Context, dnsRule: DnsRule? = null, onRuleCreated: (
AlertDialog(context, context.getPreferences().theme.dialogStyle) {
private var isWhitelist = false
companion object {
private val matchers = mutableMapOf<String, Matcher>()
private val matchers = MaxSizeMap<String, Matcher>(150, 10)
fun printableHost(host:String): String {
return host.replace("%%", "**").replace("%", "*")
......
......@@ -10,6 +10,7 @@ import android.view.*
import android.widget.Switch
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.Constraints
......@@ -29,6 +30,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.dialog.ExportDnsRulesDialog
import com.frostnerd.smokescreen.dialog.HostSourceRefreshDialog
import com.frostnerd.smokescreen.dialog.NewHostSourceDialog
import com.frostnerd.smokescreen.service.DnsVpnService
import com.frostnerd.smokescreen.service.RuleExportService
import com.frostnerd.smokescreen.service.RuleImportService
import com.frostnerd.smokescreen.util.SpaceItemDecorator
......@@ -213,6 +215,7 @@ class DnsRuleFragment : Fragment() {
GlobalScope.launch {
getDatabase().dnsRuleDao().deleteAllFromSource(it.id)
getDatabase().hostSourceDao().delete(it)
notifyRulesChanged()
}
dialog.dismiss()
}, getString(R.string.all_no) to { dialog, _ ->
......@@ -222,6 +225,7 @@ class DnsRuleFragment : Fragment() {
}, changeSourceStatus = { hostSource, enabled ->
hostSource.enabled = enabled
getDatabase().hostSourceDao().setSourceEnabled(hostSource.id, enabled)
notifyRulesChanged()
}, editSource = { hostSource ->
NewHostSourceDialog(context!!, onSourceCreated = { newSource ->
val currentSource = getDatabase().hostSourceDao().findById(hostSource.id)!!.apply {
......@@ -260,6 +264,7 @@ class DnsRuleFragment : Fragment() {
sourceAdapter.notifyItemRangeRemoved(sourceAdapterList.size + 1, userRuleCount)
}
userRuleCount = 0
notifyRulesChanged()
dialog.dismiss()
}, getString(R.string.all_no) to { dialog, _ ->
dialog.dismiss()
......@@ -325,6 +330,7 @@ class DnsRuleFragment : Fragment() {
list.smoothScrollToPosition(insertPos)
}
}
notifyRulesChanged()
} else {
Snackbar.make(
activity!!.findViewById(android.R.id.content),
......@@ -350,6 +356,7 @@ class DnsRuleFragment : Fragment() {
totalRuleCount = totalRuleCount!! - 1
updateRuleCountTitle()
}
notifyRulesChanged()
}, editRule = {
DnsRuleDialog(context!!, it) { newRule ->
val rows = getDatabase().dnsRuleDao().updateIgnore(newRule)
......@@ -447,6 +454,10 @@ class DnsRuleFragment : Fragment() {
}
}
private fun notifyRulesChanged() {
LocalBroadcastManager.getInstance(context!!).sendBroadcast(Intent(DnsVpnService.BROADCAST_DNSRULES_REFRESHED))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == fileChosenRequestCode && resultCode == RESULT_OK){
......
......@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import com.frostnerd.smokescreen.activity.BackgroundVpnConfigureActivity
import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.util.preferences.VpnServiceState
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -29,9 +30,18 @@ class AutostartReceiver : BroadcastReceiver() {
if (intent.action != null) {
var startService = false
when {
intent.action == Intent.ACTION_MY_PACKAGE_REPLACED -> startService = context.getPreferences().startAppAfterUpdate
intent.action == Intent.ACTION_PACKAGE_REPLACED -> startService = intent.data?.schemeSpecificPart == context.packageName && context.getPreferences().startAppAfterUpdate
context.getPreferences().startAppOnBoot -> startService = true
intent.action == Intent.ACTION_MY_PACKAGE_REPLACED -> {
startService = context.getPreferences().startAppAfterUpdate
context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
}
intent.action == Intent.ACTION_PACKAGE_REPLACED -> {
startService = intent.data?.schemeSpecificPart == context.packageName && context.getPreferences().startAppAfterUpdate
context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
}
context.getPreferences().startAppOnBoot -> {
context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
startService = true
}
}
if(startService) BackgroundVpnConfigureActivity.prepareVpn(context)
}
......
......@@ -15,6 +15,7 @@ import android.util.Base64
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.frostnerd.dnstunnelproxy.*
import com.frostnerd.dnstunnelproxy.QueryListener
import com.frostnerd.encrypteddnstunnelproxy.HttpsDnsServerInformation
import com.frostnerd.encrypteddnstunnelproxy.ServerConfiguration
import com.frostnerd.encrypteddnstunnelproxy.tls.TLSUpstreamAddress
......@@ -34,10 +35,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.util.DeepActionState
import com.frostnerd.smokescreen.util.Notifications
import com.frostnerd.smokescreen.util.preferences.VpnServiceState
import com.frostnerd.smokescreen.util.proxy.ProxyBypassHandler
import com.frostnerd.smokescreen.util.proxy.ProxyHttpsHandler
import com.frostnerd.smokescreen.util.proxy.ProxyTlsHandler
import com.frostnerd.smokescreen.util.proxy.SmokeProxy
import com.frostnerd.smokescreen.util.proxy.*
import com.frostnerd.vpntunnelproxy.FutureAnswer
import com.frostnerd.vpntunnelproxy.RetryingVPNTunnelProxy
import com.frostnerd.vpntunnelproxy.TrafficStats
......@@ -86,7 +84,6 @@ import kotlin.random.Random
*/
class DnsVpnService : VpnService(), Runnable {
private var fileDescriptor: ParcelFileDescriptor? = null
private var handle: ProxyHttpsHandler? = null
private var dnsProxy: SmokeProxy? = null
private var vpnProxy: RetryingVPNTunnelProxy? = null
private var destroyed = false
......@@ -102,6 +99,7 @@ class DnsVpnService : VpnService(), Runnable {
private var connectedToANetwork: Boolean? = null
private var lastScreenOff: Long? = null
private lateinit var screenStateReceiver: BroadcastReceiver
private var dnsRuleRefreshReceiver:BroadcastReceiver? = null
private var simpleNotification = getPreferences().simpleNotification
private var lastVPNStopTime:Long? = null
private val coroutineScope:CoroutineContext = SupervisorJob()
......@@ -115,6 +113,7 @@ class DnsVpnService : VpnService(), Runnable {
companion object {
const val BROADCAST_VPN_ACTIVE = BuildConfig.APPLICATION_ID + ".VPN_ACTIVE"
const val BROADCAST_VPN_INACTIVE = BuildConfig.APPLICATION_ID + ".VPN_INACTIVE"
const val BROADCAST_DNSRULES_REFRESHED = BuildConfig.APPLICATION_ID + ".DNSRULE_REFRESH"
private const val REQUEST_CODE_IGNORE_SERVICE_KILLED = 10
var currentTrafficStats: TrafficStats? = null
......@@ -256,6 +255,13 @@ class DnsVpnService : VpnService(), Runnable {
}
}
}
dnsRuleRefreshReceiver = registerLocalReceiver(listOf(BROADCAST_DNSRULES_REFRESHED)) {
vpnProxy?.apply {
((packetProxy as DnsPacketProxy).localResolver)?.apply {
(this as DnsRuleResolver).refreshRuleCount()
}
}
}
log("Service created.")
}
......@@ -750,7 +756,7 @@ class DnsVpnService : VpnService(), Runnable {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
builder.setMetered(false)
}
builder.setConfigureIntent(PendingIntent.getActivity(this, 1, Intent(this, MainActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT))
builder.setConfigureIntent(PendingIntent.getActivity(this, 1, Intent(this, PinActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT))
val deviceHasIpv6 = hasDeviceIpv6Address()
val deviceHasIpv4 = hasDeviceIpv4Address()
......@@ -779,7 +785,7 @@ class DnsVpnService : VpnService(), Runnable {
try {
builder.addAddress("$prefix.134", mask)
couldSetAddress = true
log("Ipv4-Address set to $prefix.134./$mask")
log("Ipv4-Address set to $prefix.134/$mask")
break
} catch (ignored: IllegalArgumentException) {
log("Couldn't set Ipv4-Address $prefix.134/$mask")
......@@ -975,37 +981,7 @@ class DnsVpnService : VpnService(), Runnable {
log("DnsProxy created, creating VPN proxy")
vpnProxy = RetryingVPNTunnelProxy(dnsProxy!!, vpnService = this, coroutineScope = CoroutineScope(
newFixedThreadPoolContext(2, "proxy-pool")
), logger = object : com.frostnerd.vpntunnelproxy.Logger() {
private val tag = (0..5).map { Random.nextInt('a'.toInt(), 'z'.toInt()).toChar() }.joinToString(separator = "")
private val minLogLevel =
if (BuildConfig.DEBUG || getPreferences().advancedLogging) Level.FINE
else if (getPreferences().loggingEnabled) Level.INFO
else Level.OFF
override fun logMessage(message: () -> String, level: Level) {
if (level >= minLogLevel) {
log(message(), "$tag, VPN-LIBRARY, $level")
}
}
override fun failedRequest(question: FutureAnswer, reason: Throwable?) {
if (reason != null && Level.INFO >= minLogLevel) log(
"A request failed: " + Logger.stacktraceToString(reason),
"$tag, VPN-LIBRARY"
)
}
override fun logException(ex: Exception, terminal: Boolean, level: Level) {
if (terminal) log(ex)
else if(Level.INFO >= minLogLevel) log(Logger.stacktraceToString(ex), "$tag, VPN-LIBRARY, $level")
}
override fun logMessage(message: String, level: Level) {
if (level >= minLogLevel) {
log(message, "$tag, VPN-LIBRARY, $level")
}
}
})
), logger = VpnLogger(applicationContext))
vpnProxy?.maxRetries = 15
log("VPN proxy creating, trying to run...")
......@@ -1022,7 +998,7 @@ class DnsVpnService : VpnService(), Runnable {
private fun createQueryLogger(): QueryListener? {
return if (getPreferences().shouldLogDnsQueriesToConsole() || getPreferences().queryLoggingEnabled) {
com.frostnerd.smokescreen.util.proxy.QueryListener(this)
com.frostnerd.smokescreen.util.proxy.QueryListener(applicationContext)
} else null
}
......@@ -1088,24 +1064,7 @@ class DnsVpnService : VpnService(), Runnable {
dnsCache = if (getPreferences().useDnsCache) {
log("Creating DNS Cache.")
val cacheControl: CacheControl = if (!getPreferences().useDefaultDnsCacheTime) {
val cacheTime = getPreferences().customDnsCacheTime.toLong()
val nxDomainCacheTime = getPreferences().nxDomainCacheTime.toLong()
object : CacheControl {
override suspend fun getTtl(
answerMessage: DnsMessage,
dnsName: DnsName,
type: Record.TYPE,
record: Record<*>
): Long {
return if (answerMessage.responseCode == DnsMessage.RESPONSE_CODE.NX_DOMAIN) nxDomainCacheTime else cacheTime
}
override suspend fun getTtl(question: Question, record: Record<*>): Long =
cacheTime
override fun shouldCache(question: Question): Boolean = true
}
NxDomainCacheControl(applicationContext)
} else DefaultCacheControl(getPreferences().minimumCacheTime.toLong())
val onClearCache: ((currentCache: Map<String, Map<Record.TYPE, Map<Record<*>, Long>>>) -> Unit)? =
if (getPreferences().keepDnsCacheAcrossLaunches) {
......@@ -1186,108 +1145,10 @@ class DnsVpnService : VpnService(), Runnable {
}
private fun createLocalResolver(): LocalResolver? {
if (getPreferences().dnsRulesEnabled) {
return object : LocalResolver(false) {
private val dao = getDatabase().dnsRuleDao()
private val resolveResults = mutableMapOf<Question, String>()
private val wwwRegex = Regex("^www\\.")
private val useUserRules = getPreferences().customHostsEnabled
override suspend fun canResolve(question: Question): Boolean {
return if (question.type != Record.TYPE.A && question.type != Record.TYPE.AAAA) {
false
} else {
val uniformQuestion = question.name.toString().replace(wwwRegex, "")
val isWhitelisted = dao.findPossibleWildcardRuleTarget(
uniformQuestion,
question.type,
useUserRules,
true,
false
).any {
DnsRuleDialog.databaseHostToMatcher(it.host).reset(uniformQuestion)
.matches()
} || dao.findNonWildcardWhitelistEntry(
uniformQuestion,
useUserRules
).isNotEmpty()
if (isWhitelisted) false
else {
val resolveResult =
dao.findRuleTarget(uniformQuestion, question.type, useUserRules)
?.let {
when (it) {
"0" -> "0.0.0.0"
"1" -> {
if (question.type == Record.TYPE.AAAA) "::1"
else "127.0.0.1"
}
else -> it
}
}
if (resolveResult != null) {
resolveResults[question] = resolveResult
true
} else {
val wildcardResolveResults = dao.findPossibleWildcardRuleTarget(
uniformQuestion,
question.type,
useUserRules,
false,
true
).filter {
DnsRuleDialog.databaseHostToMatcher(it.host)
.reset(uniformQuestion).matches()
}
if(wildcardResolveResults.isNotEmpty()) {
resolveResults[question] = wildcardResolveResults.first().let {
if (question.type == Record.TYPE.AAAA) it.ipv6Target
?: it.target
else it.target
}.let {
when (it) {
"0" -> "0.0.0.0"
"1" -> {
if (question.type == Record.TYPE.AAAA) "::1"
else "127.0.0.1"
}
else -> it
}
}
true
} else {
false
}
}
}
}
}
override suspend fun resolve(question: Question): List<Record<*>> {
val result = resolveResults.remove(question)
return result?.let {
val data = if (question.type == Record.TYPE.A) {
A(it)
} else {
AAAA(it)
}
listOf(
Record(
question.name.toString(),
question.type,
question.clazz.value,
9999,
data
)
)
} ?: throw IllegalStateException()
}
override fun cleanup() {}
}
return if (getPreferences().dnsRulesEnabled) {
DnsRuleResolver(applicationContext)
} else {
return null
null
}
}
......
......@@ -8,6 +8,7 @@ import android.content.Intent
import android.net.Uri
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.frostnerd.general.service.isServiceRunning
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.database.entities.DnsRule
import com.frostnerd.smokescreen.database.entities.HostSource
......@@ -244,6 +245,7 @@ class RuleImportService : IntentService("RuleImportService") {
}
getDatabase().hostSourceDao().removeChecksumForDisabled()
log("Done.")
if(isServiceRunning(DnsVpnService::class.java)) DnsVpnService.restartVpn(this, false)
showSuccessNotification()
} else {
dnsRuleDao.deleteStagedRules()
......
......@@ -80,13 +80,16 @@ class StartStopTileService:TileService() {
val tile:Tile? = qsTile
if(tile != null) {
if(serviceRunning) {
tile.label = getString(R.string.quicksettings_stop_text)
tile.icon = Icon.createWithResource(this, R.drawable.ic_stop)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
tile.subtitle = getString(R.string.quicksettings_stop_text)
}
tile.state = Tile.STATE_ACTIVE
tile.contentDescription = getString(R.string.contentdescription_stop_app)
} else {
tile.label = getString(R.string.quicksettings_start_text)
tile.icon = Icon.createWithResource(this, R.drawable.ic_play)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
tile.subtitle = getString(R.string.quicksettings_start_text)
}
tile.state = Tile.STATE_INACTIVE
tile.contentDescription = getString(R.string.contentdescription_start_app)
}
......
......@@ -3,7 +3,8 @@ package com.frostnerd.smokescreen.util
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import com.frostnerd.smokescreen.activity.MainActivity
import android.os.Bundle
import com.frostnerd.smokescreen.activity.PinActivity
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -29,7 +30,7 @@ enum class DeepActionState {
fun intentTo(context:Context): Intent {
return Intent(context, MainActivity::class.java).putExtra("deep_action", this)
return PinActivity.openAppIntent(context, Bundle().apply { putSerializable("deep_action", this@DeepActionState) })
}
fun pendingIntentTo(context: Context):PendingIntent {
......
package com.frostnerd.smokescreen.util
class MaxSizeMap<K, V>(val maxSize:Int, initialCapacity:Int) :LinkedHashMap<K, V>(initialCapacity) {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean {
return size > maxSize
}
}
\ No newline at end of file
package com.frostnerd.smokescreen.util.proxy
import android.content.Context
import com.frostnerd.dnstunnelproxy.LocalResolver
import com.frostnerd.smokescreen.database.entities.DnsRule
import com.frostnerd.smokescreen.database.getDatabase
import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.util.MaxSizeMap
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.minidns.dnsmessage.Question
import org.minidns.record.A
import org.minidns.record.AAAA
import org.minidns.record.Record
import java.util.*
import kotlin.collections.HashSet
import kotlin.math.abs
class DnsRuleResolver(context: Context) : LocalResolver(false) {
private val maxWhitelistCacheSize = 250
private val maxResolvedCacheSize = 500
private val maxWildcardResolvedCacheSize = 250
private val dao = context.getDatabase().dnsRuleDao()
private val resolveResults = mutableMapOf<Int, String>()
private val wwwRegex = Regex("^www\\.")
private val useUserRules = context.getPreferences().customHostsEnabled
private var ruleCount: Int? = null
private var wildcardCount: Int? = null
private var whitelistCount: Int? = null
private var nonWildcardCount:Int? =</