Unverified Commit 01da6b11 authored by initrider's avatar initrider Committed by GitHub

Merge pull request #3 from shadowsocks/master

Sync
parents 633b9764 7c5840b2
...@@ -12,11 +12,6 @@ Crash: [Submit an issue](https://github.com/shadowsocks/shadowsocks-android/issu ...@@ -12,11 +12,6 @@ Crash: [Submit an issue](https://github.com/shadowsocks/shadowsocks-android/issu
Use [Tasker](http://tasker.dinglisch.net/) integration. Use [Tasker](http://tasker.dinglisch.net/) integration.
### How to add QR code from local gallery?
Scan it with a third-party scanner like [QuickMark Barcode Scanner](https://play.google.com/store/apps/details?id=tw.com.quickmark) and click the `ss` url.
### Why is NAT mode deprecated? ### Why is NAT mode deprecated?
1. Requiring ROOT permission; 1. Requiring ROOT permission;
...@@ -34,7 +29,8 @@ The exclamation mark in the Wi-Fi/cellular icon appears because the system fails ...@@ -34,7 +29,8 @@ The exclamation mark in the Wi-Fi/cellular icon appears because the system fails
3. Some ROM like [Flyme](https://github.com/shadowsocks/shadowsocks-android/issues/1589) has **very** broken direct boot support; 3. Some ROM like [Flyme](https://github.com/shadowsocks/shadowsocks-android/issues/1589) has **very** broken direct boot support;
4. If you have Xposed framework and/or battery saver apps, it's likely that this app wouldn't work well with these either. 4. If you have Xposed framework and/or battery saver apps, it's likely that this app wouldn't work well with these either.
* Fixes for MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772) [#888](https://github.com/shadowsocks/shadowsocks-android/issues/888) * Fixes for MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
* Fixes for EMUI: [#888](https://github.com/shadowsocks/shadowsocks-android/issues/888)
* Fixes for Huawei: [#1091 (comment)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836) * Fixes for Huawei: [#1091 (comment)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836)
* Related to Xposed: [#1414](https://github.com/shadowsocks/shadowsocks-android/issues/1414) * Related to Xposed: [#1414](https://github.com/shadowsocks/shadowsocks-android/issues/1414)
* Samsung and/or Brevent: [#1410](https://github.com/shadowsocks/shadowsocks-android/issues/1410) * Samsung and/or Brevent: [#1410](https://github.com/shadowsocks/shadowsocks-android/issues/1410)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
[![Build Status](https://api.travis-ci.org/shadowsocks/shadowsocks-android.svg)](https://travis-ci.org/shadowsocks/shadowsocks-android) [![Build Status](https://api.travis-ci.org/shadowsocks/shadowsocks-android.svg)](https://travis-ci.org/shadowsocks/shadowsocks-android)
[![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21) [![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21)
[![Releases](https://img.shields.io/github/downloads/shadowsocks/shadowsocks-android/total.svg)](https://github.com/shadowsocks/shadowsocks-android/releases) [![Releases](https://img.shields.io/github/downloads/shadowsocks/shadowsocks-android/total.svg)](https://github.com/shadowsocks/shadowsocks-android/releases)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1a21d48d466644cdbcb57a1889abea5b)](https://www.codacy.com/app/shadowsocks/shadowsocks-android?utm_source=github.com&utm_medium=referral&utm_content=shadowsocks/shadowsocks-android&utm_campaign=Badge_Grade)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
A [shadowsocks](http://shadowsocks.org) client for Android, written in Kotlin. A [shadowsocks](http://shadowsocks.org) client for Android, written in Kotlin.
......
...@@ -4,12 +4,12 @@ apply plugin: 'com.github.ben-manes.versions' ...@@ -4,12 +4,12 @@ apply plugin: 'com.github.ben-manes.versions'
buildscript { buildscript {
ext { ext {
kotlinVersion = '1.2.21' kotlinVersion = '1.2.30'
minSdkVersion = 21 minSdkVersion = 21
sdkVersion = 27 sdkVersion = 27
buildToolsVersion = '27.0.3' buildToolsVersion = '27.0.3'
supportLibraryVersion = '27.0.2' supportLibraryVersion = '27.1.0'
takisoftFixVersion = '27.0.2.0' takisoftFixVersion = '27.1.0.0'
playServicesVersion = '11.8.0' playServicesVersion = '11.8.0'
junitVersion = '4.12' junitVersion = '4.12'
androidTestVersion = '1.0.1' androidTestVersion = '1.0.1'
......
#!/usr/bin/python #!/usr/bin/python
# -*- encoding: utf8 -*- # -*- encoding: utf8 -*-
import itertools
import math
import sys import sys
import IPy import IPy
......
Subproject commit 6040be9d0af812382934defe317c2e28434494ad Subproject commit 1a21989566e778139c489d5f8972979bda9b16c1
Subproject commit b68d7f897c6800363f855cface600c82749a4845 Subproject commit 486515fc9846cf408a75d3e3e173e3ba927a7fd2
Subproject commit 466f9902c9779b8801f521f88db1d1522c880c26 Subproject commit e7594118e8cf164ffb53923b9b89ae169cb87156
# https://github.com/arturbosch/detekt/blob/801994bd60cc759b181649356cea045b8125301b/detekt-cli/src/main/resources/default-detekt-config.yml
comments:
active: false
complexity:
active: true
ComplexCondition:
active: true
threshold: 3
ComplexInterface:
active: true
threshold: 10
includeStaticDeclarations: false
ComplexMethod:
active: true
threshold: 10
LabeledExpression:
active: true
LargeClass:
active: true
threshold: 150
LongMethod:
active: true
threshold: 20
LongParameterList:
active: true
threshold: 5
ignoreDefaultParameters: true
MethodOverloading:
active: false
NestedBlockDepth:
active: true
threshold: 3
StringLiteralDuplication:
active: true
threshold: 2
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: true
thresholdInFiles: 10
thresholdInClasses: 10
thresholdInInterfaces: 10
thresholdInObjects: 10
thresholdInEnums: 10
empty-blocks:
active: true
EmptyCatchBlock:
active: false
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
active: true
EmptyDoWhileBlock:
active: true
EmptyElseBlock:
active: true
EmptyFinallyBlock:
active: true
EmptyForBlock:
active: true
EmptyFunctionBlock:
active: true
EmptyIfBlock:
active: true
EmptyInitBlock:
active: true
EmptyKtFile:
active: true
EmptySecondaryConstructor:
active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
active: true
exceptions:
active: true
ExceptionRaisedInUnexpectedLocation:
active: true
methodNames: 'toString,hashCode,equals,finalize'
InstanceOfCheckForException:
active: true
NotImplementedDeclaration:
active: true
PrintStackTrace:
active: false
RethrowCaughtException:
active: true
ReturnFromFinally:
active: true
SwallowedException:
active: true
ThrowingExceptionFromFinally:
active: true
ThrowingExceptionInMain:
active: true
ThrowingExceptionsWithoutMessageOrCause:
active: true
exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
ThrowingNewInstanceOfSameException:
active: true
TooGenericExceptionCaught:
active: true
exceptions:
- ArrayIndexOutOfBoundsException
- Error
- Exception
- IllegalMonitorStateException
- NullPointerException
- IndexOutOfBoundsException
- RuntimeException
- Throwable
TooGenericExceptionThrown:
active: true
exceptions:
- Error
- Exception
- NullPointerException
- Throwable
- RuntimeException
naming:
active: true
ClassNaming:
active: true
classPattern: '[A-Z$][a-zA-Z0-9$]*'
EnumNaming:
active: true
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: true
forbiddenName: ''
FunctionMaxLength:
active: true
maximumFunctionNameLength: 30
FunctionMinLength:
active: true
minimumFunctionNameLength: 3
FunctionNaming:
active: true
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
MatchingDeclarationName:
active: true
MemberNameEqualsClassName:
active: false
ObjectPropertyNaming:
active: true
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
PackageNaming:
active: true
packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$'
TopLevelPropertyNaming:
active: true
constantPattern: '[A-Z][_A-Z0-9]*'
propertyPattern: '[a-z][A-Za-z\d]*'
privatePropertyPattern: '(_)?[a-z][A-Za-z0-9]*'
VariableMaxLength:
active: true
maximumVariableNameLength: 64
VariableMinLength:
active: false
VariableNaming:
active: true
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
performance:
active: true
ForEachOnRange:
active: true
SpreadOperator:
active: true
UnnecessaryTemporaryInstantiation:
active: true
potential-bugs:
active: true
DuplicateCaseInWhenExpression:
active: true
EqualsAlwaysReturnsTrueOrFalse:
active: true
EqualsWithHashCodeExist:
active: true
ExplicitGarbageCollectionCall:
active: true
InvalidRange:
active: true
IteratorHasNextCallsNextMethod:
active: true
IteratorNotThrowingNoSuchElementException:
active: true
LateinitUsage:
active: false
UnconditionalJumpStatementInLoop:
active: true
UnreachableCode:
active: true
UnsafeCallOnNullableType:
active: false
UnsafeCast:
active: false
UselessPostfixExpression:
active: true
WrongEqualsTypeParameter:
active: true
style:
active: true
CollapsibleIfStatements:
active: true
DataClassContainsFunctions:
active: true
conversionFunctionPrefix: 'to'
EqualsNullCall:
active: true
ExpressionBodySyntax:
active: true
ForbiddenComment:
active: true
values: 'TODO:,FIXME:,STOPSHIP:'
ForbiddenImport:
active: true
imports: ''
FunctionOnlyReturningConstant:
active: true
ignoreOverridableFunction: true
excludedFunctions: 'describeContents'
LoopWithTooManyJumpStatements:
active: true
maxJumpCount: 1
MagicNumber:
active: false
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: false
excludeImportStatements: false
ModifierOrder:
active: true
NestedClassesVisibility:
active: true
NewLineAtEndOfFile:
active: true
OptionalAbstractKeyword:
active: true
OptionalReturnKeyword:
active: true
OptionalUnit:
active: true
OptionalWhenBraces:
active: true
ProtectedMemberInFinalClass:
active: true
RedundantVisibilityModifierRule:
active: true
ReturnCount:
active: false
SafeCast:
active: true
SerialVersionUIDInSerializableClass:
active: true
SpacingBetweenPackageAndImports:
active: true
ThrowsCount:
active: true
max: 2
UnnecessaryAbstractClass:
active: true
UnnecessaryInheritance:
active: true
UnnecessaryParentheses:
active: true
UntilInsteadOfRangeTo:
active: true
UnusedImports:
active: true
UseDataClass:
active: false
UtilityClassWithPublicConstructor:
active: true
WildcardImport:
active: false
...@@ -21,14 +21,15 @@ android { ...@@ -21,14 +21,15 @@ android {
applicationId "com.github.shadowsocks" applicationId "com.github.shadowsocks"
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion targetSdkVersion rootProject.sdkVersion
versionCode 4040600 versionCode 4050100
versionName "4.4.6" versionName "4.5.1"
testApplicationId "com.github.shadowsocks.test" testApplicationId "com.github.shadowsocks.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW" resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
} }
buildTypes { buildTypes {
debug { debug {
multiDexEnabled true
pseudoLocalesEnabled true pseudoLocalesEnabled true
} }
release { release {
...@@ -57,21 +58,21 @@ dependencies { ...@@ -57,21 +58,21 @@ dependencies {
implementation "com.android.support:design:$supportLibraryVersion" implementation "com.android.support:design:$supportLibraryVersion"
implementation "com.android.support:gridlayout-v7:$supportLibraryVersion" implementation "com.android.support:gridlayout-v7:$supportLibraryVersion"
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5' implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
implementation 'com.evernote:android-job:1.2.2' implementation 'com.evernote:android-job:1.2.4'
implementation "com.google.android.gms:play-services-ads:$playServicesVersion" implementation "com.google.android.gms:play-services-ads:$playServicesVersion"
implementation "com.google.android.gms:play-services-analytics:$playServicesVersion" implementation "com.google.android.gms:play-services-analytics:$playServicesVersion"
implementation "com.google.android.gms:play-services-vision:$playServicesVersion"
implementation "com.google.firebase:firebase-config:$playServicesVersion" implementation "com.google.firebase:firebase-config:$playServicesVersion"
implementation 'com.j256.ormlite:ormlite-android:5.0' implementation 'com.j256.ormlite:ormlite-android:5.1'
implementation 'com.mikepenz:crossfader:1.5.2' implementation 'com.mikepenz:materialdrawer:6.0.6'
implementation 'com.mikepenz:materialdrawer:6.0.3' implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion" implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
implementation 'dnsjava:dnsjava:2.1.8' implementation 'dnsjava:dnsjava:2.1.8'
implementation 'eu.chainfire:libsuperuser:1.0.0.201704021214' implementation 'eu.chainfire:libsuperuser:1.0.0.201704021214'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation 'net.glxn.qrgen:android:2.0' implementation 'net.glxn.qrgen:android:2.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation 'xyz.belvi.mobilevision:barcodescanner:2.0.3'
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "com.android.support.test:runner:$androidTestVersion" androidTestImplementation "com.android.support.test:runner:$androidTestVersion"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$androidEspressoVersion" androidTestImplementation "com.android.support.test.espresso:espresso-core:$androidEspressoVersion"
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
package="com.github.shadowsocks" package="com.github.shadowsocks"
android:installLocation="internalOnly"> android:installLocation="internalOnly">
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
...@@ -71,7 +72,7 @@ ...@@ -71,7 +72,7 @@
<activity <activity
android:name=".VpnRequestActivity" android:name=".VpnRequestActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar" android:theme="@style/Theme.Translucent"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:taskAffinity="" android:taskAffinity=""
android:launchMode="singleTask"/> android:launchMode="singleTask"/>
...@@ -169,19 +170,16 @@ ...@@ -169,19 +170,16 @@
android:process=":bg" android:process=":bg"
android:directBootAware="true"/> android:directBootAware="true"/>
<service android:name="com.evernote.android.job.v14.PlatformAlarmService" <service android:name="com.evernote.android.job.v14.PlatformAlarmService"
android:process=":bg" tools:node="remove"/>
android:directBootAware="true"/>
<service android:name="com.evernote.android.job.v14.PlatformAlarmServiceExact" <service android:name="com.evernote.android.job.v14.PlatformAlarmServiceExact"
android:process=":bg" tools:node="remove"/>
android:directBootAware="true"/>
<service android:name="com.evernote.android.job.gcm.PlatformGcmService" <service android:name="com.evernote.android.job.gcm.PlatformGcmService"
tools:node="remove"/> tools:node="remove"/>
<service android:name="com.evernote.android.job.JobRescheduleService" <service android:name="com.evernote.android.job.JobRescheduleService"
android:process=":bg" android:process=":bg"
android:directBootAware="true"/> android:directBootAware="true"/>
<receiver android:name="com.evernote.android.job.v14.PlatformAlarmReceiver" <receiver android:name="com.evernote.android.job.v14.PlatformAlarmReceiver"
android:process=":bg" tools:node="remove"/>
android:directBootAware="true"/>
<receiver android:name="com.evernote.android.job.JobBootReceiver" <receiver android:name="com.evernote.android.job.JobBootReceiver"
android:process=":bg" android:process=":bg"
android:directBootAware="true"/> android:directBootAware="true"/>
......
1.0.1.0/24
1.0.2.0/23
1.0.8.0/21
1.0.32.0/19
1.1.0.0/24
1.1.2.0/23
1.1.4.0/22
1.1.8.0/21
1.1.16.0/20
1.1.32.0/19
1.2.0.0/23
1.2.2.0/24
1.2.4.0/22
1.2.8.0/21
1.2.16.0/20
1.2.32.0/19
1.2.64.0/18
1.3.0.0/16
1.4.1.0/24
1.4.2.0/23
1.4.4.0/22
1.4.8.0/21
1.4.16.0/20
1.4.32.0/19
1.4.64.0/18
1.8.0.0/16
1.10.0.0/21
1.10.8.0/23
1.10.11.0/24
1.10.12.0/22
1.10.16.0/20
1.10.32.0/19
1.10.64.0/18
1.12.0.0/14
1.24.0.0/13
1.45.0.0/16
1.48.0.0/14
1.56.0.0/13
1.68.0.0/14
1.80.0.0/12
1.116.0.0/14
1.180.0.0/14
1.184.0.0/15
1.188.0.0/14
1.192.0.0/13
1.202.0.0/15
1.204.0.0/14
14.0.0.0/21
14.0.12.0/22
14.1.0.0/22
14.1.24.0/22
14.1.96.0/22
14.1.108.0/22
14.16.0.0/12
14.102.128.0/22
14.102.156.0/22
14.102.180.0/22
14.103.0.0/16
14.104.0.0/13
14.112.0.0/12
14.130.0.0/15
14.134.0.0/15
14.144.0.0/12
14.192.56.0/21
14.192.76.0/22
14.196.0.0/15
14.204.0.0/15
14.208.0.0/12
20.134.160.0/20
20.139.160.0/20
27.0.128.0/21
27.0.160.0/21
27.0.188.0/22
27.0.204.0/22
27.0.208.0/21
27.8.0.0/13
27.16.0.0/12
27.34.232.0/21
27.36.0.0/14
27.40.0.0/13
27.50.40.0/21
27.50.128.0/17
27.54.72.0/21
27.54.152.0/21
27.54.192.0/18
27.98.208.0/20
27.98.224.0/19
27.99.128.0/17
27.103.0.0/16
27.106.128.0/18
27.106.204.0/22
27.109.32.0/19
27.109.124.0/22
27.112.0.0/18
27.112.80.0/20
27.112.112.0/21
27.113.128.0/18
27.115.0.0/17
27.116.44.0/22
27.121.72.0/21
27.121.120.0/21
27.123.232.0/22
27.128.0.0/15
27.131.220.0/22
27.144.0.0/16
27.148.0.0/14
27.152.0.0/13
27.184.0.0/13
27.192.0.0/11
27.224.0.0/14
36.0.0.0/22
36.0.8.0/21
36.0.16.0/20
36.0.32.0/19
36.0.64.0/18
36.0.128.0/17
36.1.0.0/16
36.4.0.0/14
36.16.0.0/12
36.32.0.0/14
36.36.0.0/16
36.37.0.0/19
36.37.36.0/23
36.37.39.0/24
36.37.40.0/21
36.37.48.0/20
36.40.0.0/13
36.48.0.0/15
36.51.0.0/16
36.56.0.0/13
36.96.0.0/11
36.128.0.0/10
36.192.0.0/11
36.248.0.0/14
36.254.0.0/16
36.255.116.0/22
36.255.128.0/22
36.255.164.0/22
36.255.172.0/22
36.255.176.0/22
36.255.220.0/22
39.0.0.0/24
39.0.2.0/23
39.0.4.0/22
39.0.8.0/21
39.0.16.0/20
39.0.32.0/19
39.0.64.0/18
39.0.128.0/17
39.64.0.0/11
39.96.0.0/13
39.104.0.0/14
39.108.0.0/16
39.128.0.0/10
40.0.176.0/20
40.0.247.0/24
40.0.248.0/22
40.0.252.0/23
40.0.255.0/24
40.72.0.0/15
40.125.128.0/17
40.126.64.0/18
40.198.10.0/24
40.198.16.0/21
40.198.24.0/23
40.251.225.0/24
40.251.227.0/24
42.0.0.0/22
42.0.8.0/21
42.0.16.0/21
42.0.24.0/22
42.0.32.0/19
42.0.128.0/17
42.1.0.0/19
42.1.32.0/20
42.1.48.0/21
42.1.56.0/22
42.1.128.0/17
42.4.0.0/14
42.48.0.0/13
42.56.0.0/14
42.62.0.0/17
42.62.128.0/19
42.62.160.0/20
42.62.180.0/22
42.62.184.0/21
42.63.0.0/16
42.80.0.0/15
42.83.64.0/20
42.83.80.0/22
42.83.88.0/21
42.83.96.0/19
42.83.128.0/17
42.84.0.0/14
42.88.0.0/13
42.96.64.0/19
42.96.96.0/21
42.96.108.0/22
42.96.112.0/20
42.96.128.0/17
42.97.0.0/16
42.99.0.0/18
42.99.64.0/19
42.99.96.0/20
42.99.112.0/22
42.99.120.0/21
42.100.0.0/14
42.120.0.0/15
42.122.0.0/16
42.123.0.0/19
42.123.36.0/22
42.123.40.0/21
42.123.48.0/20
42.123.64.0/18
42.123.128.0/17
42.128.0.0/12
42.156.0.0/19
42.156.36.0/22
42.156.40.0/21
42.156.48.0/20
42.156.64.0/18
42.156.128.0/17
42.157.0.0/16
42.158.0.0/15
42.160.0.0/12
42.176.0.0/13
42.184.0.0/15
42.186.0.0/16
42.187.0.0/18
42.187.64.0/19
42.187.96.0/20
42.187.112.0/21
42.187.120.0/22
42.187.128.0/17
42.192.0.0/13
42.201.0.0/17
42.202.0.0/15
42.204.0.0/14
42.208.0.0/12
42.224.0.0/12
42.240.0.0/16
42.242.0.0/15
42.244.0.0/14
42.248.0.0/13
43.224.12.0/22
43.224.24.0/22
43.224.44.0/22
43.224.52.0/22
43.224.56.0/22
43.224.64.0/21
43.224.72.0/22
43.224.80.0/22
43.224.100.0/22
43.224.144.0/22
43.224.160.0/22
43.224.176.0/22
43.224.184.0/22
43.224.200.0/21
43.224.208.0/21
43.224.216.0/22
43.224.224.0/22
43.224.240.0/22
43.225.76.0/22
43.225.84.0/22
43.225.120.0/21
43.225.140.0/22
43.225.172.0/22
43.225.180.0/22
43.225.184.0/22
43.225.208.0/22
43.225.216.0/21
43.225.224.0/20
43.225.240.0/21
43.225.252.0/22
43.226.32.0/19
43.226.64.0/19
43.226.96.0/20
43.226.112.0/21
43.226.120.0/22
43.226.128.0/18
43.226.192.0/20
43.226.208.0/21
43.226.236.0/22
43.226.240.0/20
43.227.0.0/21
43.227.8.0/22
43.227.32.0/19
43.227.64.0/19
43.227.96.0/21
43.227.104.0/22
43.227.136.0/21
43.227.144.0/22
43.227.152.0/21
43.227.160.0/20
43.227.176.0/21
43.227.188.0/22
43.227.192.0/19
43.227.232.0/22
43.227.248.0/21
43.228.0.0/18
43.228.64.0/21
43.228.76.0/22
43.228.100.0/22
43.228.116.0/22
43.228.120.0/22
43.228.132.0/22
43.228.136.0/22
43.228.148.0/22
43.228.152.0/22
43.228.188.0/22
43.229.16.0/22
43.229.40.0/22
43.229.48.0/22
43.229.56.0/22
43.229.96.0/22
43.229.120.0/22
43.229.136.0/21
43.229.144.0/22
43.229.168.0/21
43.229.176.0/20
43.229.192.0/21
43.229.216.0/21
43.229.232.0/21
43.230.20.0/22
43.230.32.0/22
43.230.68.0/22
43.230.72.0/22
43.230.84.0/22
43.230.124.0/22
43.230.136.0/22
43.230.168.0/22
43.230.220.0/22
43.230.224.0/19
43.231.12.0/22
43.231.32.0/20
43.231.80.0/20
43.231.96.0/20
43.231.136.0/21
43.231.144.0/20
43.231.160.0/20
43.231.176.0/21
43.236.0.0/15
43.238.0.0/16
43.239.0.0/19
43.239.32.0/20
43.239.48.0/22
43.239.116.0/22
43.239.120.0/22
43.239.172.0/22
43.239.176.0/22
43.240.0.0/22
43.240.48.0/22
43.240.56.0/21
43.240.68.0/22
43.240.72.0/21
43.240.84.0/22
43.240.124.0/22
43.240.128.0/21
43.240.136.0/22
43.240.156.0/22
43.240.160.0/19
43.240.192.0/19
43.240.236.0/22
43.240.240.0/20
43.241.0.0/20
43.241.16.0/21
43.241.48.0/22
43.241.76.0/22
43.241.80.0/20
43.241.112.0/22
43.241.168.0/21
43.241.176.0/21
43.241.184.0/22
43.241.196.0/22
43.241.208.0/20
43.241.224.0/20
43.241.240.0/22
43.241.248.0/21
43.242.8.0/21
43.242.16.0/20
43.242.44.0/22
43.242.48.0/20
43.242.64.0/22
43.242.72.0/21
43.242.80.0/20
43.242.96.0/22
43.242.144.0/20
43.242.160.0/21
43.242.168.0/22
43.242.180.0/22
43.242.188.0/22
43.242.192.0/21
43.242.204.0/22
43.242.216.0/21
43.242.252.0/22
43.243.4.0/22
43.243.8.0/21
43.243.16.0/22
43.243.24.0/22
43.243.88.0/22
43.243.128.0/22
43.243.136.0/22
43.243.144.0/21
43.243.156.0/22
43.243.168.0/22
43.243.180.0/22
43.243.188.0/22
43.243.228.0/22
43.243.232.0/22
43.243.244.0/22
43.246.0.0/18
43.246.64.0/19
43.246.96.0/22
43.246.112.0/22
43.246.212.0/22
43.246.228.0/22
43.247.4.0/22
43.247.8.0/22
43.247.44.0/22
43.247.48.0/22
43.247.68.0/22
43.247.76.0/22
43.247.84.0/22
43.247.88.0/21
43.247.96.0/21
43.247.108.0/22
43.247.112.0/22
43.247.148.0/22
43.247.152.0/22
43.247.176.0/20
43.247.196.0/22
43.247.200.0/21
43.247.208.0/20
43.247.224.0/19
43.248.0.0/21
43.248.20.0/22
43.248.28.0/22
43.248.48.0/22
43.248.76.0/22
43.248.80.0/20
43.248.96.0/19
43.248.128.0/20
43.248.144.0/21
43.248.176.0/20
43.248.192.0/20
43.248.208.0/22
43.248.228.0/22
43.248.232.0/22
43.248.244.0/22
43.249.0.0/21
43.249.8.0/22
43.249.24.0/22
43.249.120.0/22
43.249.132.0/22
43.249.136.0/22
43.249.144.0/20
43.249.160.0/21
43.249.168.0/22
43.249.192.0/22
43.249.236.0/22
43.250.4.0/22
43.250.12.0/22
43.250.16.0/21
43.250.28.0/22
43.250.32.0/21
43.250.72.0/22
43.250.96.0/20
43.250.112.0/21
43.250.128.0/22
43.250.144.0/21
43.250.160.0/22
43.250.168.0/21
43.250.176.0/22
43.250.200.0/22
43.250.212.0/22
43.250.216.0/21
43.250.236.0/22
43.250.244.0/22
43.251.4.0/22
43.251.8.0/21
43.251.36.0/22
43.251.100.0/22
43.251.116.0/22
43.251.192.0/22
43.251.232.0/21
43.251.244.0/22
43.252.40.0/22
43.252.48.0/22
43.252.56.0/22
43.252.224.0/22
43.254.0.0/21
43.254.8.0/22
43.254.24.0/22
43.254.36.0/22
43.254.44.0/22
43.254.52.0/22
43.254.64.0/22
43.254.72.0/22
43.254.84.0/22
43.254.88.0/21
43.254.100.0/22
43.254.104.0/22
43.254.112.0/21
43.254.128.0/22
43.254.136.0/21
43.254.144.0/20
43.254.168.0/21
43.254.180.0/22
43.254.184.0/21
43.254.192.0/21
43.254.200.0/22
43.254.208.0/22
43.254.220.0/22
43.254.224.0/20
43.254.240.0/22
43.254.248.0/21
43.255.0.0/21
43.255.8.0/22
43.255.16.0/22
43.255.48.0/22
43.255.64.0/20
43.255.84.0/22
43.255.96.0/22
43.255.108.0/22
43.255.144.0/22
43.255.168.0/22
43.255.176.0/22
43.255.184.0/22
43.255.192.0/22
43.255.200.0/21
43.255.208.0/21
43.255.224.0/21
43.255.232.0/22
43.255.244.0/22
45.40.192.0/18
45.65.16.0/20
45.112.132.0/22
45.112.188.0/22
45.112.208.0/20
45.112.228.0/22
45.112.232.0/21
45.113.12.0/22
45.113.16.0/20
45.113.40.0/22
45.113.52.0/22
45.113.56.0/22
45.113.72.0/22
45.113.108.0/22
45.113.144.0/21
45.113.168.0/22
45.113.176.0/22
45.113.184.0/22
45.113.200.0/21
45.113.208.0/20
45.113.228.0/22
45.113.240.0/22
45.113.252.0/22
45.114.0.0/22
45.114.12.0/22
45.114.32.0/22
45.114.40.0/22
45.114.52.0/22
45.114.96.0/22
45.114.104.0/21
45.114.124.0/22
45.114.136.0/22
45.114.196.0/22
45.114.200.0/22
45.114.228.0/22
45.114.236.0/22
45.114.252.0/22
45.115.44.0/22
45.115.100.0/22
45.115.120.0/22
45.115.132.0/22
45.115.144.0/22
45.115.156.0/22
45.115.164.0/22
45.115.200.0/22
45.115.212.0/22
45.115.216.0/22
45.115.228.0/22
45.115.236.0/22
45.115.244.0/22
45.115.248.0/22
45.116.12.0/22
45.116.16.0/21
45.116.24.0/22
45.116.32.0/21
45.116.52.0/22
45.116.96.0/21
45.116.140.0/22
45.116.152.0/22
45.116.208.0/22
45.117.8.0/22
45.117.20.0/22
45.117.68.0/22
45.117.124.0/22
45.117.252.0/22
45.119.52.0/22
45.119.60.0/22
45.119.64.0/21
45.119.72.0/22
45.119.104.0/22
45.119.116.0/22
45.119.232.0/22
45.120.100.0/22
45.120.140.0/22
45.120.164.0/22
45.120.220.0/22
45.120.240.0/22
45.121.20.0/22
45.121.52.0/22
45.121.64.0/21
45.121.72.0/22
45.121.92.0/22
45.121.96.0/22
45.121.104.0/22
45.121.172.0/22
45.121.176.0/22
45.121.212.0/22
45.121.240.0/20
45.122.0.0/19
45.122.32.0/21
45.122.40.0/22
45.122.60.0/22
45.122.64.0/19
45.122.96.0/20
45.122.112.0/21
45.122.160.0/19
45.122.192.0/20
45.122.208.0/21
45.122.216.0/22
45.123.28.0/22
45.123.32.0/21
45.123.44.0/22
45.123.48.0/20
45.123.64.0/20
45.123.80.0/21
45.123.88.0/22
45.123.120.0/22
45.123.128.0/21
45.123.136.0/22
45.123.148.0/22
45.123.152.0/21
45.123.164.0/22
45.123.168.0/21
45.123.176.0/21
45.123.184.0/22
45.123.204.0/22
45.123.212.0/22
45.123.224.0/19
45.124.0.0/22
45.124.20.0/22
45.124.28.0/22
45.124.32.0/21
45.124.44.0/22
45.124.68.0/22
45.124.76.0/22
45.124.80.0/22
45.124.100.0/22
45.124.124.0/22
45.124.172.0/22
45.124.176.0/22
45.124.208.0/22
45.124.248.0/21
45.125.12.0/22
45.125.16.0/22
45.125.24.0/21
45.125.32.0/22
45.125.44.0/22
45.125.52.0/22
45.125.56.0/22
45.125.76.0/22
45.125.80.0/20
45.125.96.0/21
45.125.104.0/22
45.125.136.0/22
45.126.48.0/21
45.126.100.0/22
45.126.108.0/22
45.126.112.0/21
45.126.120.0/22
45.126.212.0/22
45.126.220.0/22
45.127.8.0/21
45.127.36.0/22
45.127.96.0/22
45.127.116.0/22
45.127.124.0/22
45.127.128.0/22
45.127.144.0/21
45.127.156.0/22
45.127.216.0/22
45.248.8.0/22
45.248.80.0/21
45.248.88.0/22
45.248.96.0/20
45.248.128.0/21
45.248.204.0/22
45.248.208.0/20
45.248.224.0/19
45.249.0.0/21
45.249.12.0/22
45.249.16.0/20
45.249.32.0/21
45.249.92.0/22
45.249.112.0/22
45.249.180.0/22
45.249.188.0/22
45.249.192.0/20
45.249.208.0/21
45.250.12.0/22
45.250.16.0/22
45.250.28.0/22
45.250.32.0/21
45.250.40.0/22
45.250.76.0/22
45.250.80.0/20
45.250.96.0/22
45.250.104.0/21
45.250.112.0/20
45.250.128.0/20
45.250.144.0/21
45.250.152.0/22
45.250.164.0/22
45.250.180.0/22
45.250.184.0/21
45.250.192.0/22
45.251.0.0/22
45.251.8.0/22
45.251.16.0/21
45.251.52.0/22
45.251.84.0/22
45.251.88.0/21
45.251.96.0/21
45.251.120.0/21
45.251.136.0/21
45.251.144.0/20
45.251.160.0/19
45.251.192.0/19
45.251.224.0/22
45.252.0.0/19
45.252.32.0/20
45.252.48.0/22
45.252.60.0/22
45.252.84.0/22
45.252.88.0/21
45.252.96.0/19
45.252.128.0/19
45.252.160.0/20
45.252.176.0/22
45.252.192.0/19
45.252.224.0/21
45.252.232.0/22
45.253.0.0/18
45.253.64.0/20
45.253.80.0/21
45.253.92.0/22
45.253.96.0/20
45.253.112.0/21
45.253.120.0/22
45.253.130.0/23
45.253.132.0/22
45.253.136.0/21
45.253.144.0/20
45.253.160.0/19
45.253.192.0/18
45.254.0.0/19
45.254.40.0/22
45.254.48.0/20
45.254.64.0/18
45.254.128.0/18
45.254.192.0/19
45.254.224.0/21
45.254.236.0/22
45.254.240.0/22
45.254.248.0/22
45.255.0.0/17
45.255.132.0/22
45.255.136.0/21
45.255.144.0/20
45.255.160.0/19
45.255.192.0/19
45.255.224.0/20
45.255.240.0/21
45.255.248.0/22
46.248.24.0/23
47.92.0.0/14
47.96.0.0/11
47.252.128.0/17
49.4.0.0/14
49.51.0.0/16
49.52.0.0/14
49.64.0.0/11
49.112.0.0/13
49.120.0.0/14
49.128.0.0/24
49.128.2.0/23
49.128.4.0/22
49.140.0.0/15
49.152.0.0/14
49.208.0.0/14
49.220.0.0/14
49.232.0.0/14
49.239.0.0/18
49.239.192.0/18
49.246.224.0/19
52.80.0.0/14
52.94.249.0/27
54.222.0.0/15
54.231.208.0/20
54.240.224.0/24
57.92.96.0/20
58.14.0.0/15
58.16.0.0/13
58.24.0.0/15
58.30.0.0/15
58.32.0.0/11
58.65.232.0/21
58.66.0.0/15
58.68.128.0/17
58.82.0.0/17
58.83.0.0/16
58.87.64.0/18
58.99.128.0/17
58.100.0.0/15
58.116.0.0/14
58.128.0.0/13
58.144.0.0/16
58.154.0.0/15
58.192.0.0/11
58.240.0.0/12
59.32.0.0/11
59.64.0.0/12
59.80.0.0/14
59.107.0.0/16
59.108.0.0/14
59.151.0.0/17
59.152.16.0/20
59.152.32.0/21
59.152.64.0/20
59.152.112.0/21
59.153.4.0/22
59.153.32.0/22
59.153.60.0/22
59.153.64.0/21
59.153.72.0/22
59.153.92.0/22
59.153.116.0/22
59.153.136.0/22
59.153.152.0/21
59.153.164.0/22
59.153.168.0/21
59.153.176.0/20
59.153.192.0/22
59.155.0.0/16
59.172.0.0/14
59.191.0.0/17
59.191.240.0/20
59.192.0.0/10
60.0.0.0/11
60.55.0.0/16
60.63.0.0/16
60.160.0.0/11
60.194.0.0/15
60.200.0.0/13
60.208.0.0/12
60.232.0.0/15
60.235.0.0/16
60.245.128.0/17
60.247.0.0/16
60.252.0.0/16
60.253.128.0/17
60.255.0.0/16
61.4.80.0/20
61.4.176.0/20
61.8.160.0/20
61.14.212.0/22
61.14.216.0/21
61.14.240.0/21
61.28.0.0/17
61.29.128.0/17
61.45.128.0/18
61.45.224.0/20
61.47.128.0/18
61.48.0.0/13
61.87.192.0/18
61.128.0.0/10
61.232.0.0/14
61.236.0.0/15
61.240.0.0/14
62.234.0.0/16
64.85.27.0/24
72.163.248.0/22
87.254.207.0/24
91.234.36.0/24
93.183.14.0/24
93.183.18.0/24
94.191.0.0/17
101.0.0.0/22
101.1.0.0/22
101.2.172.0/22
101.4.0.0/14
101.16.0.0/12
101.32.0.0/12
101.48.0.0/15
101.50.8.0/21
101.50.56.0/22
101.52.0.0/16
101.53.100.0/22
101.54.0.0/16
101.55.224.0/21
101.64.0.0/13
101.72.0.0/14
101.76.0.0/15
101.78.0.0/22
101.78.32.0/19
101.80.0.0/12
101.96.0.0/21
101.96.8.0/22
101.96.16.0/20
101.96.128.0/17
101.99.96.0/19
101.101.64.0/19
101.101.100.0/24
101.101.102.0/23
101.101.104.0/21
101.101.112.0/20
101.102.64.0/19
101.102.100.0/23
101.102.102.0/24
101.102.104.0/21
101.102.112.0/20
101.104.0.0/14
101.110.64.0/19
101.110.96.0/20
101.110.116.0/22
101.110.120.0/21
101.120.0.0/14
101.124.0.0/15
101.126.0.0/16
101.128.0.0/22
101.128.8.0/21
101.128.16.0/20
101.128.32.0/19
101.129.0.0/16
101.130.0.0/15
101.132.0.0/14
101.144.0.0/12
101.192.0.0/13
101.200.0.0/15
101.203.128.0/19
101.203.160.0/21
101.203.172.0/22
101.203.176.0/20
101.204.0.0/14
101.224.0.0/13
101.232.0.0/15
101.234.64.0/21
101.234.76.0/22
101.234.80.0/20
101.234.96.0/19
101.236.0.0/14
101.240.0.0/13
101.248.0.0/15
101.251.0.0/22
101.251.8.0/21
101.251.16.0/20
101.251.32.0/19
101.251.64.0/18
101.251.128.0/17
101.252.0.0/15
101.254.0.0/16
103.1.8.0/22
103.1.20.0/22
103.1.24.0/22
103.1.72.0/22
103.1.88.0/22
103.1.168.0/22
103.2.108.0/22
103.2.156.0/22
103.2.164.0/22
103.2.200.0/21
103.2.208.0/21
103.3.84.0/22
103.3.88.0/21
103.3.96.0/19
103.3.128.0/20
103.3.148.0/22
103.3.152.0/21
103.4.56.0/22
103.4.168.0/22
103.4.184.0/22
103.4.224.0/22
103.5.36.0/22
103.5.52.0/22
103.5.56.0/22
103.5.152.0/22
103.5.168.0/22
103.5.192.0/22
103.5.252.0/22
103.6.76.0/22
103.6.108.0/22
103.6.120.0/22
103.6.220.0/22
103.6.228.0/22
103.7.4.0/22
103.7.28.0/22
103.7.140.0/22
103.7.212.0/22
103.7.216.0/21
103.8.0.0/21
103.8.8.0/22
103.8.32.0/22
103.8.52.0/22
103.8.68.0/22
103.8.108.0/22
103.8.156.0/22
103.8.200.0/21
103.8.220.0/22
103.9.8.0/22
103.9.24.0/22
103.9.108.0/22
103.9.152.0/22
103.9.192.0/22
103.9.248.0/21
103.10.0.0/22
103.10.16.0/22
103.10.84.0/22
103.10.111.0/24
103.10.140.0/22
103.11.16.0/22
103.11.168.0/22
103.11.180.0/22
103.12.32.0/22
103.12.68.0/22
103.12.92.0/22
103.12.136.0/22
103.12.184.0/22
103.12.232.0/22
103.13.12.0/22
103.13.72.0/23
103.13.124.0/22
103.13.144.0/22
103.13.196.0/22
103.13.220.0/22
103.13.244.0/22
103.14.32.0/22
103.14.84.0/22
103.14.100.0/22
103.14.112.0/22
103.14.132.0/22
103.14.136.0/22
103.14.156.0/22
103.14.240.0/22
103.15.4.0/22
103.15.8.0/22
103.15.16.0/22
103.15.96.0/22
103.15.200.0/22
103.16.52.0/22
103.16.80.0/21
103.16.88.0/22
103.16.108.0/22
103.16.124.0/22
103.17.40.0/22
103.17.64.0/22
103.17.120.0/22
103.17.136.0/22
103.17.160.0/22
103.17.204.0/22
103.17.228.0/22
103.18.192.0/22
103.18.208.0/21
103.18.224.0/22
103.19.0.0/22
103.19.12.0/22
103.19.40.0/21
103.19.64.0/21
103.19.72.0/22
103.19.232.0/22
103.20.12.0/22
103.20.32.0/22
103.20.44.0/22
103.20.68.0/22
103.20.112.0/22
103.20.128.0/22
103.20.160.0/22
103.20.248.0/22
103.21.112.0/21
103.21.136.0/21
103.21.176.0/22
103.21.208.0/22
103.21.240.0/22
103.22.0.0/18
103.22.64.0/19
103.22.100.0/22
103.22.104.0/21
103.22.112.0/20
103.22.188.0/22
103.22.228.0/22
103.22.252.0/22
103.23.8.0/22
103.23.56.0/22
103.23.160.0/21
103.23.176.0/22
103.23.228.0/22
103.24.24.0/22
103.24.116.0/22
103.24.128.0/22
103.24.144.0/22
103.24.176.0/22
103.24.184.0/22
103.24.220.0/22
103.24.228.0/22
103.24.248.0/21
103.25.8.0/23
103.25.20.0/22
103.25.24.0/21
103.25.32.0/21
103.25.40.0/22
103.25.48.0/22
103.25.64.0/21
103.25.148.0/22
103.25.156.0/22
103.25.216.0/22
103.26.0.0/22
103.26.64.0/22
103.26.76.0/22
103.26.116.0/22
103.26.132.0/22
103.26.156.0/22
103.26.160.0/22
103.26.228.0/22
103.26.240.0/22
103.27.4.0/22
103.27.12.0/22
103.27.24.0/22
103.27.56.0/22
103.27.96.0/22
103.27.184.0/22
103.27.208.0/21
103.27.240.0/22
103.28.4.0/22
103.28.8.0/22
103.28.184.0/22
103.28.204.0/22
103.28.212.0/22
103.29.16.0/22
103.29.128.0/21
103.29.136.0/22
103.30.20.0/22
103.30.96.0/22
103.30.148.0/22
103.30.200.0/22
103.30.228.0/22
103.30.234.0/24
103.30.236.0/22
103.31.0.0/22
103.31.48.0/20
103.31.64.0/21
103.31.72.0/24
103.31.148.0/22
103.31.160.0/22
103.31.168.0/22
103.31.200.0/22
103.31.236.0/22
103.32.0.0/15
103.34.0.0/16
103.35.0.0/19
103.35.32.0/20
103.35.48.0/22
103.35.104.0/22
103.35.116.0/22
103.35.180.0/22
103.35.200.0/22
103.35.220.0/22
103.36.20.0/22
103.36.28.0/22
103.36.36.0/22
103.36.56.0/21
103.36.64.0/22
103.36.72.0/22
103.36.96.0/22
103.36.132.0/22
103.36.136.0/22
103.36.160.0/19
103.36.192.0/19
103.36.224.0/20
103.36.240.0/21
103.37.0.0/22
103.37.12.0/22
103.37.16.0/22
103.37.24.0/22
103.37.44.0/22
103.37.52.0/22
103.37.56.0/22
103.37.72.0/22
103.37.100.0/22
103.37.104.0/22
103.37.124.0/22
103.37.136.0/21
103.37.144.0/20
103.37.160.0/21
103.37.172.0/22
103.37.176.0/22
103.37.188.0/22
103.37.208.0/20
103.37.248.0/21
103.38.0.0/22
103.38.32.0/22
103.38.40.0/21
103.38.56.0/22
103.38.76.0/22
103.38.84.0/22
103.38.92.0/22
103.38.96.0/22
103.38.116.0/22
103.38.132.0/22
103.38.140.0/22
103.38.220.0/22
103.38.224.0/21
103.38.232.0/22
103.38.252.0/22
103.39.16.0/22
103.39.64.0/22
103.39.88.0/22
103.39.100.0/22
103.39.104.0/21
103.39.160.0/19
103.39.200.0/21
103.39.208.0/20
103.39.224.0/21
103.39.232.0/22
103.40.12.0/22
103.40.16.0/20
103.40.32.0/20
103.40.88.0/22
103.40.100.0/22
103.40.112.0/22
103.40.192.0/22
103.40.212.0/22
103.40.220.0/22
103.40.228.0/22
103.40.232.0/21
103.40.240.0/20
103.41.0.0/22
103.41.16.0/22
103.41.52.0/22
103.41.140.0/22
103.41.148.0/22
103.41.152.0/22
103.41.160.0/21
103.41.220.0/22
103.41.224.0/21
103.41.232.0/22
103.42.8.0/22
103.42.24.0/21
103.42.32.0/22
103.42.64.0/21
103.42.76.0/22
103.42.104.0/22
103.42.180.0/22
103.42.232.0/22
103.43.16.0/22
103.43.26.0/23
103.43.84.0/22
103.43.96.0/21
103.43.104.0/22
103.43.124.0/22
103.43.184.0/22
103.43.192.0/21
103.43.208.0/22
103.43.220.0/22
103.43.224.0/22
103.43.232.0/22
103.43.240.0/22
103.44.56.0/22
103.44.80.0/22
103.44.88.0/22
103.44.120.0/21
103.44.132.0/22
103.44.144.0/22
103.44.152.0/22
103.44.168.0/22
103.44.176.0/20
103.44.192.0/20
103.44.224.0/22
103.44.236.0/22
103.44.240.0/20
103.45.0.0/18
103.45.72.0/21
103.45.80.0/20
103.45.96.0/19
103.45.128.0/18
103.45.192.0/19
103.45.224.0/22
103.45.248.0/22
103.46.0.0/22
103.46.12.0/22
103.46.16.0/20
103.46.32.0/19
103.46.64.0/18
103.46.128.0/21
103.46.136.0/22
103.46.152.0/21
103.46.160.0/20
103.46.176.0/21
103.46.244.0/22
103.46.248.0/22
103.47.4.0/22
103.47.20.0/22
103.47.36.0/22
103.47.40.0/22
103.47.48.0/22
103.47.80.0/22
103.47.96.0/22
103.47.108.0/22
103.47.116.0/22
103.47.120.0/22
103.47.136.0/21
103.47.212.0/22
103.48.20.0/22
103.48.52.0/22
103.48.92.0/22
103.48.144.0/20
103.48.202.0/23
103.48.216.0/21
103.48.224.0/20
103.48.240.0/21
103.49.12.0/22
103.49.20.0/22
103.49.72.0/21
103.49.92.0/22
103.49.96.0/22
103.49.108.0/22
103.49.128.0/22
103.49.176.0/21
103.49.196.0/22
103.49.248.0/22
103.50.36.0/22
103.50.44.0/22
103.50.48.0/20
103.50.64.0/21
103.50.72.0/22
103.50.92.0/22
103.50.108.0/22
103.50.112.0/20
103.50.132.0/22
103.50.136.0/21
103.50.172.0/22
103.50.176.0/20
103.50.192.0/21
103.50.200.0/22
103.50.220.0/22
103.50.224.0/20
103.50.240.0/21
103.50.248.0/22
103.52.40.0/22
103.52.72.0/21
103.52.80.0/21
103.52.96.0/21
103.52.104.0/22
103.52.160.0/21
103.52.172.0/22
103.52.176.0/22
103.52.184.0/22
103.52.196.0/22
103.53.4.0/22
103.53.64.0/21
103.53.92.0/22
103.53.100.0/22
103.53.124.0/22
103.53.128.0/20
103.53.144.0/22
103.53.160.0/22
103.53.180.0/22
103.53.204.0/22
103.53.208.0/21
103.53.216.0/22
103.53.236.0/22
103.53.248.0/22
103.54.8.0/22
103.54.48.0/22
103.54.60.0/22
103.54.160.0/21
103.54.212.0/22
103.54.228.0/22
103.54.240.0/22
103.55.24.0/22
103.55.80.0/22
103.55.120.0/22
103.55.152.0/22
103.55.172.0/22
103.55.204.0/22
103.55.208.0/22
103.55.228.0/22
103.55.236.0/22
103.55.240.0/22
103.56.8.0/22
103.56.16.0/21
103.56.32.0/22
103.56.52.0/22
103.56.56.0/21
103.56.72.0/21
103.56.140.0/22
103.56.152.0/22
103.56.184.0/22
103.56.200.0/22
103.57.12.0/22
103.57.52.0/22
103.57.56.0/22
103.57.76.0/22
103.57.136.0/22
103.57.196.0/22
103.58.24.0/22
103.58.182.0/23
103.59.76.0/22
103.59.100.0/22
103.59.112.0/20
103.59.128.0/22
103.59.148.0/22
103.59.164.0/22
103.60.32.0/22
103.60.44.0/22
103.60.164.0/22
103.60.228.0/22
103.60.236.0/22
103.61.60.0/22
103.61.104.0/22
103.61.140.0/22
103.61.152.0/21
103.61.160.0/22
103.61.172.0/22
103.61.176.0/22
103.61.184.0/21
103.62.24.0/22
103.62.52.0/22
103.62.72.0/21
103.62.80.0/21
103.62.88.0/22
103.62.96.0/19
103.62.128.0/21
103.62.156.0/22
103.62.160.0/19
103.62.192.0/22
103.62.204.0/22
103.62.208.0/20
103.62.224.0/22
103.63.32.0/19
103.63.64.0/20
103.63.80.0/21
103.63.88.0/22
103.63.140.0/22
103.63.144.0/22
103.63.152.0/22
103.63.160.0/20
103.63.176.0/21
103.63.184.0/22
103.63.192.0/20
103.63.208.0/22
103.63.240.0/20
103.64.0.0/21
103.64.24.0/21
103.64.32.0/19
103.64.64.0/18
103.64.140.0/22
103.64.144.0/22
103.64.152.0/21
103.64.160.0/19
103.64.192.0/18
103.65.0.0/20
103.65.16.0/22
103.65.36.0/22
103.65.40.0/22
103.65.48.0/20
103.65.64.0/19
103.65.100.0/22
103.65.104.0/21
103.65.112.0/20
103.65.128.0/21
103.65.136.0/22
103.65.144.0/20
103.65.160.0/20
103.66.32.0/22
103.66.40.0/22
103.66.92.0/22
103.66.108.0/22
103.66.200.0/22
103.66.216.0/22
103.66.240.0/20
103.67.0.0/21
103.67.8.0/22
103.67.40.0/21
103.67.48.0/20
103.67.64.0/18
103.67.128.0/20
103.67.144.0/21
103.67.172.0/22
103.67.192.0/22
103.67.212.0/22
103.67.252.0/22
103.68.64.0/22
103.68.88.0/22
103.68.100.0/22
103.68.128.0/22
103.68.192.0/22
103.69.16.0/22
103.69.116.0/22
103.69.132.0/22
103.69.152.0/22
103.69.212.0/22
103.70.8.0/22
103.70.148.0/22
103.70.184.0/22
103.70.220.0/22
103.70.224.0/22
103.70.236.0/22
103.70.252.0/22
103.71.0.0/22
103.71.32.0/22
103.71.48.0/22
103.71.68.0/22
103.71.72.0/22
103.71.80.0/21
103.71.88.0/22
103.71.120.0/21
103.71.128.0/22
103.71.144.0/22
103.71.196.0/22
103.71.200.0/22
103.71.232.0/22
103.72.12.0/22
103.72.16.0/20
103.72.32.0/20
103.72.48.0/21
103.72.112.0/20
103.72.128.0/21
103.72.144.0/21
103.72.172.0/22
103.72.180.0/22
103.72.224.0/19
103.73.0.0/19
103.73.48.0/22
103.73.88.0/22
103.73.96.0/22
103.73.116.0/22
103.73.120.0/22
103.73.128.0/20
103.73.144.0/22
103.73.168.0/22
103.73.176.0/22
103.73.204.0/22
103.73.208.0/22
103.73.240.0/21
103.73.248.0/22
103.74.24.0/21
103.74.32.0/20
103.74.48.0/22
103.74.56.0/21
103.74.80.0/22
103.74.124.0/22
103.74.148.0/22
103.74.152.0/21
103.74.204.0/22
103.74.232.0/22
103.75.16.0/22
103.75.87.0/24
103.75.88.0/21
103.75.104.0/21
103.75.112.0/22
103.75.120.0/22
103.75.128.0/22
103.75.144.0/22
103.75.152.0/22
103.75.236.0/24
103.76.60.0/22
103.76.64.0/21
103.76.72.0/22
103.76.84.0/22
103.76.92.0/22
103.76.104.0/22
103.76.216.0/21
103.76.224.0/22
103.77.28.0/22
103.77.52.0/22
103.77.56.0/22
103.77.72.0/22
103.77.88.0/21
103.77.132.0/22
103.77.148.0/22
103.77.220.0/22
103.78.56.0/21
103.78.64.0/21
103.78.124.0/22
103.78.172.0/22
103.78.176.0/22
103.78.196.0/22
103.78.228.0/22
103.79.24.0/21
103.79.36.0/22
103.79.40.0/21
103.79.52.0/22
103.79.56.0/21
103.79.64.0/21
103.79.80.0/21
103.79.120.0/22
103.79.136.0/22
103.79.188.0/22
103.79.192.0/20
103.79.208.0/21
103.79.240.0/22
103.80.24.0/21
103.80.44.0/22
103.80.72.0/22
103.80.176.0/21
103.80.184.0/22
103.80.192.0/22
103.80.200.0/22
103.80.212.0/22
103.80.232.0/22
103.81.4.0/22
103.81.8.0/22
103.81.16.0/21
103.81.44.0/22
103.81.48.0/22
103.81.96.0/22
103.81.120.0/22
103.81.148.0/22
103.81.164.0/22
103.81.168.0/22
103.81.183.0/24
103.81.184.0/22
103.81.200.0/22
103.81.232.0/22
103.82.52.0/22
103.82.60.0/22
103.82.68.0/22
103.82.84.0/22
103.82.104.0/22
103.82.224.0/22
103.82.236.0/22
103.83.44.0/22
103.83.52.0/22
103.83.60.0/22
103.83.64.0/22
103.83.72.0/22
103.83.112.0/22
103.83.120.0/22
103.83.132.0/22
103.83.180.0/22
103.84.0.0/22
103.84.12.0/22
103.84.16.0/20
103.84.48.0/22
103.84.56.0/22
103.84.64.0/22
103.84.72.0/22
103.84.92.0/22
103.84.108.0/22
103.84.136.0/22
103.85.20.0/22
103.85.24.0/22
103.85.44.0/22
103.85.48.0/21
103.85.56.0/22
103.85.84.0/22
103.85.136.0/22
103.85.144.0/22
103.85.164.0/22
103.85.168.0/21
103.85.176.0/22
103.85.224.0/22
103.86.28.0/22
103.86.32.0/22
103.86.44.0/22
103.86.60.0/22
103.86.68.0/22
103.86.80.0/21
103.86.88.0/22
103.86.129.0/24
103.86.204.0/22
103.86.208.0/20
103.86.224.0/19
103.87.0.0/21
103.87.20.0/22
103.87.32.0/22
103.87.72.0/22
103.87.96.0/22
103.87.132.0/22
103.87.180.0/22
103.87.224.0/22
103.88.4.0/22
103.88.8.0/21
103.88.16.0/21
103.88.32.0/21
103.88.60.0/22
103.88.64.0/22
103.88.72.0/22
103.88.96.0/21
103.88.139.0/24
103.88.152.0/23
103.88.164.0/22
103.88.176.0/22
103.88.184.0/21
103.88.212.0/22
103.89.28.0/22
103.89.96.0/20
103.89.112.0/21
103.89.148.0/22
103.89.172.0/22
103.89.184.0/21
103.89.192.0/19
103.89.224.0/21
103.90.52.0/22
103.90.92.0/22
103.90.100.0/22
103.90.104.0/21
103.90.112.0/20
103.90.128.0/21
103.90.152.0/22
103.90.168.0/22
103.90.173.0/24
103.90.176.0/22
103.90.188.0/22
103.90.192.0/22
103.91.36.0/22
103.91.40.0/22
103.91.108.0/22
103.91.152.0/22
103.91.176.0/22
103.91.200.0/22
103.91.208.0/21
103.91.219.0/24
103.91.236.0/22
103.91.252.0/22
103.92.0.0/20
103.92.48.0/20
103.92.64.0/20
103.92.80.0/22
103.92.86.0/24
103.92.88.0/22
103.92.108.0/22
103.92.124.0/22
103.92.128.0/24
103.92.132.0/22
103.92.156.0/22
103.92.164.0/22
103.92.168.0/21
103.92.176.0/20
103.92.192.0/22
103.92.236.0/22
103.92.240.0/20
103.93.0.0/21
103.93.28.0/22
103.93.76.0/22
103.93.84.0/22
103.93.121.0/24
103.93.152.0/22
103.93.180.0/22
103.93.204.0/22
103.94.12.0/22
103.94.20.0/22
103.94.28.0/22
103.94.32.0/20
103.94.72.0/22
103.94.88.0/22
103.94.116.0/22
103.94.160.0/22
103.94.180.0/22
103.94.200.0/22
103.95.28.0/22
103.95.52.0/22
103.95.64.0/21
103.95.88.0/21
103.95.116.0/22
103.95.128.0/22
103.95.136.0/21
103.95.144.0/22
103.95.152.0/22
103.95.207.0/24
103.95.216.0/21
103.95.224.0/22
103.95.236.0/22
103.95.240.0/20
103.96.0.0/22
103.96.8.0/22
103.96.80.0/22
103.96.124.0/22
103.96.136.0/22
103.96.140.0/24
103.96.148.0/22
103.96.152.0/21
103.96.160.0/19
103.96.192.0/20
103.96.208.0/21
103.96.216.0/22
103.97.8.0/21
103.97.16.0/20
103.97.32.0/21
103.97.40.0/22
103.97.56.0/21
103.97.64.0/21
103.97.72.0/22
103.97.80.0/22
103.97.112.0/21
103.97.128.0/22
103.97.144.0/21
103.97.188.0/22
103.97.192.0/22
103.97.224.0/22
103.97.228.0/23
103.98.28.0/23
103.98.40.0/21
103.98.48.0/22
103.98.56.0/22
103.98.80.0/22
103.98.88.0/21
103.98.96.0/21
103.98.124.0/22
103.98.136.0/21
103.98.144.0/22
103.98.164.0/22
103.98.168.0/22
103.98.180.0/22
103.98.196.0/22
103.98.216.0/21
103.98.224.0/21
103.98.232.0/22
103.98.240.0/20
103.99.40.0/23
103.99.52.0/22
103.99.56.0/21
103.99.76.0/22
103.99.104.0/22
103.99.116.0/22
103.99.120.0/22
103.99.132.0/22
103.99.136.0/21
103.99.144.0/22
103.99.152.0/22
103.99.220.0/22
103.99.232.0/21
103.100.0.0/22
103.100.32.0/22
103.100.40.0/22
103.100.48.0/20
103.100.64.0/21
103.100.88.0/22
103.100.116.0/22
103.100.140.0/22
103.100.144.0/22
103.100.236.0/22
103.100.240.0/22
103.100.248.0/21
103.101.4.0/22
103.101.8.0/21
103.101.28.0/22
103.101.60.0/22
103.101.120.0/21
103.101.144.0/21
103.101.153.0/24
103.101.180.0/22
103.101.184.0/22
103.102.76.0/22
103.102.80.0/22
103.102.168.0/21
103.102.180.0/22
103.102.184.0/21
103.102.192.0/21
103.102.200.0/22
103.102.208.0/21
103.103.12.0/22
103.103.16.0/22
103.103.36.0/22
103.103.68.0/22
103.103.72.0/22
103.103.176.0/22
103.103.188.0/22
103.103.200.0/21
103.103.220.0/22
103.103.224.0/21
103.103.232.0/22
103.103.248.0/21
103.104.0.0/21
103.104.36.0/22
103.104.40.0/22
103.104.64.0/22
103.104.104.0/22
103.104.152.0/22
103.104.168.0/21
103.104.188.0/22
103.104.198.0/23
103.104.252.0/22
103.105.0.0/21
103.105.12.0/22
103.105.16.0/22
103.105.23.0/24
103.105.56.0/21
103.105.116.0/22
103.105.132.0/22
103.105.180.0/22
103.105.184.0/22
103.105.200.0/21
103.105.220.0/22
103.106.36.0/22
103.106.40.0/21
103.106.60.0/22
103.106.68.0/22
103.106.96.0/22
103.106.120.0/22
103.106.128.0/21
103.106.160.0/22
103.106.188.0/22
103.106.196.0/22
103.106.202.0/23
103.106.212.0/22
103.192.0.0/19
103.192.48.0/21
103.192.56.0/22
103.192.84.0/22
103.192.88.0/21
103.192.96.0/20
103.192.112.0/22
103.192.128.0/20
103.192.144.0/22
103.192.164.0/22
103.192.188.0/22
103.192.208.0/21
103.192.216.0/22
103.192.252.0/22
103.193.40.0/21
103.193.120.0/21
103.193.140.0/22
103.193.144.0/21
103.193.160.0/22
103.193.188.0/22
103.193.192.0/22
103.193.212.0/22
103.193.216.0/21
103.193.224.0/20
103.193.240.0/22
103.194.16.0/22
103.194.230.0/23
103.195.104.0/22
103.195.112.0/22
103.195.136.0/22
103.195.148.0/22
103.195.152.0/22
103.195.160.0/22
103.195.192.0/22
103.196.60.0/22
103.196.64.0/22
103.196.72.0/22
103.196.88.0/21
103.196.96.0/22
103.196.168.0/22
103.196.185.0/24
103.196.186.0/23
103.196.204.0/22
103.197.180.0/22
103.197.228.0/22
103.197.253.0/24
103.197.254.0/23
103.198.20.0/22
103.198.60.0/22
103.198.64.0/22
103.198.72.0/22
103.198.124.0/22
103.198.156.0/22
103.198.180.0/22
103.198.196.0/22
103.198.200.0/22
103.198.216.0/21
103.198.224.0/20
103.198.240.0/21
103.199.164.0/22
103.199.196.0/22
103.199.228.0/22
103.199.248.0/21
103.200.28.0/22
103.200.32.0/22
103.200.52.0/22
103.200.64.0/21
103.200.136.0/21
103.200.144.0/20
103.200.160.0/19
103.200.192.0/22
103.200.220.0/22
103.200.224.0/19
103.201.0.0/20
103.201.16.0/21
103.201.28.0/22
103.201.32.0/19
103.201.64.0/22
103.201.76.0/22
103.201.80.0/20
103.201.96.0/20
103.201.112.0/21
103.201.120.0/22
103.201.152.0/21
103.201.160.0/19
103.201.192.0/18
103.202.0.0/19
103.202.32.0/20
103.202.56.0/21
103.202.64.0/18
103.202.128.0/20
103.202.144.0/22
103.202.152.0/21
103.202.160.0/19
103.202.192.0/20
103.202.212.0/22
103.202.228.0/22
103.202.236.0/22
103.202.240.0/20
103.203.0.0/19
103.203.32.0/22
103.203.52.0/22
103.203.56.0/22
103.203.96.0/19
103.203.128.0/22
103.203.140.0/22
103.203.164.0/22
103.203.168.0/22
103.203.192.0/22
103.203.200.0/22
103.203.212.0/22
103.203.216.0/22
103.204.24.0/22
103.204.72.0/22
103.204.88.0/22
103.204.112.0/22
103.204.136.0/21
103.204.144.0/21
103.204.152.0/22
103.204.196.0/22
103.204.232.0/21
103.205.4.0/22
103.205.8.0/22
103.205.40.0/21
103.205.52.0/22
103.205.108.0/22
103.205.116.0/22
103.205.120.0/22
103.205.136.0/22
103.205.162.0/24
103.205.188.0/22
103.205.192.0/21
103.205.200.0/22
103.205.236.0/22
103.205.248.0/21
103.206.0.0/22
103.206.44.0/22
103.206.108.0/22
103.206.148.0/22
103.207.48.0/22
103.207.104.0/22
103.207.164.0/22
103.207.184.0/21
103.207.192.0/20
103.207.208.0/21
103.207.220.0/22
103.207.228.0/22
103.207.232.0/22
103.208.12.0/22
103.208.16.0/22
103.208.28.0/22
103.208.40.0/21
103.208.48.0/22
103.208.148.0/22
103.209.112.0/22
103.209.136.0/22
103.209.200.0/22
103.209.208.0/22
103.209.216.0/22
103.210.0.0/22
103.210.20.0/22
103.210.96.0/22
103.210.156.0/22
103.210.160.0/19
103.210.216.0/22
103.211.44.0/22
103.211.96.0/21
103.211.156.0/22
103.211.164.0/22
103.211.168.0/22
103.211.192.0/22
103.211.220.0/22
103.211.224.0/21
103.211.248.0/22
103.212.0.0/20
103.212.32.0/22
103.212.44.0/22
103.212.48.0/22
103.212.84.0/22
103.212.100.0/22
103.212.104.0/21
103.212.148.0/22
103.212.164.0/22
103.212.196.0/22
103.212.200.0/22
103.212.228.0/22
103.212.252.0/22
103.213.40.0/21
103.213.48.0/20
103.213.64.0/19
103.213.96.0/22
103.213.132.0/22
103.213.136.0/21
103.213.144.0/20
103.213.160.0/19
103.213.248.0/21
103.214.32.0/22
103.214.48.0/22
103.214.84.0/22
103.214.168.0/22
103.214.212.0/22
103.214.224.0/22
103.214.240.0/21
103.215.28.0/22
103.215.32.0/21
103.215.44.0/22
103.215.48.0/22
103.215.100.0/22
103.215.104.0/21
103.215.116.0/22
103.215.120.0/22
103.215.140.0/22
103.215.184.0/22
103.215.228.0/22
103.216.4.0/22
103.216.8.0/21
103.216.16.0/20
103.216.32.0/20
103.216.64.0/22
103.216.108.0/22
103.216.136.0/22
103.216.152.0/22
103.216.224.0/21
103.216.240.0/20
103.217.0.0/18
103.217.168.0/22
103.217.180.0/22
103.217.184.0/21
103.217.192.0/20
103.218.0.0/22
103.218.8.0/21
103.218.16.0/21
103.218.28.0/22
103.218.32.0/19
103.218.64.0/19
103.218.184.0/22
103.218.192.0/20
103.218.208.0/21
103.218.216.0/22
103.219.24.0/21
103.219.32.0/21
103.219.64.0/22
103.219.84.0/22
103.219.88.0/21
103.219.96.0/21
103.219.176.0/22
103.219.184.0/22
103.220.48.0/20
103.220.64.0/22
103.220.92.0/22
103.220.96.0/20
103.220.116.0/22
103.220.120.0/21
103.220.128.0/20
103.220.144.0/21
103.220.152.0/22
103.220.160.0/19
103.220.192.0/21
103.220.200.0/22
103.220.240.0/20
103.221.0.0/19
103.221.32.0/20
103.221.48.0/22
103.221.88.0/21
103.221.96.0/19
103.221.128.0/18
103.221.192.0/20
103.222.0.0/20
103.222.16.0/22
103.222.24.0/21
103.222.32.0/19
103.222.64.0/18
103.222.128.0/18
103.222.192.0/19
103.222.224.0/21
103.222.232.0/22
103.222.240.0/21
103.223.16.0/20
103.223.32.0/19
103.223.64.0/18
103.223.128.0/21
103.223.140.0/22
103.223.144.0/20
103.223.160.0/20
103.223.176.0/21
103.223.188.0/22
103.223.192.0/18
103.224.0.0/22
103.224.16.0/22
103.224.40.0/21
103.224.60.0/22
103.224.80.0/22
103.224.220.0/22
103.224.224.0/21
103.224.232.0/22
103.225.84.0/22
103.226.16.0/22
103.226.40.0/22
103.226.56.0/21
103.226.80.0/22
103.226.116.0/22
103.226.132.0/22
103.226.156.0/22
103.226.180.0/22
103.226.196.0/22
103.227.48.0/22
103.227.72.0/21
103.227.80.0/22
103.227.100.0/22
103.227.120.0/22
103.227.132.0/22
103.227.136.0/22
103.227.196.0/22
103.227.204.0/22
103.227.212.0/22
103.227.228.0/22
103.228.12.0/22
103.228.28.0/22
103.228.68.0/22
103.228.88.0/22
103.228.128.0/22
103.228.136.0/22
103.228.160.0/22
103.228.176.0/22
103.228.204.0/22
103.228.208.0/22
103.228.228.0/22
103.228.232.0/22
103.229.20.0/22
103.229.60.0/22
103.229.136.0/22
103.229.148.0/22
103.229.172.0/22
103.229.212.0/22
103.229.216.0/21
103.229.228.0/22
103.229.236.0/22
103.229.240.0/22
103.230.0.0/22
103.230.28.0/22
103.230.40.0/21
103.230.96.0/22
103.230.196.0/22
103.230.200.0/21
103.230.212.0/22
103.230.236.0/22
103.231.16.0/21
103.231.64.0/21
103.231.144.0/22
103.231.180.0/22
103.231.184.0/22
103.231.244.0/22
103.232.4.0/22
103.232.144.0/22
103.232.188.0/22
103.232.212.0/22
103.233.4.0/22
103.233.44.0/22
103.233.52.0/22
103.233.104.0/22
103.233.128.0/22
103.233.136.0/22
103.233.228.0/22
103.234.0.0/22
103.234.20.0/22
103.234.56.0/22
103.234.124.0/22
103.234.128.0/22
103.234.172.0/22
103.234.180.0/22
103.234.244.0/22
103.235.16.0/22
103.235.48.0/22
103.235.56.0/21
103.235.80.0/21
103.235.128.0/20
103.235.144.0/21
103.235.184.0/22
103.235.192.0/22
103.235.200.0/22
103.235.220.0/22
103.235.224.0/19
103.236.0.0/18
103.236.64.0/19
103.236.96.0/22
103.236.120.0/22
103.236.184.0/22
103.236.220.0/22
103.236.232.0/22
103.236.240.0/20
103.237.0.0/20
103.237.24.0/21
103.237.68.0/22
103.237.88.0/22
103.237.152.0/22
103.237.176.0/20
103.237.192.0/18
103.238.0.0/21
103.238.16.0/20
103.238.32.0/20
103.238.48.0/21
103.238.56.0/22
103.238.88.0/21
103.238.96.0/22
103.238.132.0/22
103.238.140.0/22
103.238.144.0/22
103.238.160.0/19
103.238.196.0/22
103.238.204.0/22
103.238.252.0/22
103.239.0.0/22
103.239.44.0/22
103.239.68.0/22
103.239.96.0/22
103.239.152.0/21
103.239.176.0/21
103.239.184.0/22
103.239.192.0/21
103.239.204.0/22
103.239.208.0/22
103.239.224.0/22
103.239.244.0/22
103.240.16.0/22
103.240.36.0/22
103.240.72.0/22
103.240.84.0/22
103.240.124.0/22
103.240.156.0/22
103.240.172.0/22
103.240.188.0/22
103.240.244.0/22
103.241.12.0/22
103.241.72.0/22
103.241.92.0/22
103.241.96.0/22
103.241.160.0/22
103.241.184.0/21
103.241.220.0/22
103.242.64.0/22
103.242.128.0/21
103.242.160.0/22
103.242.168.0/21
103.242.176.0/22
103.242.200.0/22
103.242.212.0/22
103.242.220.0/22
103.242.240.0/22
103.243.136.0/22
103.243.252.0/22
103.244.16.0/22
103.244.58.0/23
103.244.60.0/22
103.244.64.0/20
103.244.80.0/21
103.244.116.0/22
103.244.164.0/22
103.244.232.0/22
103.244.252.0/22
103.245.23.0/24
103.245.52.0/22
103.245.60.0/22
103.245.80.0/22
103.245.124.0/22
103.245.128.0/22
103.246.8.0/21
103.246.120.0/21
103.246.132.0/22
103.246.152.0/21
103.247.168.0/21
103.247.176.0/22
103.247.200.0/22
103.247.212.0/22
103.248.0.0/23
103.248.64.0/22
103.248.100.0/22
103.248.124.0/22
103.248.152.0/22
103.248.168.0/22
103.248.192.0/22
103.248.212.0/22
103.248.220.0/22
103.248.224.0/21
103.249.8.0/21
103.249.52.0/22
103.249.104.0/22
103.249.128.0/22
103.249.136.0/22
103.249.144.0/22
103.249.164.0/22
103.249.168.0/21
103.249.176.0/22
103.249.188.0/22
103.249.192.0/22
103.249.244.0/22
103.249.252.0/22
103.250.32.0/22
103.250.104.0/22
103.250.124.0/22
103.250.180.0/22
103.250.192.0/22
103.250.216.0/22
103.250.224.0/22
103.250.236.0/22
103.250.248.0/21
103.251.32.0/21
103.251.84.0/22
103.251.96.0/22
103.251.124.0/22
103.251.128.0/22
103.251.160.0/22
103.251.192.0/22
103.251.204.0/22
103.251.236.0/22
103.251.240.0/22
103.252.28.0/22
103.252.36.0/22
103.252.64.0/22
103.252.96.0/22
103.252.104.0/22
103.252.172.0/22
103.252.204.0/22
103.252.208.0/22
103.252.232.0/22
103.252.248.0/22
103.253.4.0/22
103.253.60.0/22
103.253.204.0/22
103.253.220.0/22
103.253.224.0/22
103.253.232.0/22
103.254.8.0/22
103.254.20.0/22
103.254.64.0/20
103.254.112.0/22
103.254.176.0/22
103.254.188.0/22
103.254.196.0/24
103.254.220.0/22
103.255.56.0/22
103.255.68.0/22
103.255.88.0/21
103.255.136.0/21
103.255.184.0/22
103.255.200.0/22
103.255.208.0/21
103.255.228.0/22
104.166.103.0/24
104.222.196.0/24
106.0.0.0/24
106.0.2.0/23
106.0.4.0/22
106.0.8.0/21
106.0.16.0/20
106.0.44.0/22
106.0.64.0/18
106.2.0.0/15
106.4.0.0/14
106.8.0.0/15
106.11.0.0/16
106.12.0.0/14
106.16.0.0/12
106.32.0.0/12
106.48.0.0/15
106.50.0.0/16
106.52.0.0/14
106.56.0.0/13
106.74.0.0/15
106.80.0.0/12
106.108.0.0/14
106.112.0.0/12
106.224.0.0/12
107.153.91.0/24
107.153.92.0/23
109.71.4.0/24
109.244.0.0/16
110.6.0.0/15
110.16.0.0/14
110.34.40.0/21
110.40.0.0/14
110.44.12.0/22
110.44.144.0/20
110.48.0.0/16
110.51.0.0/16
110.52.0.0/15
110.56.0.0/13
110.64.0.0/15
110.72.0.0/15
110.75.0.0/16
110.76.0.0/18
110.76.132.0/22
110.76.156.0/22
110.76.184.0/22
110.76.192.0/18
110.77.0.0/17
110.80.0.0/13
110.88.0.0/14
110.92.68.0/22
110.93.32.0/19
110.94.0.0/15
110.96.0.0/11
110.152.0.0/14
110.156.0.0/15
110.165.32.0/19
110.166.0.0/15
110.172.192.0/18
110.173.0.0/19
110.173.32.0/20
110.173.64.0/18
110.173.192.0/19
110.176.0.0/12
110.192.0.0/11
110.228.0.0/14
110.232.32.0/19
110.236.0.0/15
110.240.0.0/12
111.0.0.0/10
111.66.0.0/16
111.67.192.0/20
111.68.64.0/19
111.72.0.0/13
111.85.0.0/16
111.91.192.0/19
111.92.248.0/21
111.112.0.0/14
111.116.0.0/15
111.118.200.0/21
111.119.64.0/18
111.119.128.0/19
111.120.0.0/14
111.124.0.0/16
111.126.0.0/15
111.128.0.0/11
111.160.0.0/13
111.170.0.0/16
111.172.0.0/14
111.176.0.0/13
111.186.0.0/15
111.192.0.0/12
111.208.0.0/13
111.221.28.0/24
111.221.128.0/17
111.222.0.0/16
111.223.4.0/22
111.223.8.0/21
111.223.16.0/22
111.223.240.0/22
111.223.248.0/22
111.224.0.0/13
111.235.96.0/19
111.235.156.0/22
111.235.160.0/19
112.0.0.0/10
112.64.0.0/14
112.73.0.0/16
112.74.0.0/15
112.80.0.0/12
112.96.0.0/13
112.109.128.0/17
112.111.0.0/16
112.112.0.0/14
112.116.0.0/15
112.122.0.0/15
112.124.0.0/14
112.128.0.0/14
112.132.0.0/16
112.137.48.0/21
112.192.0.0/14
112.224.0.0/11
113.0.0.0/13
113.8.0.0/15
113.11.192.0/19
113.12.0.0/14
113.16.0.0/15
113.18.0.0/16
113.21.232.0/21
113.24.0.0/14
113.31.0.0/16
113.44.0.0/14
113.48.0.0/14
113.52.160.0/19
113.52.228.0/22
113.54.0.0/15
113.56.0.0/15
113.58.0.0/16
113.59.0.0/17
113.59.224.0/22
113.62.0.0/15
113.64.0.0/10
113.128.0.0/15
113.130.96.0/20
113.130.112.0/21
113.132.0.0/14
113.136.0.0/13
113.194.0.0/15
113.197.100.0/22
113.200.0.0/15
113.202.0.0/16
113.204.0.0/14
113.208.96.0/19
113.208.128.0/17
113.209.0.0/16
113.212.0.0/18
113.212.100.0/22
113.212.184.0/21
113.213.0.0/17
113.214.0.0/15
113.218.0.0/15
113.220.0.0/14
113.224.0.0/12
113.240.0.0/13
113.248.0.0/14
114.28.0.0/16
114.31.64.0/21
114.54.0.0/15
114.60.0.0/14
114.64.0.0/14
114.68.0.0/16
114.79.64.0/18
114.80.0.0/12
114.96.0.0/13
114.104.0.0/14
114.110.0.0/20
114.110.64.0/18
114.111.0.0/19
114.111.160.0/19
114.112.0.0/13
114.132.0.0/16
114.135.0.0/16
114.138.0.0/15
114.141.64.0/21
114.141.80.0/21
114.141.128.0/18
114.196.0.0/15
114.198.248.0/21
114.208.0.0/12
114.224.0.0/11
115.24.0.0/14
115.28.0.0/15
115.31.64.0/20
115.32.0.0/14
115.42.56.0/22
115.44.0.0/14
115.48.0.0/12
115.69.64.0/20
115.84.0.0/18
115.84.192.0/19
115.85.192.0/18
115.100.0.0/14
115.104.0.0/14
115.120.0.0/14
115.124.16.0/20
115.148.0.0/14
115.152.0.0/13
115.166.64.0/19
115.168.0.0/13
115.180.0.0/14
115.187.0.0/20
115.190.0.0/15
115.192.0.0/11
115.224.0.0/12
116.0.8.0/21
116.0.24.0/21
116.1.0.0/16
116.2.0.0/15
116.4.0.0/14
116.8.0.0/14
116.13.0.0/16
116.16.0.0/12
116.50.0.0/20
116.52.0.0/14
116.56.0.0/15
116.58.128.0/20
116.58.208.0/20
116.60.0.0/14
116.66.0.0/17
116.66.176.0/22
116.68.136.0/21
116.68.176.0/21
116.69.0.0/16
116.70.0.0/17
116.76.0.0/14
116.85.0.0/16
116.89.144.0/20
116.89.240.0/22
116.90.80.0/20
116.90.184.0/21
116.95.0.0/16
116.112.0.0/14
116.116.0.0/15
116.128.0.0/10
116.192.0.0/16
116.193.16.0/20
116.193.32.0/19
116.193.152.0/22
116.193.164.0/22
116.193.176.0/21
116.194.0.0/15
116.196.0.0/16
116.197.160.0/21
116.197.180.0/23
116.198.0.0/16
116.199.0.0/17
116.199.128.0/19
116.204.0.0/15
116.206.92.0/22
116.206.100.0/22
116.206.176.0/22
116.207.0.0/16
116.208.0.0/14
116.212.160.0/20
116.213.40.0/21
116.213.64.0/18
116.213.128.0/17
116.214.32.0/19
116.214.64.0/20
116.214.128.0/17
116.215.0.0/16
116.216.0.0/14
116.224.0.0/12
116.242.0.0/15
116.244.0.0/14
116.248.0.0/15
116.251.64.0/18
116.252.0.0/15
116.254.104.0/21
116.254.128.0/17
116.255.128.0/17
117.8.0.0/13
117.21.0.0/16
117.22.0.0/15
117.24.0.0/13
117.32.0.0/13
117.40.0.0/14
117.44.0.0/15
117.48.0.0/14
117.53.48.0/20
117.53.176.0/20
117.57.0.0/16
117.58.0.0/17
117.59.0.0/16
117.60.0.0/14
117.64.0.0/13
117.72.0.0/15
117.74.64.0/19
117.74.128.0/17
117.75.0.0/16
117.76.0.0/14
117.80.0.0/12
117.100.0.0/15
117.103.16.0/20
117.103.40.0/21
117.103.72.0/21
117.103.128.0/20
117.104.168.0/21
117.104.188.0/24
117.106.0.0/15
117.112.0.0/13
117.120.64.0/18
117.120.128.0/17
117.121.0.0/17
117.121.128.0/18
117.121.192.0/21
117.122.128.0/17
117.124.0.0/14
117.128.0.0/10
118.24.0.0/15
118.26.0.0/16
118.28.0.0/14
118.64.0.0/15
118.66.0.0/16
118.67.112.0/20
118.72.0.0/13
118.80.0.0/15
118.84.0.0/15
118.88.32.0/19
118.88.64.0/18
118.88.128.0/17
118.89.0.0/16
118.91.240.0/20
118.102.16.0/20
118.102.32.0/21
118.103.164.0/22
118.103.168.0/21
118.103.176.0/22
118.103.245.0/24
118.103.246.0/23
118.107.180.0/22
118.112.0.0/13
118.120.0.0/14
118.124.0.0/15
118.126.0.0/16
118.127.128.0/19
118.132.0.0/14
118.144.0.0/14
118.178.0.0/16
118.180.0.0/14
118.184.0.0/16
118.186.0.0/15
118.188.0.0/16
118.190.0.0/15
118.192.0.0/16
118.193.0.0/20
118.193.32.0/19
118.193.64.0/20
118.193.96.0/19
118.193.128.0/17
118.194.0.0/15
118.196.0.0/14
118.202.0.0/15
118.204.0.0/14
118.212.0.0/15
118.215.192.0/18
118.224.0.0/14
118.228.0.0/15
118.230.0.0/16
118.239.0.0/16
118.242.0.0/16
118.244.0.0/14
118.248.0.0/13
119.0.0.0/15
119.2.0.0/19
119.2.128.0/17
119.3.0.0/16
119.4.0.0/14
119.8.0.0/16
119.10.0.0/17
119.15.136.0/21
119.16.0.0/16
119.18.192.0/20
119.18.208.0/21
119.18.224.0/19
119.19.0.0/16
119.20.0.0/14
119.27.64.0/18
119.27.128.0/17
119.28.0.0/15
119.30.48.0/20
119.31.192.0/19
119.32.0.0/13
119.40.0.0/18
119.40.64.0/20
119.40.128.0/17
119.41.0.0/16
119.42.0.0/19
119.42.52.0/22
119.42.128.0/20
119.42.224.0/19
119.44.0.0/15
119.48.0.0/13
119.57.0.0/16
119.58.0.0/16
119.59.128.0/17
119.60.0.0/15
119.62.0.0/16
119.63.32.0/19
119.75.208.0/20
119.78.0.0/15
119.80.0.0/16
119.82.208.0/20
119.84.0.0/14
119.88.0.0/14
119.96.0.0/13
119.108.0.0/15
119.112.0.0/12
119.128.0.0/12
119.144.0.0/14
119.148.160.0/19
119.151.192.0/18
119.160.200.0/21
119.161.120.0/21
119.161.128.0/17
119.162.0.0/15
119.164.0.0/14
119.176.0.0/12
119.232.0.0/15
119.235.128.0/18
119.248.0.0/14
119.252.96.0/21
119.252.240.0/20
119.253.0.0/16
119.254.0.0/15
120.0.0.0/12
120.24.0.0/14
120.30.0.0/15
120.32.0.0/12
120.48.0.0/15
120.52.0.0/14
120.64.0.0/13
120.72.32.0/19
120.72.128.0/17
120.76.0.0/14
120.80.0.0/13
120.88.8.0/21
120.90.0.0/15
120.92.0.0/16
120.94.0.0/15
120.128.0.0/13
120.136.16.0/21
120.136.128.0/18
120.137.0.0/17
120.143.128.0/19
120.192.0.0/10
121.0.8.0/21
121.0.16.0/20
121.4.0.0/15
121.8.0.0/13
121.16.0.0/12
121.32.0.0/13
121.40.0.0/14
121.46.0.0/18
121.46.76.0/22
121.46.128.0/17
121.47.0.0/16
121.48.0.0/15
121.50.8.0/21
121.51.0.0/16
121.52.160.0/19
121.52.208.0/20
121.52.224.0/19
121.54.176.0/21
121.54.188.0/22
121.55.0.0/18
121.56.0.0/15
121.58.0.0/17
121.58.136.0/21
121.58.144.0/20
121.58.160.0/21
121.59.0.0/16
121.60.0.0/14
121.68.0.0/14
121.76.0.0/15
121.79.128.0/18
121.89.0.0/16
121.100.128.0/17
121.101.0.0/18
121.101.208.0/20
121.192.0.0/13
121.200.192.0/21
121.201.0.0/16
121.204.0.0/14
121.224.0.0/12
121.248.0.0/14
121.255.0.0/16
122.0.64.0/18
122.0.128.0/17
122.4.0.0/14
122.8.0.0/15
122.10.128.0/17
122.11.0.0/17
122.12.0.0/15
122.14.0.0/16
122.48.0.0/16
122.49.0.0/18
122.51.0.0/16
122.64.0.0/11
122.96.0.0/15
122.98.144.0/20
122.98.160.0/21
122.98.172.0/22
122.98.176.0/20
122.98.192.0/21
122.98.232.0/21
122.98.240.0/20
122.102.0.0/20
122.102.64.0/19
122.112.0.0/14
122.119.0.0/16
122.128.100.0/22
122.128.120.0/21
122.136.0.0/13
122.144.128.0/17
122.152.192.0/18
122.156.0.0/14
122.188.0.0/14
122.192.0.0/14
122.198.0.0/16
122.200.40.0/21
122.200.64.0/18
122.201.48.0/20
122.204.0.0/14
122.224.0.0/12
122.240.0.0/13
122.248.24.0/21
122.248.48.0/20
122.255.64.0/21
123.0.128.0/18
123.4.0.0/14
123.8.0.0/13
123.49.128.0/17
123.50.160.0/19
123.52.0.0/14
123.56.0.0/14
123.60.0.0/15
123.62.0.0/16
123.64.0.0/11
123.96.0.0/15
123.98.0.0/17
123.99.128.0/17
123.100.0.0/19
123.100.232.0/24
123.101.0.0/16
123.103.0.0/17
123.108.128.0/20
123.108.208.0/20
123.112.0.0/12
123.128.0.0/13
123.136.80.0/20
123.137.0.0/16
123.138.0.0/15
123.144.0.0/12
123.160.0.0/12
123.176.60.0/22
123.176.80.0/20
123.177.0.0/16
123.178.0.0/15
123.180.0.0/14
123.184.0.0/13
123.196.0.0/15
123.199.128.0/17
123.206.0.0/15
123.232.0.0/14
123.242.0.0/17
123.242.192.0/21
123.244.0.0/14
123.249.0.0/16
123.253.0.0/16
123.254.96.0/21
124.6.64.0/18
124.14.0.0/15
124.16.0.0/15
124.20.0.0/14
124.28.192.0/18
124.29.0.0/17
124.31.0.0/16
124.40.112.0/20
124.40.128.0/18
124.40.192.0/19
124.40.240.0/22
124.42.0.0/16
124.47.0.0/18
124.64.0.0/15
124.66.0.0/17
124.67.0.0/16
124.68.0.0/14
124.72.0.0/13
124.88.0.0/13
124.108.8.0/21
124.108.40.0/21
124.109.96.0/21
124.112.0.0/13
124.126.0.0/15
124.128.0.0/13
124.147.128.0/17
124.150.137.0/24
124.151.0.0/16
124.152.0.0/16
124.156.0.0/16
124.160.0.0/13
124.172.0.0/14
124.192.0.0/15
124.196.0.0/16
124.200.0.0/13
124.220.0.0/14
124.224.0.0/12
124.240.0.0/17
124.240.128.0/18
124.242.0.0/16
124.243.192.0/18
124.248.0.0/17
124.249.0.0/16
124.250.0.0/15
124.254.0.0/18
125.31.192.0/18
125.32.0.0/12
125.58.128.0/17
125.61.128.0/17
125.62.0.0/18
125.64.0.0/11
125.96.0.0/15
125.98.0.0/16
125.104.0.0/13
125.112.0.0/12
125.169.0.0/16
125.171.0.0/16
125.208.0.0/18
125.210.0.0/15
125.213.0.0/17
125.214.96.0/19
125.215.0.0/18
125.216.0.0/13
125.254.128.0/17
128.108.0.0/16
129.28.0.0/16
129.204.0.0/16
129.211.0.0/16
129.223.254.0/24
131.228.96.0/24
132.232.0.0/16
132.237.134.0/24
132.237.150.0/24
134.175.0.0/16
135.159.208.0/20
135.244.80.0/20
137.59.59.0/24
137.59.88.0/22
138.32.244.0/22
139.5.56.0/21
139.5.80.0/22
139.5.92.0/22
139.5.108.0/22
139.5.128.0/22
139.5.160.0/22
139.5.192.0/22
139.5.204.0/22
139.5.208.0/21
139.5.244.0/22
139.9.0.0/16
139.129.0.0/16
139.148.0.0/16
139.155.0.0/16
139.159.0.0/16
139.170.0.0/16
139.176.0.0/16
139.183.0.0/16
139.186.0.0/16
139.189.0.0/16
139.196.0.0/14
139.200.0.0/13
139.208.0.0/13
139.217.0.0/16
139.219.0.0/16
139.220.0.0/15
139.224.0.0/16
139.226.0.0/15
140.75.0.0/16
140.101.208.0/24
140.143.0.0/16
140.205.0.0/16
140.206.0.0/15
140.210.0.0/16
140.224.0.0/16
140.237.0.0/16
140.240.0.0/16
140.242.216.0/24
140.242.223.0/24
140.242.224.0/24
140.243.0.0/16
140.246.0.0/16
140.249.0.0/16
140.250.0.0/16
140.255.0.0/16
144.0.0.0/16
144.7.0.0/16
144.12.0.0/16
144.36.146.0/23
144.48.8.0/21
144.48.56.0/22
144.48.64.0/22
144.48.88.0/22
144.48.156.0/22
144.48.172.0/22
144.48.180.0/22
144.48.184.0/22
144.48.204.0/22
144.48.208.0/21
144.48.220.0/22
144.48.252.0/22
144.52.0.0/16
144.123.0.0/16
144.211.80.0/24
144.211.138.0/24
144.255.0.0/16
146.56.192.0/18
146.196.56.0/22
146.196.68.0/22
146.196.72.0/21
146.196.92.0/22
146.196.112.0/21
146.196.124.0/22
146.217.137.0/24
146.222.79.0/24
146.222.81.0/24
146.222.94.0/24
148.70.0.0/16
150.0.0.0/16
150.109.0.0/16
150.115.0.0/16
150.121.0.0/16
150.122.0.0/16
150.129.136.0/22
150.129.192.0/22
150.129.216.0/22
150.129.252.0/22
150.138.0.0/15
150.223.0.0/16
150.242.0.0/21
150.242.8.0/22
150.242.28.0/22
150.242.44.0/22
150.242.48.0/21
150.242.56.0/22
150.242.76.0/22
150.242.80.0/22
150.242.92.0/22
150.242.96.0/22
150.242.112.0/21
150.242.120.0/22
150.242.152.0/21
150.242.160.0/21
150.242.168.0/22
150.242.184.0/21
150.242.192.0/22
150.242.212.0/22
150.242.224.0/20
150.242.240.0/21
150.242.248.0/22
150.255.0.0/16
152.104.128.0/17
152.136.0.0/16
153.0.0.0/16
153.3.0.0/16
153.34.0.0/15
153.36.0.0/15
153.99.0.0/16
153.101.0.0/16
153.118.0.0/15
154.8.128.0/17
156.107.160.0/24
156.107.170.0/24
157.0.0.0/16
157.18.0.0/16
157.61.0.0/16
157.119.0.0/22
157.119.8.0/21
157.119.16.0/22
157.119.28.0/22
157.119.68.0/22
157.119.112.0/22
157.119.132.0/22
157.119.136.0/21
157.119.144.0/20
157.119.160.0/21
157.119.172.0/22
157.119.192.0/21
157.119.240.0/22
157.119.252.0/22
157.122.0.0/16
157.133.186.0/23
157.133.192.0/21
157.133.212.0/24
157.133.236.0/24
157.148.0.0/16
157.156.0.0/16
157.255.0.0/16
159.153.120.0/22
159.226.0.0/16
160.19.208.0/21
160.19.216.0/22
160.20.48.0/22
160.62.10.0/24
160.83.109.0/24
160.83.110.0/23
160.202.60.0/22
160.202.148.0/22
160.202.152.0/22
160.202.168.0/22
160.202.212.0/22
160.202.216.0/21
160.202.224.0/19
160.238.64.0/22
161.163.0.0/21
161.163.28.0/23
161.163.176.0/24
161.163.178.0/23
161.163.180.0/22
161.207.0.0/16
162.62.0.0/16
162.105.0.0/16
163.0.0.0/16
163.47.4.0/22
163.53.0.0/20
163.53.36.0/22
163.53.40.0/21
163.53.48.0/20
163.53.64.0/22
163.53.88.0/21
163.53.96.0/19
163.53.128.0/21
163.53.136.0/22
163.53.160.0/20
163.53.188.0/22
163.53.220.0/22
163.53.236.0/22
163.53.240.0/22
163.125.0.0/16
163.142.0.0/16
163.177.0.0/16
163.179.0.0/16
163.204.0.0/16
163.244.246.0/24
164.52.0.0/17
165.156.30.0/24
166.111.0.0/16
167.139.0.0/16
167.189.0.0/16
167.220.244.0/22
168.159.144.0/21
168.159.152.0/22
168.159.156.0/23
168.159.158.0/24
168.160.0.0/16
168.230.0.0/24
170.106.0.0/16
170.179.0.0/16
170.225.224.0/23
170.252.152.0/21
171.8.0.0/13
171.34.0.0/15
171.36.0.0/14
171.40.0.0/13
171.80.0.0/12
171.104.0.0/13
171.112.0.0/12
171.208.0.0/12
172.81.192.0/18
175.0.0.0/12
175.16.0.0/13
175.24.0.0/14
175.30.0.0/15
175.42.0.0/15
175.44.0.0/16
175.46.0.0/15
175.48.0.0/12
175.64.0.0/11
175.102.0.0/16
175.106.128.0/17
175.111.108.0/22
175.111.144.0/20
175.111.160.0/20
175.111.184.0/22
175.146.0.0/15
175.148.0.0/14
175.152.0.0/14
175.158.96.0/22
175.160.0.0/12
175.176.156.0/22
175.176.176.0/22
175.176.188.0/22
175.178.0.0/16
175.184.128.0/18
175.185.0.0/16
175.186.0.0/15
175.188.0.0/14
180.76.0.0/14
180.84.0.0/15
180.86.0.0/16
180.88.0.0/14
180.94.56.0/21
180.94.96.0/20
180.94.120.0/21
180.95.128.0/17
180.96.0.0/11
180.129.128.0/17
180.130.0.0/16
180.136.0.0/13
180.148.16.0/21
180.148.152.0/21
180.148.216.0/21
180.148.224.0/19
180.149.128.0/19
180.149.236.0/22
180.150.160.0/19
180.152.0.0/13
180.160.0.0/12
180.178.112.0/21
180.178.192.0/18
180.184.0.0/14
180.188.0.0/17
180.189.148.0/22
180.200.252.0/22
180.201.0.0/16
180.202.0.0/15
180.208.0.0/15
180.210.212.0/22
180.210.224.0/19
180.212.0.0/15
180.222.224.0/19
180.223.0.0/16
180.233.0.0/18
180.233.64.0/19
180.233.144.0/22
180.235.64.0/19
180.235.112.0/22
180.235.136.0/22
182.16.144.0/21
182.16.192.0/19
182.18.0.0/17
182.23.184.0/21
182.23.200.0/21
182.32.0.0/12
182.48.96.0/19
182.49.0.0/16
182.50.0.0/20
182.50.112.0/20
182.51.0.0/16
182.54.0.0/17
182.54.244.0/22
182.61.0.0/16
182.80.0.0/13
182.88.0.0/14
182.92.0.0/16
182.96.0.0/11
182.128.0.0/12
182.144.0.0/13
182.157.0.0/16
182.160.64.0/19
182.174.0.0/15
182.200.0.0/13
182.236.128.0/17
182.237.24.0/21
182.238.0.0/16
182.239.0.0/19
182.240.0.0/13
182.254.0.0/16
182.255.36.0/22
182.255.60.0/22
183.0.0.0/10
183.64.0.0/13
183.78.160.0/21
183.78.180.0/22
183.81.172.0/22
183.81.180.0/22
183.84.0.0/15
183.91.128.0/22
183.91.136.0/21
183.91.144.0/20
183.92.0.0/14
183.128.0.0/11
183.160.0.0/13
183.168.0.0/15
183.170.0.0/16
183.172.0.0/14
183.182.0.0/19
183.184.0.0/13
183.192.0.0/10
185.109.236.0/24
188.131.128.0/17
192.11.23.0/24
192.11.26.0/24
192.11.39.0/24
192.11.236.0/24
192.23.191.0/24
192.55.10.0/23
192.55.40.0/24
192.55.46.0/24
192.55.68.0/22
192.102.204.0/22
192.124.154.0/24
192.137.31.0/24
192.139.135.0/24
192.139.136.0/24
192.140.128.0/21
192.140.136.0/22
192.140.156.0/22
192.140.160.0/19
192.140.192.0/20
192.140.208.0/21
192.144.128.0/17
192.163.11.0/24
192.200.24.0/24
192.232.97.0/24
193.20.64.0/22
193.112.0.0/16
194.138.202.0/23
195.78.82.0/23
198.175.100.0/22
198.208.17.0/24
199.7.72.0/24
199.65.192.0/21
199.244.144.0/24
202.0.100.0/23
202.0.122.0/23
202.0.176.0/22
202.1.105.0/24
202.1.106.0/24
202.3.128.0/23
202.4.128.0/19
202.4.252.0/22
202.5.208.0/21
202.5.216.0/22
202.6.6.0/23
202.6.66.0/23
202.6.72.0/23
202.6.87.0/24
202.6.88.0/23
202.6.92.0/23
202.6.103.0/24
202.6.108.0/24
202.6.110.0/23
202.6.114.0/24
202.6.176.0/20
202.8.0.0/24
202.8.2.0/23
202.8.4.0/23
202.8.12.0/24
202.8.24.0/24
202.8.77.0/24
202.8.128.0/19
202.8.192.0/20
202.9.32.0/24
202.9.34.0/23
202.9.48.0/23
202.9.51.0/24
202.9.52.0/23
202.9.54.0/24
202.9.57.0/24
202.9.58.0/23
202.10.64.0/20
202.10.112.0/20
202.12.1.0/24
202.12.2.0/24
202.12.17.0/24
202.12.18.0/23
202.12.72.0/24
202.12.84.0/23
202.12.96.0/24
202.12.98.0/23
202.12.106.0/24
202.12.111.0/24
202.12.116.0/24
202.14.64.0/23
202.14.69.0/24
202.14.73.0/24
202.14.74.0/23
202.14.76.0/24
202.14.78.0/23
202.14.88.0/24
202.14.97.0/24
202.14.104.0/23
202.14.108.0/23
202.14.111.0/24
202.14.114.0/23
202.14.118.0/23
202.14.124.0/23
202.14.127.0/24
202.14.129.0/24
202.14.135.0/24
202.14.136.0/24
202.14.149.0/24
202.14.151.0/24
202.14.157.0/24
202.14.158.0/23
202.14.169.0/24
202.14.170.0/23
202.14.172.0/22
202.14.176.0/24
202.14.184.0/23
202.14.208.0/23
202.14.213.0/24
202.14.219.0/24
202.14.220.0/24
202.14.222.0/23
202.14.225.0/24
202.14.226.0/23
202.14.231.0/24
202.14.235.0/24
202.14.236.0/22
202.14.246.0/24
202.14.251.0/24
202.20.66.0/24
202.20.79.0/24
202.20.87.0/24
202.20.88.0/23
202.20.90.0/24
202.20.94.0/23
202.20.114.0/24
202.20.117.0/24
202.20.120.0/24
202.20.125.0/24
202.20.126.0/23
202.21.48.0/20
202.21.131.0/24
202.21.132.0/24
202.21.141.0/24
202.21.142.0/24
202.21.147.0/24
202.21.148.0/24
202.21.150.0/23
202.21.152.0/23
202.21.154.0/24
202.21.156.0/24
202.21.208.0/24
202.22.248.0/21
202.27.12.0/24
202.27.14.0/24
202.27.136.0/23
202.36.226.0/24
202.38.0.0/22
202.38.8.0/21
202.38.48.0/20
202.38.64.0/18
202.38.128.0/21
202.38.136.0/23
202.38.138.0/24
202.38.140.0/22
202.38.146.0/23
202.38.149.0/24
202.38.150.0/23
202.38.152.0/22
202.38.156.0/24
202.38.158.0/23
202.38.160.0/23
202.38.164.0/22
202.38.168.0/22
202.38.176.0/23
202.38.184.0/21
202.38.192.0/18
202.40.4.0/23
202.40.7.0/24
202.40.15.0/24
202.40.135.0/24
202.40.136.0/24
202.40.140.0/24
202.40.143.0/24
202.40.144.0/23
202.40.150.0/24
202.40.155.0/24
202.40.156.0/24
202.40.158.0/23
202.40.162.0/24
202.41.8.0/23
202.41.11.0/24
202.41.12.0/23
202.41.128.0/24
202.41.130.0/23
202.41.142.0/24
202.41.152.0/21
202.41.192.0/24
202.41.196.0/22
202.41.200.0/22
202.41.240.0/20
202.43.76.0/22
202.43.144.0/20
202.44.16.0/20
202.44.48.0/22
202.44.67.0/24
202.44.74.0/24
202.44.97.0/24
202.44.129.0/24
202.44.132.0/23
202.44.146.0/23
202.45.0.0/23
202.45.2.0/24
202.45.15.0/24
202.45.16.0/20
202.46.16.0/23
202.46.18.0/24
202.46.20.0/23
202.46.32.0/19
202.46.128.0/24
202.46.224.0/20
202.47.82.0/23
202.47.96.0/20
202.47.126.0/24
202.47.128.0/24
202.47.130.0/23
202.52.33.0/24
202.52.34.0/24
202.52.47.0/24
202.52.143.0/24
202.53.140.0/24
202.53.143.0/24
202.57.192.0/20
202.57.212.0/22
202.57.216.0/22
202.57.240.0/20
202.58.0.0/24
202.58.104.0/22
202.58.112.0/22
202.59.0.0/23
202.59.212.0/22
202.59.236.0/24
202.59.240.0/24
202.60.48.0/21
202.60.96.0/21
202.60.112.0/20
202.60.132.0/22
202.60.136.0/21
202.60.144.0/20
202.61.68.0/22
202.61.76.0/22
202.61.88.0/22
202.61.123.0/24
202.61.127.0/24
202.62.112.0/22
202.62.248.0/22
202.62.252.0/24
202.62.255.0/24
202.63.80.0/20
202.63.160.0/19
202.63.248.0/22
202.63.253.0/24
202.65.0.0/21
202.65.8.0/23
202.65.96.0/20
202.66.168.0/22
202.67.0.0/22
202.69.4.0/22
202.69.16.0/20
202.70.0.0/19
202.70.96.0/20
202.70.192.0/20
202.71.32.0/20
202.72.40.0/21
202.72.80.0/20
202.72.112.0/20
202.73.128.0/22
202.73.240.0/20
202.74.8.0/21
202.74.36.0/24
202.74.42.0/24
202.74.52.0/24
202.74.80.0/20
202.74.232.0/22
202.74.254.0/23
202.75.208.0/20
202.75.252.0/22
202.76.247.0/24
202.76.252.0/22
202.77.80.0/21
202.77.92.0/22
202.78.8.0/21
202.79.224.0/21
202.79.248.0/22
202.80.192.0/20
202.81.0.0/22
202.81.176.0/20
202.83.252.0/22
202.84.0.0/20
202.84.16.0/23
202.84.22.0/24
202.84.24.0/21
202.85.208.0/20
202.86.249.0/24
202.86.252.0/22
202.87.80.0/20
202.88.32.0/22
202.89.8.0/21
202.89.96.0/22
202.89.108.0/22
202.89.119.0/24
202.89.232.0/21
202.90.0.0/22
202.90.16.0/20
202.90.37.0/24
202.90.96.0/19
202.90.193.0/24
202.90.196.0/24
202.90.205.0/24
202.90.224.0/20
202.91.0.0/22
202.91.36.0/22
202.91.96.0/20
202.91.128.0/22
202.91.176.0/20
202.91.224.0/19
202.92.0.0/22
202.92.8.0/21
202.92.48.0/20
202.92.252.0/22
202.93.0.0/22
202.93.252.0/22
202.94.0.0/19
202.94.74.0/24
202.94.81.0/24
202.94.92.0/22
202.95.0.0/19
202.95.240.0/21
202.95.252.0/22
202.96.0.0/12
202.112.0.0/13
202.120.0.0/15
202.122.0.0/21
202.122.32.0/21
202.122.64.0/19
202.122.112.0/20
202.122.128.0/24
202.122.132.0/24
202.123.96.0/20
202.123.116.0/22
202.123.120.0/22
202.124.16.0/21
202.124.24.0/22
202.125.107.0/24
202.125.109.0/24
202.125.112.0/20
202.125.176.0/20
202.127.0.0/21
202.127.12.0/22
202.127.16.0/20
202.127.40.0/21
202.127.48.0/20
202.127.112.0/20
202.127.128.0/19
202.127.160.0/21
202.127.192.0/20
202.127.208.0/23
202.127.212.0/22
202.127.216.0/21
202.127.224.0/19
202.129.208.0/24
202.130.0.0/19
202.130.39.0/24
202.130.224.0/19
202.131.16.0/21
202.131.48.0/20
202.131.208.0/20
202.133.32.0/20
202.134.58.0/24
202.134.128.0/20
202.134.208.0/20
202.136.48.0/20
202.136.208.0/20
202.136.224.0/20
202.136.248.0/22
202.136.254.0/23
202.137.231.0/24
202.140.140.0/22
202.140.144.0/20
202.141.160.0/19
202.142.16.0/20
202.143.4.0/22
202.143.16.0/20
202.143.32.0/20
202.143.56.0/21
202.143.100.0/22
202.143.104.0/22
202.144.196.0/22
202.146.160.0/20
202.146.186.0/24
202.146.188.0/22
202.146.196.0/22
202.146.200.0/21
202.147.144.0/20
202.148.32.0/20
202.148.64.0/18
202.149.32.0/19
202.149.160.0/19
202.149.224.0/19
202.150.16.0/20
202.150.32.0/20
202.150.56.0/22
202.150.192.0/20
202.150.224.0/19
202.151.0.0/22
202.151.33.0/24
202.151.128.0/19
202.152.176.0/20
202.153.0.0/22
202.153.7.0/24
202.153.48.0/20
202.157.192.0/19
202.158.160.0/19
202.158.242.0/24
202.160.140.0/22
202.160.156.0/22
202.160.176.0/20
202.162.67.0/24
202.162.75.0/24
202.164.0.0/20
202.164.96.0/19
202.165.96.0/21
202.165.104.0/22
202.165.110.0/23
202.165.176.0/20
202.165.208.0/20
202.165.239.0/24
202.165.240.0/23
202.165.243.0/24
202.165.245.0/24
202.165.251.0/24
202.165.252.0/22
202.166.224.0/19
202.168.80.0/22
202.168.128.0/20
202.168.160.0/19
202.170.128.0/19
202.170.216.0/21
202.170.224.0/19
202.171.216.0/21
202.171.232.0/24
202.171.235.0/24
202.172.0.0/22
202.172.7.0/24
202.173.0.0/22
202.173.6.0/24
202.173.8.0/21
202.173.112.0/22
202.173.120.0/22
202.173.224.0/19
202.174.64.0/20
202.174.124.0/22
202.176.224.0/19
202.179.160.0/20
202.179.240.0/20
202.180.128.0/19
202.180.208.0/21
202.181.8.0/22
202.181.28.0/22
202.181.112.0/20
202.182.32.0/20
202.182.192.0/19
202.189.0.0/18
202.189.80.0/20
202.189.184.0/21
202.191.0.0/24
202.191.68.0/22
202.191.72.0/21
202.191.80.0/20
202.192.0.0/12
203.0.4.0/22
203.0.10.0/23
203.0.18.0/24
203.0.24.0/24
203.0.42.0/23
203.0.45.0/24
203.0.46.0/23
203.0.81.0/24
203.0.82.0/23
203.0.90.0/23
203.0.96.0/23
203.0.104.0/21
203.0.114.0/23
203.0.122.0/24
203.0.128.0/24
203.0.130.0/23
203.0.132.0/22
203.0.137.0/24
203.0.142.0/24
203.0.144.0/24
203.0.146.0/24
203.0.148.0/24
203.0.150.0/23
203.0.152.0/24
203.0.177.0/24
203.0.224.0/24
203.1.4.0/22
203.1.18.0/24
203.1.26.0/23
203.1.65.0/24
203.1.66.0/23
203.1.70.0/23
203.1.76.0/23
203.1.90.0/24
203.1.97.0/24
203.1.98.0/23
203.1.100.0/22
203.1.108.0/24
203.1.253.0/24
203.1.254.0/24
203.2.64.0/21
203.2.73.0/24
203.2.112.0/21
203.2.126.0/23
203.2.140.0/24
203.2.150.0/24
203.2.152.0/22
203.2.156.0/23
203.2.160.0/21
203.2.180.0/23
203.2.196.0/23
203.2.209.0/24
203.2.214.0/23
203.2.226.0/23
203.2.229.0/24
203.2.236.0/23
203.3.68.0/24
203.3.72.0/23
203.3.75.0/24
203.3.80.0/21
203.3.96.0/22
203.3.105.0/24
203.3.112.0/21
203.3.120.0/24
203.3.123.0/24
203.3.135.0/24
203.3.139.0/24
203.3.143.0/24
203.4.132.0/23
203.4.134.0/24
203.4.151.0/24
203.4.152.0/22
203.4.174.0/23
203.4.180.0/24
203.4.186.0/24
203.4.205.0/24
203.4.208.0/22
203.4.227.0/24
203.4.230.0/23
203.5.4.0/23
203.5.7.0/24
203.5.8.0/23
203.5.11.0/24
203.5.21.0/24
203.5.22.0/24
203.5.44.0/24
203.5.46.0/23
203.5.52.0/22
203.5.56.0/23
203.5.60.0/23
203.5.114.0/23
203.5.118.0/24
203.5.120.0/24
203.5.172.0/24
203.5.180.0/23
203.5.182.0/24
203.5.185.0/24
203.5.186.0/24
203.5.188.0/23
203.5.190.0/24
203.5.195.0/24
203.5.214.0/23
203.5.218.0/23
203.6.131.0/24
203.6.136.0/24
203.6.138.0/23
203.6.142.0/24
203.6.150.0/23
203.6.157.0/24
203.6.159.0/24
203.6.224.0/20
203.6.248.0/23
203.7.129.0/24
203.7.138.0/23
203.7.147.0/24
203.7.150.0/23
203.7.158.0/24
203.7.192.0/23
203.7.200.0/24
203.8.0.0/24
203.8.8.0/24
203.8.23.0/24
203.8.24.0/21
203.8.70.0/24
203.8.82.0/24
203.8.86.0/23
203.8.91.0/24
203.8.110.0/23
203.8.115.0/24
203.8.166.0/23
203.8.169.0/24
203.8.173.0/24
203.8.184.0/24
203.8.186.0/23
203.8.190.0/23
203.8.192.0/24
203.8.197.0/24
203.8.198.0/23
203.8.203.0/24
203.8.209.0/24
203.8.210.0/23
203.8.212.0/22
203.8.217.0/24
203.8.220.0/24
203.9.32.0/24
203.9.36.0/23
203.9.57.0/24
203.9.63.0/24
203.9.65.0/24
203.9.70.0/23
203.9.72.0/24
203.9.75.0/24
203.9.76.0/23
203.9.96.0/22
203.9.100.0/23
203.9.108.0/24
203.9.158.0/24
203.10.34.0/24
203.10.56.0/24
203.10.74.0/23
203.10.84.0/22
203.10.88.0/24
203.10.95.0/24
203.10.125.0/24
203.11.70.0/24
203.11.76.0/22
203.11.82.0/24
203.11.84.0/22
203.11.100.0/22
203.11.109.0/24
203.11.117.0/24
203.11.122.0/24
203.11.126.0/24
203.11.136.0/22
203.11.141.0/24
203.11.142.0/23
203.11.180.0/22
203.11.208.0/22
203.12.16.0/24
203.12.19.0/24
203.12.24.0/24
203.12.57.0/24
203.12.65.0/24
203.12.66.0/24
203.12.70.0/23
203.12.87.0/24
203.12.88.0/21
203.12.100.0/23
203.12.103.0/24
203.12.114.0/24
203.12.118.0/24
203.12.130.0/24
203.12.137.0/24
203.12.196.0/22
203.12.200.0/21
203.12.211.0/24
203.12.219.0/24
203.12.226.0/24
203.12.240.0/22
203.13.18.0/24
203.13.24.0/24
203.13.44.0/23
203.13.80.0/21
203.13.88.0/23
203.13.92.0/22
203.13.173.0/24
203.13.224.0/23
203.13.227.0/24
203.13.233.0/24
203.14.24.0/22
203.14.33.0/24
203.14.56.0/24
203.14.61.0/24
203.14.62.0/24
203.14.104.0/24
203.14.114.0/23
203.14.118.0/24
203.14.162.0/24
203.14.184.0/21
203.14.192.0/24
203.14.194.0/23
203.14.214.0/24
203.14.231.0/24
203.14.246.0/24
203.15.0.0/20
203.15.20.0/23
203.15.22.0/24
203.15.87.0/24
203.15.88.0/23
203.15.105.0/24
203.15.112.0/21
203.15.130.0/23
203.15.149.0/24
203.15.151.0/24
203.15.156.0/22
203.15.174.0/24
203.15.227.0/24
203.15.232.0/21
203.15.240.0/23
203.15.246.0/24
203.16.10.0/24
203.16.12.0/23
203.16.16.0/21
203.16.27.0/24
203.16.38.0/24
203.16.49.0/24
203.16.50.0/23
203.16.58.0/24
203.16.63.0/24
203.16.133.0/24
203.16.161.0/24
203.16.162.0/24
203.16.186.0/23
203.16.228.0/24
203.16.238.0/24
203.16.240.0/24
203.16.245.0/24
203.17.2.0/24
203.17.18.0/24
203.17.28.0/24
203.17.39.0/24
203.17.56.0/24
203.17.74.0/23
203.17.88.0/23
203.17.136.0/24
203.17.164.0/24
203.17.187.0/24
203.17.190.0/23
203.17.231.0/24
203.17.233.0/24
203.17.248.0/23
203.17.255.0/24
203.18.2.0/23
203.18.4.0/24
203.18.7.0/24
203.18.31.0/24
203.18.37.0/24
203.18.48.0/23
203.18.52.0/24
203.18.72.0/22
203.18.80.0/23
203.18.87.0/24
203.18.100.0/23
203.18.105.0/24
203.18.107.0/24
203.18.110.0/24
203.18.129.0/24
203.18.131.0/24
203.18.132.0/23
203.18.144.0/24
203.18.153.0/24
203.18.199.0/24
203.18.208.0/24
203.18.211.0/24
203.18.215.0/24
203.19.1.0/24
203.19.18.0/24
203.19.24.0/24
203.19.30.0/24
203.19.32.0/21
203.19.41.0/24
203.19.44.0/23
203.19.46.0/24
203.19.58.0/24
203.19.60.0/23
203.19.64.0/24
203.19.68.0/24
203.19.72.0/24
203.19.101.0/24
203.19.111.0/24
203.19.131.0/24
203.19.133.0/24
203.19.144.0/24
203.19.147.0/24
203.19.149.0/24
203.19.156.0/24
203.19.176.0/24
203.19.178.0/23
203.19.208.0/24
203.19.228.0/22
203.19.233.0/24
203.19.242.0/24
203.19.248.0/23
203.19.255.0/24
203.20.17.0/24
203.20.40.0/23
203.20.44.0/24
203.20.48.0/24
203.20.61.0/24
203.20.65.0/24
203.20.84.0/23
203.20.89.0/24
203.20.106.0/23
203.20.115.0/24
203.20.117.0/24
203.20.118.0/23
203.20.122.0/24
203.20.126.0/23
203.20.135.0/24
203.20.136.0/21
203.20.150.0/24
203.20.230.0/24
203.20.232.0/24
203.20.236.0/24
203.21.0.0/23
203.21.2.0/24
203.21.8.0/24
203.21.10.0/24
203.21.18.0/24
203.21.33.0/24
203.21.34.0/24
203.21.41.0/24
203.21.44.0/24
203.21.68.0/24
203.21.82.0/24
203.21.96.0/22
203.21.124.0/24
203.21.136.0/23
203.21.145.0/24
203.21.206.0/24
203.22.24.0/24
203.22.28.0/23
203.22.31.0/24
203.22.68.0/24
203.22.76.0/24
203.22.78.0/24
203.22.84.0/24
203.22.87.0/24
203.22.92.0/22
203.22.99.0/24
203.22.106.0/24
203.22.122.0/23
203.22.131.0/24
203.22.163.0/24
203.22.166.0/24
203.22.170.0/24
203.22.176.0/21
203.22.194.0/24
203.22.242.0/23
203.22.245.0/24
203.22.246.0/24
203.22.252.0/23
203.23.0.0/24
203.23.47.0/24
203.23.61.0/24
203.23.62.0/23
203.23.73.0/24
203.23.85.0/24
203.23.92.0/22
203.23.98.0/24
203.23.107.0/24
203.23.112.0/24
203.23.130.0/24
203.23.140.0/23
203.23.172.0/24
203.23.182.0/24
203.23.186.0/23
203.23.192.0/24
203.23.197.0/24
203.23.198.0/24
203.23.204.0/22
203.23.224.0/24
203.23.226.0/23
203.23.228.0/22
203.23.249.0/24
203.23.251.0/24
203.24.13.0/24
203.24.18.0/24
203.24.27.0/24
203.24.43.0/24
203.24.56.0/24
203.24.58.0/24
203.24.67.0/24
203.24.74.0/24
203.24.79.0/24
203.24.80.0/23
203.24.84.0/23
203.24.86.0/24
203.24.90.0/24
203.24.111.0/24
203.24.112.0/24
203.24.116.0/24
203.24.122.0/23
203.24.145.0/24
203.24.152.0/23
203.24.157.0/24
203.24.161.0/24
203.24.167.0/24
203.24.186.0/23
203.24.199.0/24
203.24.202.0/24
203.24.212.0/23
203.24.217.0/24
203.24.219.0/24
203.24.244.0/24
203.25.19.0/24
203.25.20.0/23
203.25.46.0/24
203.25.48.0/21
203.25.64.0/23
203.25.91.0/24
203.25.99.0/24
203.25.100.0/24
203.25.106.0/24
203.25.131.0/24
203.25.135.0/24
203.25.138.0/24
203.25.147.0/24
203.25.153.0/24
203.25.154.0/23
203.25.164.0/24
203.25.166.0/24
203.25.174.0/23
203.25.180.0/24
203.25.182.0/24
203.25.191.0/24
203.25.199.0/24
203.25.200.0/24
203.25.202.0/23
203.25.208.0/20
203.25.229.0/24
203.25.235.0/24
203.25.236.0/24
203.25.242.0/24
203.26.12.0/24
203.26.34.0/24
203.26.49.0/24
203.26.50.0/24
203.26.55.0/24
203.26.56.0/23
203.26.60.0/24
203.26.65.0/24
203.26.68.0/24
203.26.76.0/24
203.26.80.0/24
203.26.84.0/24
203.26.97.0/24
203.26.102.0/23
203.26.115.0/24
203.26.116.0/24
203.26.129.0/24
203.26.143.0/24
203.26.144.0/24
203.26.148.0/23
203.26.154.0/24
203.26.158.0/23
203.26.161.0/24
203.26.170.0/24
203.26.173.0/24
203.26.176.0/24
203.26.185.0/24
203.26.202.0/23
203.26.210.0/24
203.26.214.0/24
203.26.222.0/24
203.26.224.0/24
203.26.228.0/24
203.26.232.0/24
203.27.0.0/24
203.27.10.0/24
203.27.15.0/24
203.27.16.0/24
203.27.20.0/24
203.27.22.0/23
203.27.40.0/24
203.27.45.0/24
203.27.53.0/24
203.27.65.0/24
203.27.66.0/24
203.27.81.0/24
203.27.88.0/24
203.27.102.0/24
203.27.109.0/24
203.27.117.0/24
203.27.121.0/24
203.27.122.0/23
203.27.125.0/24
203.27.200.0/24
203.27.202.0/24
203.27.233.0/24
203.27.241.0/24
203.27.250.0/24
203.28.10.0/24
203.28.12.0/24
203.28.33.0/24
203.28.34.0/23
203.28.43.0/24
203.28.44.0/24
203.28.54.0/24
203.28.56.0/24
203.28.73.0/24
203.28.74.0/24
203.28.76.0/24
203.28.86.0/24
203.28.88.0/24
203.28.112.0/24
203.28.131.0/24
203.28.136.0/24
203.28.140.0/24
203.28.145.0/24
203.28.165.0/24
203.28.169.0/24
203.28.170.0/24
203.28.178.0/23
203.28.185.0/24
203.28.187.0/24
203.28.196.0/24
203.28.226.0/23
203.28.239.0/24
203.29.2.0/24
203.29.8.0/23
203.29.13.0/24
203.29.14.0/24
203.29.28.0/24
203.29.46.0/24
203.29.57.0/24
203.29.61.0/24
203.29.63.0/24
203.29.69.0/24
203.29.73.0/24
203.29.81.0/24
203.29.90.0/24
203.29.95.0/24
203.29.100.0/24
203.29.103.0/24
203.29.112.0/24
203.29.120.0/22
203.29.182.0/23
203.29.187.0/24
203.29.189.0/24
203.29.190.0/24
203.29.205.0/24
203.29.210.0/24
203.29.217.0/24
203.29.227.0/24
203.29.231.0/24
203.29.233.0/24
203.29.234.0/24
203.29.248.0/24
203.29.254.0/23
203.30.16.0/23
203.30.25.0/24
203.30.27.0/24
203.30.29.0/24
203.30.66.0/24
203.30.81.0/24
203.30.87.0/24
203.30.111.0/24
203.30.121.0/24
203.30.123.0/24
203.30.152.0/24
203.30.156.0/24
203.30.162.0/24
203.30.173.0/24
203.30.175.0/24
203.30.187.0/24
203.30.194.0/24
203.30.217.0/24
203.30.220.0/24
203.30.222.0/24
203.30.232.0/23
203.30.235.0/24
203.30.240.0/23
203.30.246.0/24
203.30.250.0/23
203.31.45.0/24
203.31.46.0/24
203.31.49.0/24
203.31.51.0/24
203.31.54.0/23
203.31.69.0/24
203.31.72.0/24
203.31.80.0/24
203.31.85.0/24
203.31.97.0/24
203.31.105.0/24
203.31.106.0/24
203.31.108.0/23
203.31.124.0/24
203.31.162.0/24
203.31.174.0/24
203.31.177.0/24
203.31.181.0/24
203.31.187.0/24
203.31.189.0/24
203.31.204.0/24
203.31.220.0/24
203.31.222.0/23
203.31.225.0/24
203.31.229.0/24
203.31.248.0/23
203.31.253.0/24
203.32.20.0/24
203.32.48.0/23
203.32.56.0/24
203.32.60.0/24
203.32.62.0/24
203.32.68.0/23
203.32.76.0/24
203.32.81.0/24
203.32.84.0/23
203.32.95.0/24
203.32.102.0/24
203.32.105.0/24
203.32.130.0/24
203.32.133.0/24
203.32.140.0/24
203.32.152.0/24
203.32.186.0/23
203.32.192.0/24
203.32.196.0/24
203.32.203.0/24
203.32.204.0/23
203.32.212.0/24
203.33.4.0/24
203.33.7.0/24
203.33.8.0/21
203.33.21.0/24
203.33.26.0/24
203.33.32.0/24
203.33.63.0/24
203.33.64.0/24
203.33.67.0/24
203.33.68.0/24
203.33.73.0/24
203.33.79.0/24
203.33.100.0/24
203.33.122.0/24
203.33.129.0/24
203.33.131.0/24
203.33.145.0/24
203.33.156.0/24
203.33.158.0/23
203.33.174.0/24
203.33.185.0/24
203.33.200.0/24
203.33.202.0/23
203.33.204.0/24
203.33.206.0/23
203.33.214.0/23
203.33.224.0/23
203.33.226.0/24
203.33.233.0/24
203.33.243.0/24
203.33.250.0/24
203.34.4.0/24
203.34.21.0/24
203.34.27.0/24
203.34.39.0/24
203.34.48.0/23
203.34.54.0/24
203.34.56.0/23
203.34.67.0/24
203.34.69.0/24
203.34.76.0/24
203.34.92.0/24
203.34.106.0/24
203.34.113.0/24
203.34.147.0/24
203.34.150.0/24
203.34.152.0/23
203.34.161.0/24
203.34.162.0/24
203.34.187.0/24
203.34.192.0/21
203.34.204.0/22
203.34.232.0/24
203.34.240.0/24
203.34.242.0/24
203.34.245.0/24
203.34.251.0/24
203.55.2.0/23
203.55.4.0/24
203.55.10.0/24
203.55.13.0/24
203.55.22.0/24
203.55.30.0/24
203.55.93.0/24
203.55.101.0/24
203.55.109.0/24
203.55.110.0/24
203.55.116.0/23
203.55.119.0/24
203.55.128.0/23
203.55.146.0/23
203.55.192.0/24
203.55.196.0/24
203.55.218.0/23
203.55.221.0/24
203.55.224.0/24
203.56.1.0/24
203.56.4.0/24
203.56.12.0/24
203.56.24.0/24
203.56.38.0/24
203.56.40.0/24
203.56.46.0/24
203.56.48.0/21
203.56.68.0/23
203.56.82.0/23
203.56.84.0/23
203.56.95.0/24
203.56.110.0/24
203.56.121.0/24
203.56.161.0/24
203.56.169.0/24
203.56.172.0/23
203.56.175.0/24
203.56.183.0/24
203.56.185.0/24
203.56.187.0/24
203.56.192.0/24
203.56.198.0/24
203.56.201.0/24
203.56.208.0/23
203.56.210.0/24
203.56.214.0/24
203.56.216.0/24
203.56.227.0/24
203.56.228.0/24
203.56.231.0/24
203.56.232.0/24
203.56.240.0/24
203.56.252.0/24
203.56.254.0/24
203.57.5.0/24
203.57.6.0/24
203.57.12.0/23
203.57.28.0/24
203.57.39.0/24
203.57.46.0/24
203.57.58.0/24
203.57.61.0/24
203.57.66.0/24
203.57.69.0/24
203.57.70.0/23
203.57.73.0/24
203.57.90.0/24
203.57.101.0/24
203.57.109.0/24
203.57.123.0/24
203.57.157.0/24
203.57.200.0/24
203.57.202.0/24
203.57.206.0/24
203.57.222.0/24
203.57.224.0/20
203.57.246.0/23
203.57.249.0/24
203.57.253.0/24
203.57.254.0/23
203.62.2.0/24
203.62.131.0/24
203.62.139.0/24
203.62.161.0/24
203.62.197.0/24
203.62.228.0/22
203.62.234.0/24
203.62.246.0/24
203.65.240.0/22
203.76.160.0/22
203.76.168.0/22
203.76.208.0/21
203.76.216.0/22
203.76.240.0/21
203.77.180.0/22
203.78.48.0/20
203.78.156.0/22
203.79.0.0/20
203.79.32.0/20
203.80.4.0/23
203.80.32.0/20
203.80.57.0/24
203.80.129.0/24
203.80.132.0/22
203.80.136.0/21
203.80.144.0/20
203.81.0.0/21
203.81.16.0/20
203.81.244.0/22
203.82.0.0/23
203.82.16.0/21
203.82.112.0/20
203.82.224.0/20
203.83.0.0/22
203.83.8.0/21
203.83.56.0/21
203.83.224.0/20
203.86.0.0/17
203.86.250.0/24
203.86.254.0/23
203.88.32.0/19
203.88.192.0/19
203.89.0.0/22
203.89.8.0/21
203.89.100.0/22
203.89.133.0/24
203.89.136.0/22
203.89.144.0/24
203.90.0.0/22
203.90.8.0/21
203.90.128.0/18
203.90.192.0/19
203.91.1.0/24
203.91.32.0/19
203.91.96.0/20
203.91.120.0/21
203.92.0.0/22
203.92.6.0/24
203.92.160.0/19
203.93.0.0/16
203.94.0.0/19
203.95.0.0/21
203.95.96.0/19
203.95.128.0/18
203.95.200.0/21
203.95.208.0/22
203.95.224.0/19
203.99.8.0/21
203.99.16.0/20
203.99.80.0/20
203.100.32.0/20
203.100.48.0/21
203.100.58.0/24
203.100.60.0/24
203.100.63.0/24
203.100.80.0/20
203.100.96.0/19
203.100.192.0/20
203.104.32.0/20
203.105.96.0/19
203.105.128.0/19
203.107.0.0/17
203.110.160.0/19
203.110.208.0/20
203.110.232.0/23
203.110.234.0/24
203.114.80.0/20
203.114.244.0/22
203.118.192.0/19
203.118.241.0/24
203.118.248.0/22
203.119.24.0/21
203.119.32.0/22
203.119.80.0/22
203.119.85.0/24
203.119.113.0/24
203.119.114.0/23
203.119.116.0/22
203.119.120.0/21
203.119.128.0/17
203.123.58.0/24
203.128.32.0/19
203.128.96.0/19
203.128.128.0/24
203.128.224.0/21
203.129.8.0/21
203.130.32.0/19
203.132.32.0/19
203.134.240.0/21
203.135.96.0/19
203.135.160.0/20
203.142.12.0/23
203.142.219.0/24
203.142.224.0/19
203.144.96.0/19
203.145.0.0/19
203.148.0.0/18
203.148.64.0/20
203.148.80.0/22
203.148.86.0/23
203.149.92.0/22
203.152.64.0/19
203.152.128.0/19
203.153.0.0/22
203.156.192.0/18
203.158.16.0/21
203.160.52.0/22
203.160.104.0/21
203.160.129.0/24
203.160.192.0/19
203.161.0.0/22
203.161.180.0/24
203.161.183.0/24
203.161.192.0/19
203.166.160.0/19
203.167.28.0/22
203.168.0.0/19
203.170.58.0/23
203.171.0.0/22
203.171.208.0/24
203.171.224.0/20
203.174.4.0/24
203.174.6.0/23
203.174.96.0/19
203.175.128.0/19
203.175.192.0/18
203.176.0.0/18
203.176.64.0/19
203.176.168.0/21
203.184.80.0/20
203.185.189.0/24
203.187.160.0/19
203.189.0.0/23
203.189.6.0/23
203.189.112.0/22
203.189.192.0/19
203.189.232.0/21
203.189.240.0/22
203.190.96.0/20
203.190.249.0/24
203.191.0.0/23
203.191.2.0/24
203.191.5.0/24
203.191.7.0/24
203.191.16.0/20
203.191.64.0/18
203.191.133.0/24
203.191.144.0/20
203.192.0.0/19
203.193.224.0/19
203.194.120.0/21
203.195.64.0/19
203.195.112.0/21
203.195.128.0/17
203.196.0.0/20
203.196.28.0/22
203.201.181.0/24
203.201.182.0/24
203.202.236.0/22
203.205.64.0/19
203.205.128.0/17
203.207.64.0/18
203.207.128.0/17
203.208.0.0/20
203.208.16.0/22
203.208.32.0/19
203.209.224.0/19
203.212.0.0/20
203.212.80.0/20
203.215.232.0/21
203.217.164.0/22
203.222.192.0/20
203.223.0.0/20
203.223.16.0/21
204.55.160.0/24
204.74.96.0/24
204.114.176.0/23
206.219.44.0/23
206.219.50.0/23
206.219.52.0/23
207.89.20.0/24
210.2.0.0/19
210.5.0.0/19
210.5.56.0/21
210.5.128.0/19
210.7.56.0/21
210.12.0.0/15
210.14.64.0/19
210.14.112.0/20
210.14.128.0/17
210.15.0.0/17
210.15.128.0/18
210.16.104.0/22
210.16.128.0/18
210.21.0.0/16
210.22.0.0/16
210.23.32.0/19
210.25.0.0/16
210.26.0.0/15
210.28.0.0/14
210.32.0.0/12
210.51.0.0/16
210.52.0.0/15
210.56.192.0/19
210.72.0.0/14
210.76.0.0/15
210.78.0.0/16
210.79.64.0/18
210.79.224.0/19
210.82.0.0/15
210.87.128.0/18
210.185.192.0/18
210.192.96.0/19
211.64.0.0/13
211.80.0.0/12
211.96.0.0/13
211.136.0.0/13
211.144.0.0/12
211.160.0.0/13
212.64.0.0/17
212.129.128.0/17
216.250.108.0/22
218.0.0.0/11
218.56.0.0/13
218.64.0.0/11
218.96.0.0/14
218.100.88.0/21
218.100.96.0/19
218.100.128.0/17
218.104.0.0/14
218.108.0.0/15
218.185.192.0/19
218.185.240.0/21
218.192.0.0/12
218.240.0.0/13
218.249.0.0/16
219.72.0.0/16
219.82.0.0/16
219.83.128.0/17
219.90.68.0/22
219.90.72.0/21
219.128.0.0/11
219.216.0.0/13
219.224.0.0/12
219.242.0.0/15
219.244.0.0/14
220.101.192.0/18
220.112.0.0/14
220.152.128.0/17
220.154.0.0/15
220.158.240.0/22
220.160.0.0/11
220.192.0.0/12
220.231.0.0/18
220.231.128.0/17
220.232.64.0/18
220.234.0.0/16
220.242.0.0/15
220.247.136.0/21
220.248.0.0/14
220.252.0.0/16
221.0.0.0/13
221.8.0.0/14
221.12.0.0/17
221.12.128.0/18
221.13.0.0/16
221.14.0.0/15
221.122.0.0/15
221.128.128.0/17
221.129.0.0/16
221.130.0.0/15
221.133.224.0/19
221.136.0.0/15
221.172.0.0/14
221.176.0.0/13
221.192.0.0/14
221.196.0.0/15
221.198.0.0/16
221.199.0.0/17
221.199.128.0/18
221.199.192.0/20
221.199.224.0/19
221.200.0.0/13
221.208.0.0/12
221.224.0.0/12
222.16.0.0/12
222.32.0.0/11
222.64.0.0/11
222.125.0.0/16
222.126.128.0/17
222.128.0.0/12
222.160.0.0/14
222.168.0.0/13
222.176.0.0/12
222.192.0.0/11
222.240.0.0/13
222.248.0.0/15
223.0.0.0/12
223.20.0.0/15
223.27.184.0/22
223.29.208.0/22
223.29.252.0/22
223.64.0.0/11
223.96.0.0/12
223.112.0.0/14
223.116.0.0/15
223.120.0.0/13
223.128.0.0/15
223.130.8.0/22
223.144.0.0/12
223.160.0.0/14
223.166.0.0/15
223.192.0.0/15
223.198.0.0/15
223.201.0.0/16
223.202.0.0/15
223.208.0.0/13
223.220.0.0/15
223.223.176.0/20
223.223.192.0/20
223.240.0.0/13
223.248.0.0/14
223.252.128.0/17
223.254.0.0/16
223.255.0.0/17
223.255.236.0/22
223.255.252.0/23
...@@ -37,8 +37,10 @@ import android.support.annotation.RequiresApi ...@@ -37,8 +37,10 @@ import android.support.annotation.RequiresApi
import android.support.v4.os.UserManagerCompat import android.support.v4.os.UserManagerCompat
import android.support.v7.app.AppCompatDelegate import android.support.v7.app.AppCompatDelegate
import android.util.Log import android.util.Log
import android.widget.Toast
import com.evernote.android.job.JobConstants import com.evernote.android.job.JobConstants
import com.evernote.android.job.JobManager import com.evernote.android.job.JobManager
import com.evernote.android.job.JobManagerCreateException
import com.github.shadowsocks.acl.Acl import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.AclSyncJob import com.github.shadowsocks.acl.AclSyncJob
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
...@@ -69,7 +71,10 @@ class App : Application() { ...@@ -69,7 +71,10 @@ class App : Application() {
val deviceContext: Context by lazy { if (Build.VERSION.SDK_INT < 24) this else DeviceContext(this) } val deviceContext: Context by lazy { if (Build.VERSION.SDK_INT < 24) this else DeviceContext(this) }
val remoteConfig: FirebaseRemoteConfig by lazy { FirebaseRemoteConfig.getInstance() } val remoteConfig: FirebaseRemoteConfig by lazy { FirebaseRemoteConfig.getInstance() }
private val tracker: Tracker by lazy { GoogleAnalytics.getInstance(deviceContext).newTracker(R.xml.tracker) } private val tracker: Tracker by lazy { GoogleAnalytics.getInstance(deviceContext).newTracker(R.xml.tracker) }
val info: PackageInfo by lazy { packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) } val info: PackageInfo by lazy { getPackageInfo(packageName) }
fun getPackageInfo(packageName: String) =
packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)!!
fun startService() { fun startService() {
val intent = Intent(this, BaseService.serviceClass.java) val intent = Intent(this, BaseService.serviceClass.java)
...@@ -126,11 +131,16 @@ class App : Application() { ...@@ -126,11 +131,16 @@ class App : Application() {
remoteConfig.fetch().addOnCompleteListener { remoteConfig.fetch().addOnCompleteListener {
if (it.isSuccessful) remoteConfig.activateFetched() else Log.e(TAG, "Failed to fetch config") if (it.isSuccessful) remoteConfig.activateFetched() else Log.e(TAG, "Failed to fetch config")
} }
JobManager.create(deviceContext).addJobCreator(AclSyncJob) try {
JobManager.create(deviceContext).addJobCreator(AclSyncJob)
} catch (e: JobManagerCreateException) {
Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
app.track(e)
}
// handle data restored // handle data restored
if (DataStore.directBootAware && UserManagerCompat.isUserUnlocked(this)) DirectBoot.update() if (DataStore.directBootAware && UserManagerCompat.isUserUnlocked(this)) DirectBoot.update()
TcpFastOpen.enabled(DataStore.publicStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled)) TcpFastOpen.enabledAsync(DataStore.publicStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) { if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) {
val assetManager = assets val assetManager = assets
for (dir in arrayOf("acl", "overture")) for (dir in arrayOf("acl", "overture"))
...@@ -167,13 +177,16 @@ class App : Application() { ...@@ -167,13 +177,16 @@ class App : Application() {
} }
} }
fun listenForPackageChanges(callback: () -> Unit): BroadcastReceiver { fun listenForPackageChanges(onetime: Boolean = true, callback: () -> Unit): BroadcastReceiver {
val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED) val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED)
filter.addAction(Intent.ACTION_PACKAGE_REMOVED) filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
filter.addDataScheme("package") filter.addDataScheme("package")
val result = broadcastReceiver { _, intent -> val result = object : BroadcastReceiver() {
if (intent.action != Intent.ACTION_PACKAGE_REMOVED || override fun onReceive(context: Context, intent: Intent) {
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) callback() if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) return
callback()
if (onetime) app.unregisterReceiver(this)
}
} }
app.registerReceiver(result, filter) app.registerReceiver(result, filter)
return result return result
......
...@@ -34,6 +34,7 @@ import android.content.pm.PackageManager ...@@ -34,6 +34,7 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.support.design.widget.Snackbar
import android.support.v4.app.TaskStackBuilder import android.support.v4.app.TaskStackBuilder
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator import android.support.v7.widget.DefaultItemAnimator
...@@ -43,7 +44,6 @@ import android.support.v7.widget.Toolbar ...@@ -43,7 +44,6 @@ import android.support.v7.widget.Toolbar
import android.view.* import android.view.*
import android.widget.ImageView import android.widget.ImageView
import android.widget.Switch import android.widget.Switch
import android.widget.Toast
import com.futuremind.recyclerviewfastscroll.FastScroller import com.futuremind.recyclerviewfastscroll.FastScroller
import com.futuremind.recyclerviewfastscroll.SectionTitleProvider import com.futuremind.recyclerviewfastscroll.SectionTitleProvider
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
...@@ -63,11 +63,14 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -63,11 +63,14 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
private var receiver: BroadcastReceiver? = null private var receiver: BroadcastReceiver? = null
private var cachedApps: List<PackageInfo>? = null private var cachedApps: List<PackageInfo>? = null
private fun getApps(pm: PackageManager): List<ProxiedApp> { private fun getApps(pm: PackageManager): List<ProxiedApp> {
if (receiver == null) receiver = app.listenForPackageChanges {
synchronized(AppManager) { cachedApps = null }
AppManager.instance?.reloadApps()
}
return synchronized(AppManager) { return synchronized(AppManager) {
if (receiver == null) receiver = app.listenForPackageChanges {
synchronized(AppManager) {
receiver = null
cachedApps = null
}
AppManager.instance?.reloadApps()
}
// Labels and icons can change on configuration (locale, etc.) changes, therefore they are not cached. // Labels and icons can change on configuration (locale, etc.) changes, therefore they are not cached.
val cachedApps = cachedApps ?: pm.getInstalledPackages(PackageManager.GET_PERMISSIONS) val cachedApps = cachedApps ?: pm.getInstalledPackages(PackageManager.GET_PERMISSIONS)
.filter { it.packageName != app.packageName && .filter { it.packageName != app.packageName &&
...@@ -231,14 +234,14 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -231,14 +234,14 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
ProfileManager.updateProfile(it) ProfileManager.updateProfile(it)
} }
if (DataStore.directBootAware) DirectBoot.update() if (DataStore.directBootAware) DirectBoot.update()
Toast.makeText(this, R.string.action_apply_all, Toast.LENGTH_SHORT).show() Snackbar.make(appListView, R.string.action_apply_all, Snackbar.LENGTH_LONG).show()
} else Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show() } else Snackbar.make(appListView, R.string.action_export_err, Snackbar.LENGTH_LONG).show()
return true return true
} }
R.id.action_export -> { R.id.action_export -> {
clipboard.primaryClip = ClipData.newPlainText(Key.individual, clipboard.primaryClip = ClipData.newPlainText(Key.individual,
"${DataStore.bypass}\n${DataStore.individual}") "${DataStore.bypass}\n${DataStore.individual}")
Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show() Snackbar.make(appListView, R.string.action_export_msg, Snackbar.LENGTH_LONG).show()
return true return true
} }
R.id.action_import -> { R.id.action_import -> {
...@@ -251,23 +254,21 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -251,23 +254,21 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
bypassSwitch.isChecked = enabled.toBoolean() bypassSwitch.isChecked = enabled.toBoolean()
DataStore.individual = apps DataStore.individual = apps
DataStore.dirty = true DataStore.dirty = true
Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show() Snackbar.make(appListView, R.string.action_import_msg, Snackbar.LENGTH_LONG).show()
initProxiedApps(apps) initProxiedApps(apps)
reloadApps() reloadApps()
return true return true
} catch (_: IllegalArgumentException) { } } catch (_: IllegalArgumentException) { }
} }
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show() Snackbar.make(appListView, R.string.action_import_err, Snackbar.LENGTH_LONG).show()
} }
} }
return false return false
} }
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyUp(keyCode: Int, event: KeyEvent?) = if (keyCode == KeyEvent.KEYCODE_MENU)
return if (keyCode == KeyEvent.KEYCODE_MENU) if (toolbar.isOverflowMenuShowing) toolbar.hideOverflowMenu() else toolbar.showOverflowMenu()
if (toolbar.isOverflowMenuShowing) toolbar.hideOverflowMenu() else toolbar.showOverflowMenu() else super.onKeyUp(keyCode, event)
else super.onKeyUp(keyCode, event)
}
override fun onDestroy() { override fun onDestroy() {
instance = null instance = null
......
...@@ -26,7 +26,6 @@ import android.os.Bundle ...@@ -26,7 +26,6 @@ import android.os.Bundle
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.support.v14.preference.SwitchPreference import android.support.v14.preference.SwitchPreference
import android.support.v7.preference.Preference import android.support.v7.preference.Preference
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot import com.github.shadowsocks.utils.DirectBoot
...@@ -51,7 +50,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompatDividers() { ...@@ -51,7 +50,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompatDividers() {
boot.isChecked = BootReceiver.enabled boot.isChecked = BootReceiver.enabled
val dba = findPreference(Key.directBootAware) val dba = findPreference(Key.directBootAware)
if (Build.VERSION.SDK_INT >= 24 && context!!.getSystemService(DevicePolicyManager::class.java) if (Build.VERSION.SDK_INT >= 24 && requireContext().getSystemService(DevicePolicyManager::class.java)
.storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER) .storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER)
dba.onPreferenceChangeListener = directBootAwareListener else dba.parent!!.removePreference(dba) dba.onPreferenceChangeListener = directBootAwareListener else dba.parent!!.removePreference(dba)
...@@ -60,7 +59,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompatDividers() { ...@@ -60,7 +59,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompatDividers() {
tfo.setOnPreferenceChangeListener { _, value -> tfo.setOnPreferenceChangeListener { _, value ->
val result = TcpFastOpen.enabled(value as Boolean) val result = TcpFastOpen.enabled(value as Boolean)
if (result != null && result != "Success.") if (result != null && result != "Success.")
Snackbar.make(activity!!.findViewById(R.id.snackbar), result, Snackbar.LENGTH_LONG).show() Snackbar.make(requireActivity().findViewById(R.id.snackbar), result, Snackbar.LENGTH_LONG).show()
value == TcpFastOpen.sendEnabled value == TcpFastOpen.sendEnabled
} }
if (!TcpFastOpen.supported) { if (!TcpFastOpen.supported) {
......
...@@ -62,6 +62,7 @@ import com.mikepenz.materialdrawer.Drawer ...@@ -62,6 +62,7 @@ import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.DrawerBuilder import com.mikepenz.materialdrawer.DrawerBuilder
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import java.io.IOException
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.Proxy import java.net.Proxy
...@@ -178,8 +179,8 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe ...@@ -178,8 +179,8 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
val elapsed = SystemClock.elapsedRealtime() - start val elapsed = SystemClock.elapsedRealtime() - start
if (code == 204 || code == 200 && conn.responseLength == 0L) if (code == 204 || code == 200 && conn.responseLength == 0L)
Pair(true, getString(R.string.connection_test_available, elapsed)) Pair(true, getString(R.string.connection_test_available, elapsed))
else throw Exception(getString(R.string.connection_test_error_status_code, code)) else throw IOException(getString(R.string.connection_test_error_status_code, code))
} catch (e: Exception) { } catch (e: IOException) {
Pair(false, getString(R.string.connection_test_error, e.message)) Pair(false, getString(R.string.connection_test_error, e.message))
} finally { } finally {
conn.disconnect() conn.disconnect()
...@@ -196,6 +197,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe ...@@ -196,6 +197,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
override fun onServiceConnected(service: IShadowsocksService) = changeState(service.state) override fun onServiceConnected(service: IShadowsocksService) = changeState(service.state)
override fun onServiceDisconnected() = changeState(BaseService.IDLE) override fun onServiceDisconnected() = changeState(BaseService.IDLE)
override fun binderDied() { override fun binderDied() {
super.binderDied()
app.handler.post { app.handler.post {
connection.disconnect() connection.disconnect()
Executable.killAll() Executable.killAll()
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.app.Activity import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
...@@ -55,22 +56,17 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu ...@@ -55,22 +56,17 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
private const val REQUEST_CODE_PLUGIN_CONFIGURE = 1 private const val REQUEST_CODE_PLUGIN_CONFIGURE = 1
} }
private lateinit var profile: Profile private var profileId = -1
private lateinit var isProxyApps: SwitchPreference private lateinit var isProxyApps: SwitchPreference
private lateinit var plugin: IconListPreference private lateinit var plugin: IconListPreference
private lateinit var pluginConfigure: EditTextPreference private lateinit var pluginConfigure: EditTextPreference
private lateinit var pluginConfiguration: PluginConfiguration private lateinit var pluginConfiguration: PluginConfiguration
private lateinit var receiver: BroadcastReceiver
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore.privateStore preferenceManager.preferenceDataStore = DataStore.privateStore
val activity = activity!! val activity = requireActivity()
val profile = ProfileManager.getProfile(activity.intent.getIntExtra(Action.EXTRA_PROFILE_ID, -1)) profileId = activity.intent.getIntExtra(Action.EXTRA_PROFILE_ID, -1)
if (profile == null) {
activity.finish()
return
}
this.profile = profile
profile.serialize()
addPreferencesFromResource(R.xml.pref_profile) addPreferencesFromResource(R.xml.pref_profile)
if (Build.VERSION.SDK_INT >= 25 && activity.getSystemService(UserManager::class.java).isDemoUser) { if (Build.VERSION.SDK_INT >= 25 && activity.getSystemService(UserManager::class.java).isDemoUser) {
findPreference(Key.host).summary = "shadowsocks.example.org" findPreference(Key.host).summary = "shadowsocks.example.org"
...@@ -102,7 +98,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu ...@@ -102,7 +98,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
} }
pluginConfigure.onPreferenceChangeListener = this pluginConfigure.onPreferenceChangeListener = this
initPlugins() initPlugins()
app.listenForPackageChanges { initPlugins() } receiver = app.listenForPackageChanges(false) { initPlugins() }
DataStore.privateStore.registerChangeListener(this) DataStore.privateStore.registerChangeListener(this)
} }
...@@ -128,11 +124,13 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu ...@@ -128,11 +124,13 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
} }
fun saveAndExit() { fun saveAndExit() {
val profile = ProfileManager.getProfile(profileId) ?: Profile()
profile.id = profileId
profile.deserialize() profile.deserialize()
ProfileManager.updateProfile(profile) ProfileManager.updateProfile(profile)
ProfilesFragment.instance?.profilesAdapter?.deepRefreshId(profile.id) ProfilesFragment.instance?.profilesAdapter?.deepRefreshId(profileId)
if (DataStore.profileId == profile.id && DataStore.directBootAware) DirectBoot.update() if (DataStore.profileId == profileId && DataStore.directBootAware) DirectBoot.update()
activity!!.finish() requireActivity().finish()
} }
override fun onResume() { override fun onResume() {
...@@ -159,7 +157,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu ...@@ -159,7 +157,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
override fun onDisplayPreferenceDialog(preference: Preference) { override fun onDisplayPreferenceDialog(preference: Preference) {
if (preference.key == Key.pluginConfigure) { if (preference.key == Key.pluginConfigure) {
val intent = PluginManager.buildIntent(pluginConfiguration.selected, PluginContract.ACTION_CONFIGURE) val intent = PluginManager.buildIntent(pluginConfiguration.selected, PluginContract.ACTION_CONFIGURE)
if (intent.resolveActivity(activity!!.packageManager) != null) if (intent.resolveActivity(requireContext().packageManager) != null)
startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS, startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS,
pluginConfiguration.selectedOptions.toString()), REQUEST_CODE_PLUGIN_CONFIGURE) else { pluginConfiguration.selectedOptions.toString()), REQUEST_CODE_PLUGIN_CONFIGURE) else {
showPluginEditor() showPluginEditor()
...@@ -179,31 +177,30 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu ...@@ -179,31 +177,30 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
} else super.onActivityResult(requestCode, resultCode, data) } else super.onActivityResult(requestCode, resultCode, data)
} }
override fun onMenuItemClick(item: MenuItem): Boolean { override fun onMenuItemClick(item: MenuItem) = when (item.itemId) {
return when (item.itemId) { R.id.action_delete -> {
R.id.action_delete -> { val activity = requireActivity()
val activity = activity!! AlertDialog.Builder(activity)
AlertDialog.Builder(activity) .setTitle(R.string.delete_confirm_prompt)
.setTitle(R.string.delete_confirm_prompt) .setPositiveButton(R.string.yes, { _, _ ->
.setPositiveButton(R.string.yes, { _, _ -> ProfileManager.delProfile(profileId)
ProfileManager.delProfile(profile.id) activity.finish()
activity.finish() })
}) .setNegativeButton(R.string.no, null)
.setNegativeButton(R.string.no, null) .create()
.create() .show()
.show() true
true }
} R.id.action_apply -> {
R.id.action_apply -> { saveAndExit()
saveAndExit() true
true
}
else -> false
} }
else -> false
} }
override fun onDestroy() { override fun onDestroy() {
DataStore.privateStore.unregisterChangeListener(this) DataStore.privateStore.unregisterChangeListener(this)
app.unregisterReceiver(receiver)
super.onDestroy() super.onDestroy()
} }
} }
...@@ -37,7 +37,6 @@ import android.view.* ...@@ -37,7 +37,6 @@ import android.view.*
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.bg.TrafficMonitor import com.github.shadowsocks.bg.TrafficMonitor
...@@ -124,12 +123,12 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -124,12 +123,12 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private var adView: AdView? = null private var adView: AdView? = null
init { init {
edit.setOnClickListener { startConfig(item.id) } edit.setOnClickListener { startConfig(item) }
TooltipCompat.setTooltipText(edit, edit.contentDescription) TooltipCompat.setTooltipText(edit, edit.contentDescription)
itemView.setOnClickListener(this) itemView.setOnClickListener(this)
val share = itemView.findViewById<View>(R.id.share) val share = itemView.findViewById<View>(R.id.share)
share.setOnClickListener { share.setOnClickListener {
val popup = PopupMenu(activity!!, share) val popup = PopupMenu(requireContext(), share)
popup.menuInflater.inflate(R.menu.profile_share_popup, popup.menu) popup.menuInflater.inflate(R.menu.profile_share_popup, popup.menu)
popup.setOnMenuItemClickListener(this) popup.setOnMenuItemClickListener(this)
popup.show() popup.show()
...@@ -174,10 +173,10 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -174,10 +173,10 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
var adView = adView var adView = adView
if (item.host == "198.199.101.152") { if (item.host == "198.199.101.152") {
if (adView == null) { if (adView == null) {
val params = val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) ViewGroup.LayoutParams.WRAP_CONTENT)
params.gravity = Gravity.CENTER_HORIZONTAL params.gravity = Gravity.CENTER_HORIZONTAL
val context = context!! val context = requireContext()
adView = AdView(context) adView = AdView(context)
adView.layoutParams = params adView.layoutParams = params
adView.adUnitId = "ca-app-pub-9097031975646651/7760346322" adView.adUnitId = "ca-app-pub-9097031975646651/7760346322"
...@@ -209,7 +208,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -209,7 +208,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) { override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_qr_code_nfc -> { R.id.action_qr_code_nfc -> {
fragmentManager!!.beginTransaction().add(QRCodeDialog(this.item.toString()), "") requireFragmentManager().beginTransaction().add(QRCodeDialog(this.item.toString()), "")
.commitAllowingStateLoss() .commitAllowingStateLoss()
true true
} }
...@@ -230,8 +229,8 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -230,8 +229,8 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
} }
override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) = holder.bind(profiles[position]) override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) = holder.bind(profiles[position])
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ProfileViewHolder = ProfileViewHolder( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder(
LayoutInflater.from(parent!!.context).inflate(R.layout.layout_profile, parent, false)) LayoutInflater.from(parent.context).inflate(R.layout.layout_profile, parent, false))
override fun getItemCount(): Int = profiles.size override fun getItemCount(): Int = profiles.size
override fun getItemId(position: Int): Long = profiles[position].id.toLong() override fun getItemId(position: Int): Long = profiles[position].id.toLong()
...@@ -306,10 +305,12 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -306,10 +305,12 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private var txTotal: Long = 0L private var txTotal: Long = 0L
private var rxTotal: Long = 0L private var rxTotal: Long = 0L
private val clipboard by lazy { activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager } private val clipboard by lazy { requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager }
private fun startConfig(id: Int) = startActivity(Intent(context, ProfileConfigActivity::class.java) private fun startConfig(profile: Profile) {
.putExtra(Action.EXTRA_PROFILE_ID, id)) profile.serialize()
startActivity(Intent(context, ProfileConfigActivity::class.java).putExtra(Action.EXTRA_PROFILE_ID, profile.id))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.layout_list, container, false) inflater.inflate(R.layout.layout_list, container, false)
...@@ -332,7 +333,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -332,7 +333,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
profilesList.itemAnimator = animator profilesList.itemAnimator = animator
profilesList.adapter = profilesAdapter profilesList.adapter = profilesAdapter
instance = this instance = this
undoManager = UndoSnackbarManager(activity!!.findViewById(R.id.snackbar), undoManager = UndoSnackbarManager(requireActivity().findViewById(R.id.snackbar),
profilesAdapter::undo, profilesAdapter::commit) profilesAdapter::undo, profilesAdapter::commit)
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.START or ItemTouchHelper.END) { ItemTouchHelper.START or ItemTouchHelper.END) {
...@@ -352,7 +353,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -352,7 +353,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
profilesAdapter.move(viewHolder.adapterPosition, target.adapterPosition) profilesAdapter.move(viewHolder.adapterPosition, target.adapterPosition)
return true return true
} }
override fun clearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?) { override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder) super.clearView(recyclerView, viewHolder)
profilesAdapter.commitMove() profilesAdapter.commitMove()
} }
...@@ -367,29 +368,28 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -367,29 +368,28 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
} }
R.id.action_import -> { R.id.action_import -> {
try { try {
val profiles = Profile.findAll(clipboard.primaryClip.getItemAt(0).text).toList() val profiles = Profile.findAll(clipboard.primaryClip!!.getItemAt(0).text).toList()
if (profiles.isNotEmpty()) { if (profiles.isNotEmpty()) {
profiles.forEach { ProfileManager.createProfile(it) } profiles.forEach { ProfileManager.createProfile(it) }
Toast.makeText(activity, R.string.action_import_msg, Toast.LENGTH_SHORT).show() Snackbar.make(requireActivity().findViewById(R.id.snackbar), R.string.action_import_msg,
Snackbar.LENGTH_LONG).show()
return true return true
} }
} catch (exc: Exception) { } catch (_: Exception) { }
app.track(exc) Snackbar.make(requireActivity().findViewById(R.id.snackbar), R.string.action_import_err,
} Snackbar.LENGTH_LONG).show()
Snackbar.make(activity!!.findViewById(R.id.snackbar), R.string.action_import_err, Snackbar.LENGTH_LONG)
.show()
true true
} }
R.id.action_manual_settings -> { R.id.action_manual_settings -> {
startConfig(ProfileManager.createProfile().id) startConfig(ProfileManager.createProfile())
true true
} }
R.id.action_export -> { R.id.action_export -> {
val profiles = ProfileManager.getAllProfiles() val profiles = ProfileManager.getAllProfiles()
if (profiles != null) { Snackbar.make(requireActivity().findViewById(R.id.snackbar), if (profiles != null) {
clipboard.primaryClip = ClipData.newPlainText(null, profiles.joinToString("\n")) clipboard.primaryClip = ClipData.newPlainText(null, profiles.joinToString("\n"))
Toast.makeText(activity, R.string.action_export_msg, Toast.LENGTH_SHORT).show() R.string.action_export_msg
} else Toast.makeText(activity, R.string.action_export_err, Toast.LENGTH_SHORT).show() } else R.string.action_export_err, Snackbar.LENGTH_LONG).show()
true true
} }
else -> false else -> false
......
...@@ -20,29 +20,40 @@ ...@@ -20,29 +20,40 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.content.pm.PackageManager import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutManager import android.content.pm.ShortcutManager
import android.graphics.BitmapFactory
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.app.TaskStackBuilder import android.support.v4.app.TaskStackBuilder
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.util.Log
import android.util.SparseArray
import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.utils.resolveResourceId import com.github.shadowsocks.utils.resolveResourceId
import com.google.zxing.Result import com.google.android.gms.samples.vision.barcodereader.BarcodeCapture
import me.dm7.barcodescanner.zxing.ZXingScannerView import com.google.android.gms.samples.vision.barcodereader.BarcodeGraphic
import com.google.android.gms.vision.Frame
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.BarcodeDetector
import xyz.belvi.mobilevisionbarcodescanner.BarcodeRetriever
class ScannerActivity : AppCompatActivity(), ZXingScannerView.ResultHandler { class ScannerActivity : AppCompatActivity(), Toolbar.OnMenuItemClickListener, BarcodeRetriever {
companion object { companion object {
private const val MY_PERMISSIONS_REQUEST_CAMERA = 1 private const val TAG = "ScannerActivity"
private const val REQUEST_IMPORT = 2
private const val REQUEST_IMPORT_OR_FINISH = 3
} }
private lateinit var scannerView: ZXingScannerView
private fun navigateUp() { private fun navigateUp() {
val intent = parentActivityIntent val intent = parentActivityIntent
if (shouldUpRecreateTask(intent) || isTaskRoot) if (shouldUpRecreateTask(intent) || isTaskRoot)
...@@ -52,45 +63,79 @@ class ScannerActivity : AppCompatActivity(), ZXingScannerView.ResultHandler { ...@@ -52,45 +63,79 @@ class ScannerActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= 25) getSystemService(ShortcutManager::class.java).reportShortcutUsed("scan")
if (try {
(getSystemService(Context.CAMERA_SERVICE) as CameraManager).cameraIdList.isEmpty()
} catch (_: CameraAccessException) {
true
}) {
startImport()
return
}
setContentView(R.layout.layout_scanner) setContentView(R.layout.layout_scanner)
val toolbar = findViewById<Toolbar>(R.id.toolbar) val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.title = title toolbar.title = title
toolbar.setNavigationIcon(theme.resolveResourceId(R.attr.homeAsUpIndicator)) toolbar.setNavigationIcon(theme.resolveResourceId(R.attr.homeAsUpIndicator))
toolbar.setNavigationOnClickListener { navigateUp() } toolbar.setNavigationOnClickListener { navigateUp() }
scannerView = findViewById(R.id.scanner) toolbar.inflateMenu(R.menu.scanner_menu)
if (Build.VERSION.SDK_INT >= 25) getSystemService(ShortcutManager::class.java).reportShortcutUsed("scan") toolbar.setOnMenuItemClickListener(this)
(supportFragmentManager.findFragmentById(R.id.barcode) as BarcodeCapture).setRetrieval(this)
} }
override fun onResume() { override fun onRetrieved(barcode: Barcode) = runOnUiThread {
super.onResume() Profile.findAll(barcode.rawValue).forEach { ProfileManager.createProfile(it) }
val permissionCheck = ContextCompat.checkSelfPermission(this, navigateUp()
android.Manifest.permission.CAMERA)
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
scannerView.setResultHandler(this) // Register ourselves as a handler for scan results.
scannerView.startCamera() // Start camera on resume
} else ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.CAMERA),
MY_PERMISSIONS_REQUEST_CAMERA)
} }
override fun onRetrievedMultiple(closetToClick: Barcode?, barcode: MutableList<BarcodeGraphic>?) = check(false)
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { override fun onBitmapScanned(sparseArray: SparseArray<Barcode>?) { }
if (requestCode == MY_PERMISSIONS_REQUEST_CAMERA) override fun onRetrievedFailed(reason: String?) {
if (grantResults.getOrNull(0) == PackageManager.PERMISSION_GRANTED) { Log.w(TAG, reason)
scannerView.setResultHandler(this) }
scannerView.startCamera() override fun onPermissionRequestDenied() {
} else { Toast.makeText(this, R.string.add_profile_scanner_permission_required, Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.add_profile_scanner_permission_required, Toast.LENGTH_SHORT).show() startImport()
finish()
}
else super.onRequestPermissionsResult(requestCode, permissions, grantResults)
} }
override fun onPause() { override fun onMenuItemClick(item: MenuItem) = when (item.itemId) {
super.onPause() R.id.action_import -> {
scannerView.stopCamera() // Stop camera on pause startImport(true)
true
}
else -> false
} }
override fun handleResult(rawResult: Result?) { private fun startImport(manual: Boolean = false) = startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT)
Profile.findAll(rawResult?.text).forEach { ProfileManager.createProfile(it) } .addCategory(Intent.CATEGORY_OPENABLE)
navigateUp() .setType("image/*")
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true), if (manual) REQUEST_IMPORT else REQUEST_IMPORT_OR_FINISH)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_IMPORT, REQUEST_IMPORT_OR_FINISH -> if (resultCode == Activity.RESULT_OK) {
var success = false
val detector = BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.QR_CODE)
.build()
if (detector.isOperational) {
var list = listOfNotNull(data?.data)
val clipData = data?.clipData
if (clipData != null) list += (0 until clipData.itemCount).map { clipData.getItemAt(it).uri }
val resolver = contentResolver
for (uri in list) try {
val barcodes = detector.detect(Frame.Builder()
.setBitmap(BitmapFactory.decodeStream(resolver.openInputStream(uri))).build())
for (i in 0 until barcodes.size()) Profile.findAll(barcodes.valueAt(i).rawValue).forEach {
ProfileManager.createProfile(it)
success = true
}
} catch (e: Exception) {
app.track(e)
}
} else Log.w(TAG, "Google vision isn't operational.")
Toast.makeText(this, if (success) R.string.action_import_msg else R.string.action_import_err,
Toast.LENGTH_SHORT).show()
navigateUp()
} else if (requestCode == REQUEST_IMPORT_OR_FINISH) navigateUp()
else -> super.onActivityResult(requestCode, resultCode, data)
}
} }
} }
...@@ -48,7 +48,9 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection ...@@ -48,7 +48,9 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection
* Different from Android framework, this method will be called even when you call `detachService`. * Different from Android framework, this method will be called even when you call `detachService`.
*/ */
fun onServiceDisconnected() { } fun onServiceDisconnected() { }
override fun binderDied() { } override fun binderDied() {
connection.service = null
}
} }
private var connectionActive = false private var connectionActive = false
...@@ -109,6 +111,8 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection ...@@ -109,6 +111,8 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection
connectionActive = false connectionActive = false
if (instance.listenForDeath) binder?.unlinkToDeath(instance, 0) if (instance.listenForDeath) binder?.unlinkToDeath(instance, 0)
binder = null binder = null
if (instance.serviceCallback != null)
service?.stopListeningForBandwidth(instance.serviceCallback)
service = null service = null
} }
} }
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.app.Activity
import android.app.KeyguardManager import android.app.KeyguardManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
...@@ -28,13 +27,14 @@ import android.content.Intent ...@@ -28,13 +27,14 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.VpnService import android.net.VpnService
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log import android.util.Log
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.aidl.IShadowsocksService import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.broadcastReceiver import com.github.shadowsocks.utils.broadcastReceiver
class VpnRequestActivity : Activity(), ShadowsocksConnection.Interface { class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface {
companion object { companion object {
private const val TAG = "VpnRequestActivity" private const val TAG = "VpnRequestActivity"
private const val REQUEST_CONNECT = 1 private const val REQUEST_CONNECT = 1
...@@ -56,11 +56,9 @@ class VpnRequestActivity : Activity(), ShadowsocksConnection.Interface { ...@@ -56,11 +56,9 @@ class VpnRequestActivity : Activity(), ShadowsocksConnection.Interface {
} }
override fun onServiceConnected(service: IShadowsocksService) { override fun onServiceConnected(service: IShadowsocksService) {
app.handler.postDelayed({ val intent = VpnService.prepare(this)
val intent = VpnService.prepare(this) if (intent == null) onActivityResult(REQUEST_CONNECT, RESULT_OK, null)
if (intent == null) onActivityResult(REQUEST_CONNECT, RESULT_OK, null) else startActivityForResult(intent, REQUEST_CONNECT)
else startActivityForResult(intent, REQUEST_CONNECT)
}, 1000)
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
package com.github.shadowsocks.acl package com.github.shadowsocks.acl
import android.annotation.TargetApi
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputLayout
import android.support.v4.content.ContextCompat import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog import android.support.v7.app.AlertDialog
import android.support.v7.widget.DefaultItemAnimator import android.support.v7.widget.DefaultItemAnimator
...@@ -34,11 +34,10 @@ import android.support.v7.widget.LinearLayoutManager ...@@ -34,11 +34,10 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.support.v7.widget.helper.ItemTouchHelper import android.support.v7.widget.helper.ItemTouchHelper
import android.text.Editable
import android.text.TextWatcher
import android.view.* import android.view.*
import android.widget.EditText import android.widget.*
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import com.futuremind.recyclerviewfastscroll.FastScroller import com.futuremind.recyclerviewfastscroll.FastScroller
import com.futuremind.recyclerviewfastscroll.SectionTitleProvider import com.futuremind.recyclerviewfastscroll.SectionTitleProvider
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
...@@ -51,6 +50,7 @@ import com.github.shadowsocks.utils.asIterable ...@@ -51,6 +50,7 @@ import com.github.shadowsocks.utils.asIterable
import com.github.shadowsocks.utils.resolveResourceId import com.github.shadowsocks.utils.resolveResourceId
import com.github.shadowsocks.widget.UndoSnackbarManager import com.github.shadowsocks.widget.UndoSnackbarManager
import java.net.IDN import java.net.IDN
import java.net.MalformedURLException
import java.net.URL import java.net.URL
import java.util.* import java.util.*
...@@ -71,6 +71,92 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -71,6 +71,92 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
Domain, Domain,
Url; Url;
} }
private inner class AclRuleDialog(item: Any = "") : TextWatcher, AdapterView.OnItemSelectedListener {
val builder: AlertDialog.Builder
val templateSelector: Spinner
val editText: EditText
private val inputLayout: TextInputLayout
private lateinit var dialog: AlertDialog
private lateinit var positive: Button
init {
val activity = requireActivity()
val view = activity.layoutInflater.inflate(R.layout.dialog_acl_rule, null)
templateSelector = view.findViewById(R.id.template_selector)
editText = view.findViewById(R.id.content)
inputLayout = view.findViewById(R.id.content_layout)
when (item) {
is String -> {
val match = PATTERN_DOMAIN.find(item)
if (match != null) {
templateSelector.setSelection(Template.Domain.ordinal)
editText.setText(IDN.toUnicode(match.value.replace("\\.", "."),
IDN.ALLOW_UNASSIGNED or IDN.USE_STD3_ASCII_RULES))
} else {
templateSelector.setSelection(Template.Generic.ordinal)
editText.setText(item)
}
}
is URL -> {
templateSelector.setSelection(Template.Url.ordinal)
editText.setText(item.toString())
}
else -> {
templateSelector.setSelection(Template.Generic.ordinal)
editText.setText(item.toString())
}
}
templateSelector.onItemSelectedListener = this
editText.addTextChangedListener(this)
builder = AlertDialog.Builder(activity)
.setTitle(R.string.edit_rule)
.setNegativeButton(android.R.string.cancel, null)
.setView(view)
}
fun show() {
dialog = builder.create()
dialog.show()
positive = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
validate()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
override fun afterTextChanged(s: Editable) = validate(value = s)
override fun onNothingSelected(parent: AdapterView<*>?) = check(false)
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) = validate(position)
private fun validate(template: Int = templateSelector.selectedItemPosition, value: Editable = editText.text) {
val error = when (Template.values()[template]) {
Template.Generic -> if (value.isEmpty()) "" else null
Template.Domain -> try {
IDN.toASCII(value.toString(), IDN.ALLOW_UNASSIGNED or IDN.USE_STD3_ASCII_RULES)
null
} catch (e: IllegalArgumentException) {
e.cause?.message ?: e.message
}
Template.Url -> try {
URL(value.toString())
null
} catch (e: MalformedURLException) {
e.message
}
}
inputLayout.error = error
positive.isEnabled = error == null
}
fun add(): Int? {
val text = editText.text.toString()
return when (Template.values()[templateSelector.selectedItemPosition]) {
Template.Generic -> adapter.addToProxy(text)
Template.Domain -> adapter.addHostname(TEMPLATE_REGEX_DOMAIN.format(Locale.ENGLISH, IDN.toASCII(text,
IDN.ALLOW_UNASSIGNED or IDN.USE_STD3_ASCII_RULES).replace(".", "\\.")))
Template.Url -> adapter.addURL(URL(text))
}
}
}
private inner class AclRuleViewHolder(view: View) : RecyclerView.ViewHolder(view), private inner class AclRuleViewHolder(view: View) : RecyclerView.ViewHolder(view),
View.OnClickListener, View.OnLongClickListener { View.OnClickListener, View.OnLongClickListener {
...@@ -104,19 +190,18 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -104,19 +190,18 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun onClick(v: View?) { override fun onClick(v: View?) {
if (selectedItems.isNotEmpty()) onLongClick(v) else { if (selectedItems.isNotEmpty()) onLongClick(v) else {
val (templateSelector, editText, dialog) = createAclRuleDialog(item) val dialog = AclRuleDialog(item)
dialog dialog.builder
.setNeutralButton(R.string.delete, { _, _ -> .setNeutralButton(R.string.delete, { _, _ ->
adapter.remove(item) adapter.remove(item)
undoManager.remove(Pair(-1, item)) undoManager.remove(Pair(-1, item))
}) })
.setPositiveButton(android.R.string.ok, { _, _ -> .setPositiveButton(android.R.string.ok, { _, _ ->
adapter.remove(item) adapter.remove(item)
val index = adapter.addFromTemplate(templateSelector.selectedItemPosition, val index = dialog.add() ?: adapter.add(item)
editText.text.toString()) ?: adapter.add(item)
if (index != null) list.post { list.scrollToPosition(index) } if (index != null) list.post { list.scrollToPosition(index) }
}) })
.create().show() dialog.show()
} }
} }
override fun onLongClick(p0: View?): Boolean { override fun onLongClick(p0: View?): Boolean {
...@@ -143,16 +228,14 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -143,16 +228,14 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun getItemCount(): Int = acl.subnets.size() + acl.hostnames.size() + acl.urls.size() override fun getItemCount(): Int = acl.subnets.size() + acl.hostnames.size() + acl.urls.size()
override fun getSectionTitle(i: Int): String { override fun getSectionTitle(i: Int): String {
val j = i - acl.subnets.size() val j = i - acl.subnets.size()
return try { return (if (j < 0) acl.subnets[i].address.hostAddress.substring(0, 1) else {
(if (j < 0) acl.subnets[i].address.hostAddress.substring(0, 1) else { val k = j - acl.hostnames.size()
val k = j - acl.hostnames.size() if (k < 0) {
if (k < 0) { val hostname = acl.hostnames[j]
val hostname = acl.hostnames[j] // don't convert IDN yet
// don't convert IDN yet PATTERN_DOMAIN.find(hostname)?.value?.replace("\\.", ".") ?: hostname
PATTERN_DOMAIN.find(hostname)?.value?.replace("\\.", ".") ?: hostname } else acl.urls[k].host
} else acl.urls[k].host }).firstOrNull()?.toString() ?: " "
}).substring(0, 1)
} catch (_: IndexOutOfBoundsException) { " " }
} }
private fun apply() { private fun apply() {
...@@ -208,20 +291,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -208,20 +291,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
.forEach { if (result == null) result = it } .forEach { if (result == null) result = it }
return result return result
} }
fun addFromTemplate(templateValue: Int, text: String): Int? {
val template = Template.values()[templateValue]
return when (template) {
Template.Generic -> addToProxy(text)
Template.Domain -> try {
addHostname(TEMPLATE_REGEX_DOMAIN.format(Locale.ENGLISH, IDN.toASCII(text,
IDN.ALLOW_UNASSIGNED or IDN.USE_STD3_ASCII_RULES).replace(".", "\\.")))
} catch (exc: IllegalArgumentException) {
Toast.makeText(activity, exc.message, Toast.LENGTH_SHORT).show()
null
}
Template.Url -> addURL(URL(text))
}
}
fun remove(i: Int) { fun remove(i: Int) {
val j = i - acl.subnets.size() val j = i - acl.subnets.size()
...@@ -291,43 +360,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -291,43 +360,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
private lateinit var list: RecyclerView private lateinit var list: RecyclerView
private var mode: ActionMode? = null private var mode: ActionMode? = null
private lateinit var undoManager: UndoSnackbarManager<Any> private lateinit var undoManager: UndoSnackbarManager<Any>
private val clipboard by lazy { activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager } private val clipboard by lazy { requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager }
private fun onSelectedItemsUpdated() { private fun onSelectedItemsUpdated() {
if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this) if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this)
} }
private fun createAclRuleDialog(item: Any = ""): Triple<Spinner, EditText, AlertDialog.Builder> {
val view = activity!!.layoutInflater.inflate(R.layout.dialog_acl_rule, null)
val templateSelector = view.findViewById<Spinner>(R.id.template_selector)
val editText = view.findViewById<EditText>(R.id.content)
when (item) {
is String -> {
val match = PATTERN_DOMAIN.find(item)
if (match != null) {
templateSelector.setSelection(Template.Domain.ordinal)
editText.setText(IDN.toUnicode(match.value.replace("\\.", "."),
IDN.ALLOW_UNASSIGNED or IDN.USE_STD3_ASCII_RULES))
} else {
templateSelector.setSelection(Template.Generic.ordinal)
editText.setText(item)
}
}
is URL -> {
templateSelector.setSelection(Template.Url.ordinal)
editText.setText(item.toString())
}
else -> {
templateSelector.setSelection(Template.Generic.ordinal)
editText.setText(item.toString())
}
}
return Triple(templateSelector, editText, AlertDialog.Builder(activity!!)
.setTitle(R.string.edit_rule)
.setNegativeButton(android.R.string.cancel, null)
.setView(view))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.layout_custom_rules, container, false) inflater.inflate(R.layout.layout_custom_rules, container, false)
...@@ -345,12 +383,13 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -345,12 +383,13 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
toolbar.setTitle(R.string.custom_rules) toolbar.setTitle(R.string.custom_rules)
toolbar.inflateMenu(R.menu.custom_rules_menu) toolbar.inflateMenu(R.menu.custom_rules_menu)
toolbar.setOnMenuItemClickListener(this) toolbar.setOnMenuItemClickListener(this)
val activity = requireActivity()
list = view.findViewById(R.id.list) list = view.findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
list.itemAnimator = DefaultItemAnimator() list.itemAnimator = DefaultItemAnimator()
list.adapter = adapter list.adapter = adapter
view.findViewById<FastScroller>(R.id.fastscroller).setRecyclerView(list) view.findViewById<FastScroller>(R.id.fastscroller).setRecyclerView(list)
undoManager = UndoSnackbarManager(activity!!.findViewById(R.id.snackbar), adapter::undo) undoManager = UndoSnackbarManager(activity.findViewById(R.id.snackbar), adapter::undo)
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START or ItemTouchHelper.END) { ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START or ItemTouchHelper.END) {
override fun getSwipeDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int = override fun getSwipeDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int =
if (isEnabled && selectedItems.isEmpty()) super.getSwipeDirs(recyclerView, viewHolder) else 0 if (isEnabled && selectedItems.isEmpty()) super.getSwipeDirs(recyclerView, viewHolder) else 0
...@@ -392,18 +431,17 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -392,18 +431,17 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) { override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_manual_settings -> { R.id.action_manual_settings -> {
val (templateSelector, editText, dialog) = createAclRuleDialog() val dialog = AclRuleDialog()
dialog.setPositiveButton(android.R.string.ok, { _, _ -> dialog.builder.setPositiveButton(android.R.string.ok, { _, _ -> dialog.add() })
adapter.addFromTemplate(templateSelector.selectedItemPosition, editText.text.toString()) dialog.show()
}).create().show()
true true
} }
R.id.action_import -> { R.id.action_import -> {
try { try {
adapter.addToProxy(clipboard.primaryClip.getItemAt(0).text.toString()) != null check(adapter.addToProxy(clipboard.primaryClip!!.getItemAt(0).text.toString()) != null)
} catch (exc: Exception) { } catch (exc: Exception) {
Snackbar.make(activity!!.findViewById(R.id.snackbar), R.string.action_import_err, Snackbar.LENGTH_LONG) Snackbar.make(requireActivity().findViewById(R.id.snackbar), R.string.action_import_err,
.show() Snackbar.LENGTH_LONG).show()
app.track(exc) app.track(exc)
} }
true true
...@@ -420,11 +458,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -420,11 +458,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun onDetach() { override fun onDetach() {
undoManager.flush() undoManager.flush()
mode?.finish()
super.onDetach() super.onDetach()
} }
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
val activity = activity!! val activity = requireActivity()
val window = activity.window val window = activity.window
// In the end material_grey_100 is used for background, see AppCompatDrawableManager (very complicated) // In the end material_grey_100 is used for background, see AppCompatDrawableManager (very complicated)
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {
...@@ -457,7 +496,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -457,7 +496,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
else -> false else -> false
} }
override fun onDestroyActionMode(mode: ActionMode) { override fun onDestroyActionMode(mode: ActionMode) {
val activity = activity!! val activity = requireActivity()
val window = activity.window val window = activity.window
window.statusBarColor = ContextCompat.getColor(activity, window.statusBarColor = ContextCompat.getColor(activity,
activity.theme.resolveResourceId(android.R.attr.statusBarColor)) activity.theme.resolveResourceId(android.R.attr.statusBarColor))
......
...@@ -31,7 +31,6 @@ import android.os.RemoteCallbackList ...@@ -31,7 +31,6 @@ import android.os.RemoteCallbackList
import android.support.v4.os.UserManagerCompat import android.support.v4.os.UserManagerCompat
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import android.widget.Toast
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.R import com.github.shadowsocks.R
import com.github.shadowsocks.acl.Acl import com.github.shadowsocks.acl.Acl
...@@ -88,17 +87,14 @@ object BaseService { ...@@ -88,17 +87,14 @@ object BaseService {
val closeReceiver = broadcastReceiver { _, intent -> val closeReceiver = broadcastReceiver { _, intent ->
when (intent.action) { when (intent.action) {
Action.RELOAD -> service.forceLoad() Action.RELOAD -> service.forceLoad()
else -> { else -> service.stopRunner(true)
Toast.makeText(service as Context, R.string.stopping, Toast.LENGTH_SHORT).show()
service.stopRunner(true)
}
} }
} }
var closeReceiverRegistered = false var closeReceiverRegistered = false
val binder = object : IShadowsocksService.Stub() { val binder = object : IShadowsocksService.Stub() {
override fun getState(): Int = this@Data.state override fun getState(): Int = this@Data.state
override fun getProfileName(): String = profile?.formattedName ?: "Idle" override fun getProfileName(): String = profile?.name ?: "Idle"
override fun registerCallback(cb: IShadowsocksServiceCallback) { override fun registerCallback(cb: IShadowsocksServiceCallback) {
callbacks.register(cb) callbacks.register(cb)
...@@ -149,18 +145,18 @@ object BaseService { ...@@ -149,18 +145,18 @@ object BaseService {
} }
internal fun updateTrafficTotal(tx: Long, rx: Long) { internal fun updateTrafficTotal(tx: Long, rx: Long) {
val profile = profile ?: return // this.profile may have host, etc. modified and thus a re-fetch is necessary (possible race condition)
val p = ProfileManager.getProfile(profile.id) ?: return // profile may have host, etc. modified val profile = ProfileManager.getProfile((profile ?: return).id) ?: return
p.tx += tx profile.tx += tx
p.rx += rx profile.rx += rx
ProfileManager.updateProfile(p) ProfileManager.updateProfile(profile)
app.handler.post { app.handler.post {
if (bandwidthListeners.isNotEmpty()) { if (bandwidthListeners.isNotEmpty()) {
val n = callbacks.beginBroadcast() val n = callbacks.beginBroadcast()
for (i in 0 until n) { for (i in 0 until n) {
try { try {
val item = callbacks.getBroadcastItem(i) val item = callbacks.getBroadcastItem(i)
if (bandwidthListeners.contains(item.asBinder())) item.trafficPersisted(p.id) if (bandwidthListeners.contains(item.asBinder())) item.trafficPersisted(profile.id)
} catch (_: Exception) { } // ignore } catch (_: Exception) { } // ignore
} }
callbacks.finishBroadcast() callbacks.finishBroadcast()
...@@ -185,9 +181,9 @@ object BaseService { ...@@ -185,9 +181,9 @@ object BaseService {
.put("plugin_opts", plugin.toString()) .put("plugin_opts", plugin.toString())
} }
// sensitive Shadowsocks config is stored in // sensitive Shadowsocks config is stored in
val file = File((if (UserManagerCompat.isUserUnlocked(app)) app.filesDir else @TargetApi(24) { val file = File(if (UserManagerCompat.isUserUnlocked(app)) app.filesDir else @TargetApi(24) {
app.deviceContext.noBackupFilesDir // only API 24+ will be in locked state app.deviceContext.noBackupFilesDir // only API 24+ will be in locked state
}), CONFIG_FILE) }, CONFIG_FILE)
shadowsocksConfigFile = file shadowsocksConfigFile = file
file.writeText(config.toString()) file.writeText(config.toString())
return file return file
...@@ -221,9 +217,9 @@ object BaseService { ...@@ -221,9 +217,9 @@ object BaseService {
false false
} else true } else true
fun forceLoad() { fun forceLoad() {
val p = app.currentProfile val profile = app.currentProfile
?: return stopRunner(true, (this as Context).getString(R.string.profile_empty)) ?: return stopRunner(true, (this as Context).getString(R.string.profile_empty))
if (!checkProfile(p)) return if (!checkProfile(profile)) return
val s = data.state val s = data.state
when (s) { when (s) {
STOPPED -> startRunner() STOPPED -> startRunner()
...@@ -322,6 +318,7 @@ object BaseService { ...@@ -322,6 +318,7 @@ object BaseService {
stopRunner(true, getString(R.string.profile_empty)) stopRunner(true, getString(R.string.profile_empty))
return Service.START_NOT_STICKY return Service.START_NOT_STICKY
} }
profile.name = profile.formattedName // save name for later queries
data.profile = profile data.profile = profile
TrafficMonitor.reset() TrafficMonitor.reset()
......
...@@ -24,22 +24,19 @@ import android.util.Log ...@@ -24,22 +24,19 @@ import android.util.Log
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.BuildConfig import com.github.shadowsocks.BuildConfig
import org.xbill.DNS.* import org.xbill.DNS.*
import java.net.Inet6Address import java.io.IOException
import java.net.InetAddress import java.net.*
import java.net.NetworkInterface
import java.net.UnknownHostException
import okhttp3.Dns as Okdns
object Dns { object Dns {
private const val TAG = "Dns" private const val TAG = "Dns"
private val hasIPv6Support get() = try { private val hasIPv6Support get() = try {
val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() } val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() }
.count { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } > 0 .any { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress }
if (result && BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected") if (result && BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected")
result result
} catch (ex: Exception) { } catch (ex: SocketException) {
Log.e(TAG, "Failed to get interfaces' addresses.") Log.e(TAG, "Failed to get interfaces' addresses.", ex)
app.track(ex) app.track(ex)
false false
} }
...@@ -60,7 +57,7 @@ object Dns { ...@@ -60,7 +57,7 @@ object Dns {
Type.AAAA -> return (r as AAAARecord).address.hostAddress Type.AAAA -> return (r as AAAARecord).address.hostAddress
} }
} }
} catch (_: Exception) { } } catch (_: IOException) { }
return null return null
} }
private fun resolve(host: String): String? = try { private fun resolve(host: String): String? = try {
......
...@@ -25,6 +25,7 @@ import android.util.Log ...@@ -25,6 +25,7 @@ import android.util.Log
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.JniHelper import com.github.shadowsocks.JniHelper
import java.io.File import java.io.File
import java.io.FileNotFoundException
object Executable { object Executable {
const val REDSOCKS = "libredsocks.so" const val REDSOCKS = "libredsocks.so"
...@@ -37,7 +38,11 @@ object Executable { ...@@ -37,7 +38,11 @@ object Executable {
fun killAll() { fun killAll() {
for (process in File("/proc").listFiles { _, name -> TextUtils.isDigitsOnly(name) }) { for (process in File("/proc").listFiles { _, name -> TextUtils.isDigitsOnly(name) }) {
val exe = File(File(process, "cmdline").readText().split(Character.MIN_VALUE, limit = 2).first()) val exe = File(try {
File(process, "cmdline").readText()
} catch (ignore: FileNotFoundException) {
continue
}.split(Character.MIN_VALUE, limit = 2).first())
if (exe.parent == app.applicationInfo.nativeLibraryDir && EXECUTABLES.contains(exe.name)) { if (exe.parent == app.applicationInfo.nativeLibraryDir && EXECUTABLES.contains(exe.name)) {
val errno = JniHelper.sigkill(process.name.toInt()) val errno = JniHelper.sigkill(process.name.toInt())
if (errno != 0) Log.w("kill", "SIGKILL ${exe.absolutePath} (${process.name}) failed with $errno") if (errno != 0) Log.w("kill", "SIGKILL ${exe.absolutePath} (${process.name}) failed with $errno")
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
package com.github.shadowsocks.bg package com.github.shadowsocks.bg
import android.content.Context
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.acl.Acl import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
...@@ -50,10 +49,10 @@ object LocalDnsService { ...@@ -50,10 +49,10 @@ object LocalDnsService {
fun makeDns(name: String, address: String, timeout: Int, edns: Boolean = true): JSONObject { fun makeDns(name: String, address: String, timeout: Int, edns: Boolean = true): JSONObject {
val dns = JSONObject() val dns = JSONObject()
.put("Name", name) .put("Name", name)
.put("Address", (when (address.parseNumericAddress()) { .put("Address", when (address.parseNumericAddress()) {
is Inet6Address -> "[$address]" is Inet6Address -> "[$address]"
else -> address else -> address
})) })
.put("Timeout", timeout) .put("Timeout", timeout)
.put("EDNSClientSubnet", JSONObject().put("Policy", "disable")) .put("EDNSClientSubnet", JSONObject().put("Policy", "disable"))
if (edns) dns if (edns) dns
...@@ -85,7 +84,6 @@ object LocalDnsService { ...@@ -85,7 +84,6 @@ object LocalDnsService {
Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> config Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> config
.put("PrimaryDNS", localDns) .put("PrimaryDNS", localDns)
.put("AlternativeDNS", remoteDns) .put("AlternativeDNS", remoteDns)
.put("IPNetworkFile", "china_ip_list.txt")
.put("DomainFile", data.aclFile!!.absolutePath) .put("DomainFile", data.aclFile!!.absolutePath)
Acl.CHINALIST -> config Acl.CHINALIST -> config
.put("PrimaryDNS", localDns) .put("PrimaryDNS", localDns)
......
...@@ -41,7 +41,7 @@ abstract class LocalSocketListener(protected val tag: String) : Thread() { ...@@ -41,7 +41,7 @@ abstract class LocalSocketListener(protected val tag: String) : Thread() {
* Inherited class do not need to close input/output streams as they will be closed automatically. * Inherited class do not need to close input/output streams as they will be closed automatically.
*/ */
protected abstract fun accept(socket: LocalSocket) protected abstract fun accept(socket: LocalSocket)
override final fun run() { final override fun run() {
socketFile.delete() // It's a must-have to close and reuse previous local socket. socketFile.delete() // It's a must-have to close and reuse previous local socket.
LocalSocket().use { localSocket -> LocalSocket().use { localSocket ->
val serverSocket = try { val serverSocket = try {
......
...@@ -23,7 +23,6 @@ package com.github.shadowsocks.bg ...@@ -23,7 +23,6 @@ package com.github.shadowsocks.bg
import android.app.Service import android.app.Service
import android.content.Intent import android.content.Intent
import android.os.IBinder import android.os.IBinder
import com.github.shadowsocks.database.Profile
/** /**
* Shadowsocks service at its minimum. * Shadowsocks service at its minimum.
......
...@@ -30,11 +30,12 @@ import com.github.shadowsocks.R ...@@ -30,11 +30,12 @@ import com.github.shadowsocks.R
import com.github.shadowsocks.ShadowsocksConnection import com.github.shadowsocks.ShadowsocksConnection
import com.github.shadowsocks.aidl.IShadowsocksService import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import com.github.shadowsocks.preference.DataStore
import android.service.quicksettings.TileService as BaseTileService import android.service.quicksettings.TileService as BaseTileService
@RequiresApi(24) @RequiresApi(24)
class TileService : BaseTileService(), ShadowsocksConnection.Interface { class TileService : BaseTileService(), ShadowsocksConnection.Interface {
private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_service_idle).setTint(0x79ffffff) } private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_service_idle) }
private val iconBusy by lazy { Icon.createWithResource(this, R.drawable.ic_service_busy) } private val iconBusy by lazy { Icon.createWithResource(this, R.drawable.ic_service_busy) }
private val iconConnected by lazy { Icon.createWithResource(this, R.drawable.ic_service_active) } private val iconConnected by lazy { Icon.createWithResource(this, R.drawable.ic_service_active) }
private val keyguard by lazy { getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager } private val keyguard by lazy { getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager }
...@@ -81,7 +82,7 @@ class TileService : BaseTileService(), ShadowsocksConnection.Interface { ...@@ -81,7 +82,7 @@ class TileService : BaseTileService(), ShadowsocksConnection.Interface {
} }
override fun onClick() { override fun onClick() {
if (isLocked) unlockAndRun(this::toggle) else toggle() if (isLocked && !DataStore.directBootAware) unlockAndRun(this::toggle) else toggle()
} }
private fun toggle() { private fun toggle() {
......
...@@ -44,7 +44,7 @@ object TrafficMonitor { ...@@ -44,7 +44,7 @@ object TrafficMonitor {
private val units = arrayOf("KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB", "NB", "DB", "CB") private val units = arrayOf("KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB", "NB", "DB", "CB")
private val numberFormat = DecimalFormat("@@@") private val numberFormat = DecimalFormat("@@@")
fun formatTraffic(size: Long): String { fun formatTraffic(size: Long): String {
var n: Double = size.toDouble() var n = size.toDouble()
var i = -1 var i = -1
while (n >= 999.5) { while (n >= 999.5) {
n /= 1024 n /= 1024
......
...@@ -37,8 +37,7 @@ class TrafficMonitorThread : LocalSocketListener("TrafficMonitorThread") { ...@@ -37,8 +37,7 @@ class TrafficMonitorThread : LocalSocketListener("TrafficMonitorThread") {
if (socket.inputStream.read(buffer) != 16) throw IOException("Unexpected traffic stat length") if (socket.inputStream.read(buffer) != 16) throw IOException("Unexpected traffic stat length")
val stat = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN) val stat = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN)
TrafficMonitor.update(stat.getLong(0), stat.getLong(8)) TrafficMonitor.update(stat.getLong(0), stat.getLong(8))
socket.outputStream.write(0) } catch (e: IOException) {
} catch (e: Exception) {
Log.e(tag, "Error when recv traffic stat", e) Log.e(tag, "Error when recv traffic stat", e)
app.track(e) app.track(e)
} }
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
package com.github.shadowsocks.bg package com.github.shadowsocks.bg
import android.app.Service import android.app.Service
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.LocalSocket import android.net.*
import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
import android.util.Log import android.util.Log
...@@ -38,6 +40,7 @@ import com.github.shadowsocks.utils.Subnet ...@@ -38,6 +40,7 @@ import com.github.shadowsocks.utils.Subnet
import com.github.shadowsocks.utils.parseNumericAddress import com.github.shadowsocks.utils.parseNumericAddress
import java.io.File import java.io.File
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException
import java.lang.reflect.Method import java.lang.reflect.Method
import java.util.* import java.util.*
import android.net.VpnService as BaseVpnService import android.net.VpnService as BaseVpnService
...@@ -49,22 +52,52 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -49,22 +52,52 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private const val PRIVATE_VLAN6 = "fdfe:dcba:9876::%s" private const val PRIVATE_VLAN6 = "fdfe:dcba:9876::%s"
private val getInt: Method = FileDescriptor::class.java.getDeclaredMethod("getInt$") private val getInt: Method = FileDescriptor::class.java.getDeclaredMethod("getInt$")
/**
* Unfortunately registerDefaultNetworkCallback is going to return VPN interface since Android P DP1:
* https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
*
* This makes doing a requestNetwork with REQUEST necessary so that we don't get ALL possible networks that
* satisfies default network capabilities but only THE default network. Unfortunately we need to have
* android.permission.CHANGE_NETWORK_STATE to be able to call requestNetwork.
*
* Source: https://android.googlesource.com/platform/frameworks/base/+/2df4c7d/services/core/java/com/android/server/ConnectivityService.java#887
*/
private val defaultNetworkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build()
} }
private inner class ProtectWorker : LocalSocketListener("ShadowsocksVpnThread") { private inner class ProtectWorker : LocalSocketListener("ShadowsocksVpnThread") {
override val socketFile: File = File(app.deviceContext.filesDir, "protect_path") override val socketFile: File = File(app.deviceContext.filesDir, "protect_path")
override fun accept(socket: LocalSocket) { override fun accept(socket: LocalSocket) {
var success = false
try { try {
socket.inputStream.read() socket.inputStream.read()
val fds = socket.ancillaryFileDescriptors val fd = socket.ancillaryFileDescriptors!!.single()!!
if (fds.isEmpty()) return val fdInt = getInt.invoke(fd) as Int
val fd = getInt.invoke(fds.first()) as Int try {
val ret = protect(fd) val network = underlyingNetwork
JniHelper.close(fd) // Trick to close file decriptor success = if (network != null && Build.VERSION.SDK_INT >= 23) {
socket.outputStream.write(if (ret) 0 else 1) network.bindSocket(fd)
true
} else protect(fdInt)
} catch (e: Exception) {
Log.e(tag, "Error when protect socket", e)
app.track(e)
} finally {
JniHelper.close(fdInt) // Trick to close file decriptor
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e(tag, "Error when protect socket", e) Log.e(tag, "Error when receiving ancillary fd", e)
app.track(e)
}
try {
socket.outputStream.write(if (success) 0 else 1)
} catch (e: IOException) {
Log.e(tag, "Error when returning result in protect", e)
app.track(e) app.track(e)
} }
} }
...@@ -82,6 +115,26 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -82,6 +115,26 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private var conn: ParcelFileDescriptor? = null private var conn: ParcelFileDescriptor? = null
private var worker: ProtectWorker? = null private var worker: ProtectWorker? = null
private var tun2socksProcess: GuardedProcess? = null private var tun2socksProcess: GuardedProcess? = null
private var underlyingNetwork: Network? = null
set(value) {
if (Build.VERSION.SDK_INT >= 22) setUnderlyingNetworks(if (value == null) null else arrayOf(value))
field = value
}
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
underlyingNetwork = network
}
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) {
// it's a good idea to refresh capabilities
underlyingNetwork = network
}
override fun onLost(network: Network) {
underlyingNetwork = null
}
}
private var listeningForDefaultNetwork = false
override fun onBind(intent: Intent): IBinder? = when (intent.action) { override fun onBind(intent: Intent): IBinder? = when (intent.action) {
SERVICE_INTERFACE -> super<BaseVpnService>.onBind(intent) SERVICE_INTERFACE -> super<BaseVpnService>.onBind(intent)
...@@ -91,6 +144,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -91,6 +144,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
override fun onRevoke() = stopRunner(true) override fun onRevoke() = stopRunner(true)
override fun killProcesses() { override fun killProcesses() {
if (listeningForDefaultNetwork) {
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
listeningForDefaultNetwork = false
}
worker?.stopThread() worker?.stopThread()
worker = null worker = null
super.killProcesses() super.killProcesses()
...@@ -118,7 +175,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -118,7 +175,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
super.startNativeProcesses() super.startNativeProcesses()
val fd = startVpn() val fd = startVpn()
if (!sendFd(fd)) throw Exception("sendFd failed") if (!sendFd(fd)) throw IOException("sendFd failed")
} }
override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> { override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> {
...@@ -172,6 +229,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -172,6 +229,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
this.conn = conn this.conn = conn
val fd = conn.fd val fd = conn.fd
// we want REQUEST here instead of LISTEN
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
listeningForDefaultNetwork = true
val cmd = arrayListOf(File(applicationInfo.nativeLibraryDir, Executable.TUN2SOCKS).absolutePath, val cmd = arrayListOf(File(applicationInfo.nativeLibraryDir, Executable.TUN2SOCKS).absolutePath,
"--netif-ipaddr", PRIVATE_VLAN.format(Locale.ENGLISH, "2"), "--netif-ipaddr", PRIVATE_VLAN.format(Locale.ENGLISH, "2"),
"--netif-netmask", "255.255.255.0", "--netif-netmask", "255.255.255.0",
......
/*******************************************************************************
* *
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2017 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* 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.github.shadowsocks.database
import android.database.sqlite.SQLiteDatabaseLockedException
import com.j256.ormlite.dao.Dao
import com.j256.ormlite.support.ConnectionSource
import com.j256.ormlite.table.TableUtils
import java.sql.SQLException
private val Throwable.ultimateCause: Throwable get() {
var result = this
while (true) {
val cause = result.cause ?: return result
result = cause
}
}
@Throws(SQLException::class)
fun <T> safeWrapper(func: () -> T): T {
while (true) {
try {
return func()
} catch (e: SQLException) {
if (e.ultimateCause !is SQLiteDatabaseLockedException) throw e
}
}
}
@Throws(SQLException::class)
inline fun <reified T> ConnectionSource.createTableSafe() = safeWrapper { TableUtils.createTable(this, T::class.java) }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.queryAllSafe(): MutableList<T> = safeWrapper { queryForAll() }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.queryByIdSafe(id: ID?): T? = safeWrapper { queryForId(id) }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.updateSafe(data: T?): Int = safeWrapper { update(data) }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.replaceSafe(data: T?): Dao.CreateOrUpdateStatus? = safeWrapper { createOrUpdate(data) }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.deleteByIdSafe(id: ID?) = safeWrapper { deleteById(id) }
@Throws(SQLException::class)
fun <T, ID> Dao<T, ID>.executeSafe(statement: String?) = safeWrapper { executeRawNoArgs(statement) }
...@@ -37,18 +37,18 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25) ...@@ -37,18 +37,18 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val kvPairDao: Dao<KeyValuePair, String?> by lazy { getDao(KeyValuePair::class.java) as Dao<KeyValuePair, String?> } val kvPairDao: Dao<KeyValuePair, String?> by lazy { getDao(KeyValuePair::class.java) as Dao<KeyValuePair, String?> }
override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) { override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource) {
TableUtils.createTable(connectionSource, Profile::class.java) connectionSource.createTableSafe<Profile>()
TableUtils.createTable(connectionSource, KeyValuePair::class.java) connectionSource.createTableSafe<KeyValuePair>()
} }
private fun recreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) { private fun recreate(database: SQLiteDatabase?, connectionSource: ConnectionSource) {
TableUtils.dropTable<Profile, Int>(connectionSource, Profile::class.java, true) TableUtils.dropTable<Profile, Int>(connectionSource, Profile::class.java, true)
TableUtils.dropTable<KeyValuePair, String?>(connectionSource, KeyValuePair::class.java, true) TableUtils.dropTable<KeyValuePair, String?>(connectionSource, KeyValuePair::class.java, true)
onCreate(database, connectionSource) onCreate(database, connectionSource)
} }
override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?, override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource,
oldVersion: Int, newVersion: Int) { oldVersion: Int, newVersion: Int) {
if (oldVersion < 7) { if (oldVersion < 7) {
recreate(database, connectionSource) recreate(database, connectionSource)
...@@ -57,38 +57,38 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25) ...@@ -57,38 +57,38 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25)
try { try {
if (oldVersion < 8) { if (oldVersion < 8) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
} }
if (oldVersion < 9) { if (oldVersion < 9) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN route VARCHAR DEFAULT 'all';") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN route VARCHAR DEFAULT 'all';")
} else if (oldVersion < 19) { } else if (oldVersion < 19) {
profileDao.executeRawNoArgs("UPDATE `profile` SET route = 'all' WHERE route IS NULL;") profileDao.executeSafe("UPDATE `profile` SET route = 'all' WHERE route IS NULL;")
} }
if (oldVersion < 11) { if (oldVersion < 11) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN ipv6 SMALLINT;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN ipv6 SMALLINT;")
} }
if (oldVersion < 12) { if (oldVersion < 12) {
profileDao.executeRawNoArgs("BEGIN TRANSACTION;") profileDao.executeSafe("BEGIN TRANSACTION;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` RENAME TO `tmp`;") profileDao.executeSafe("ALTER TABLE `profile` RENAME TO `tmp`;")
TableUtils.createTable(connectionSource, Profile::class.java) connectionSource.createTableSafe<Profile>()
profileDao.executeRawNoArgs( profileDao.executeSafe(
"INSERT INTO `profile`(id, name, host, localPort, remotePort, password, method, route, proxyApps, bypass," + "INSERT INTO `profile`(id, name, host, localPort, remotePort, password, method, route," +
" udpdns, ipv6, individual) " + " proxyApps, bypass, udpdns, ipv6, individual) " +
"SELECT id, name, host, localPort, remotePort, password, method, route, 1 - global, bypass, udpdns, ipv6," + "SELECT id, name, host, localPort, remotePort, password, method, route, 1 - global," +
" individual FROM `tmp`;") " bypass, udpdns, ipv6, individual FROM `tmp`;")
profileDao.executeRawNoArgs("DROP TABLE `tmp`;") profileDao.executeSafe("DROP TABLE `tmp`;")
profileDao.executeRawNoArgs("COMMIT;") profileDao.executeSafe("COMMIT;")
} else if (oldVersion < 13) { } else if (oldVersion < 13) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN tx LONG;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN tx LONG;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN rx LONG;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN rx LONG;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN date VARCHAR;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN date VARCHAR;")
} }
if (oldVersion < 15) { if (oldVersion < 15) {
if (oldVersion >= 12) profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN userOrder LONG;") if (oldVersion >= 12) profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN userOrder LONG;")
var i = 0L var i = 0L
val apps by lazy { app.packageManager.getInstalledApplications(0) } val apps by lazy { app.packageManager.getInstalledApplications(0) }
for (profile in profileDao.queryForAll()) { for (profile in profileDao.queryAllSafe()) {
if (oldVersion < 14) { if (oldVersion < 14) {
val uidSet = profile.individual.split('|').filter(TextUtils::isDigitsOnly) val uidSet = profile.individual.split('|').filter(TextUtils::isDigitsOnly)
.map(String::toInt).toSet() .map(String::toInt).toSet()
...@@ -96,28 +96,28 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25) ...@@ -96,28 +96,28 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25)
.joinToString("\n") { it.packageName } .joinToString("\n") { it.packageName }
} }
profile.userOrder = i profile.userOrder = i
profileDao.update(profile) profileDao.updateSafe(profile)
i += 1 i += 1
} }
} }
if (oldVersion < 16) { if (oldVersion < 16) {
profileDao.executeRawNoArgs( profileDao.executeSafe(
"UPDATE `profile` SET route = 'bypass-lan-china' WHERE route = 'bypass-china'") "UPDATE `profile` SET route = 'bypass-lan-china' WHERE route = 'bypass-china'")
} }
if (oldVersion < 21) { if (oldVersion < 21) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN remoteDns VARCHAR DEFAULT '8.8.8.8';") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN remoteDns VARCHAR DEFAULT '8.8.8.8';")
} }
if (oldVersion < 17) { if (oldVersion < 17) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN plugin VARCHAR;") profileDao.executeSafe("ALTER TABLE `profile` ADD COLUMN plugin VARCHAR;")
} else if (oldVersion < 22) { } else if (oldVersion < 22) {
// upgrade kcptun to SIP003 plugin // upgrade kcptun to SIP003 plugin
profileDao.executeRawNoArgs("BEGIN TRANSACTION;") profileDao.executeSafe("BEGIN TRANSACTION;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` RENAME TO `tmp`;") profileDao.executeSafe("ALTER TABLE `profile` RENAME TO `tmp`;")
TableUtils.createTable(connectionSource, Profile::class.java) connectionSource.createTableSafe<Profile>()
profileDao.executeRawNoArgs( profileDao.executeSafe(
"INSERT INTO `profile`(id, name, host, localPort, remotePort, password, method, route, " + "INSERT INTO `profile`(id, name, host, localPort, remotePort, password, method, route, " +
"remoteDns, proxyApps, bypass, udpdns, ipv6, individual, tx, rx, date, userOrder, " + "remoteDns, proxyApps, bypass, udpdns, ipv6, individual, tx, rx, date, userOrder, " +
"plugin) " + "plugin) " +
...@@ -125,17 +125,17 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25) ...@@ -125,17 +125,17 @@ object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25)
"CASE WHEN kcp = 1 THEN kcpPort ELSE remotePort END, password, method, route, " + "CASE WHEN kcp = 1 THEN kcpPort ELSE remotePort END, password, method, route, " +
"remoteDns, proxyApps, bypass, udpdns, ipv6, individual, tx, rx, date, userOrder, " + "remoteDns, proxyApps, bypass, udpdns, ipv6, individual, tx, rx, date, userOrder, " +
"CASE WHEN kcp = 1 THEN 'kcptun ' || kcpcli ELSE NULL END FROM `tmp`;") "CASE WHEN kcp = 1 THEN 'kcptun ' || kcpcli ELSE NULL END FROM `tmp`;")
profileDao.executeRawNoArgs("DROP TABLE `tmp`;") profileDao.executeSafe("DROP TABLE `tmp`;")
profileDao.executeRawNoArgs("COMMIT;") profileDao.executeSafe("COMMIT;")
} }
if (oldVersion < 23) { if (oldVersion < 23) {
profileDao.executeRawNoArgs("BEGIN TRANSACTION;") profileDao.executeSafe("BEGIN TRANSACTION;")
TableUtils.createTable(connectionSource, KeyValuePair::class.java) connectionSource.createTableSafe<KeyValuePair>()
profileDao.executeRawNoArgs("COMMIT;") profileDao.executeSafe("COMMIT;")
val old = PreferenceManager.getDefaultSharedPreferences(app) val old = PreferenceManager.getDefaultSharedPreferences(app)
PublicDatabase.kvPairDao.createOrUpdate(KeyValuePair(Key.id).put(old.getInt(Key.id, 0))) PublicDatabase.kvPairDao.replaceSafe(KeyValuePair(Key.id).put(old.getInt(Key.id, 0)))
PublicDatabase.kvPairDao.createOrUpdate(KeyValuePair(Key.tfo).put(old.getBoolean(Key.tfo, false))) PublicDatabase.kvPairDao.replaceSafe(KeyValuePair(Key.tfo).put(old.getBoolean(Key.tfo, false)))
} }
if (oldVersion < 25) { if (oldVersion < 25) {
......
...@@ -31,52 +31,64 @@ import com.j256.ormlite.field.DataType ...@@ -31,52 +31,64 @@ import com.j256.ormlite.field.DataType
import com.j256.ormlite.field.DatabaseField import com.j256.ormlite.field.DatabaseField
import java.io.Serializable import java.io.Serializable
import java.net.URI import java.net.URI
import java.net.URISyntaxException
import java.util.* import java.util.*
class Profile : Serializable { class Profile : Serializable {
companion object { companion object {
private const val TAG = "ShadowParser" private const val TAG = "ShadowParser"
private const val serialVersionUID = 0L
private val pattern = """(?i)ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;\[\]]*[-a-zA-Z0-9+&@#/%=~_|\[\]]""".toRegex() private val pattern = """(?i)ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;\[\]]*[-a-zA-Z0-9+&@#/%=~_|\[\]]""".toRegex()
private val userInfoPattern = "^(.+?):(.*)$".toRegex() private val userInfoPattern = "^(.+?):(.*)$".toRegex()
private val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".toRegex() private val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".toRegex()
fun findAll(data: CharSequence?) = pattern.findAll(data ?: "").map { fun findAll(data: CharSequence?) = pattern.findAll(data ?: "").map {
val uri = Uri.parse(it.value) val uri = Uri.parse(it.value)
if (uri.userInfo == null) { try {
val match = legacyPattern.matchEntire(String(Base64.decode(uri.host, Base64.NO_PADDING))) if (uri.userInfo == null) {
if (match != null) { val match = legacyPattern.matchEntire(String(Base64.decode(uri.host, Base64.NO_PADDING)))
val profile = Profile() if (match != null) {
profile.method = match.groupValues[1].toLowerCase() val profile = Profile()
profile.password = match.groupValues[2] profile.method = match.groupValues[1].toLowerCase()
profile.host = match.groupValues[3] profile.password = match.groupValues[2]
profile.remotePort = match.groupValues[4].toInt() profile.host = match.groupValues[3]
profile.plugin = uri.getQueryParameter(Key.plugin) profile.remotePort = match.groupValues[4].toInt()
profile.name = uri.fragment profile.plugin = uri.getQueryParameter(Key.plugin)
profile profile.name = uri.fragment
profile
} else {
Log.e(TAG, "Unrecognized URI: ${it.value}")
null
}
} else { } else {
Log.e(TAG, "Unrecognized URI: ${it.value}") val match = userInfoPattern.matchEntire(String(Base64.decode(uri.userInfo,
null Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE)))
} if (match != null) {
} else { val profile = Profile()
val match = userInfoPattern.matchEntire(String(Base64.decode(uri.userInfo, profile.method = match.groupValues[1]
Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE))) profile.password = match.groupValues[2]
if (match != null) { // bug in Android: https://code.google.com/p/android/issues/detail?id=192855
val profile = Profile() try {
profile.method = match.groupValues[1] val javaURI = URI(it.value)
profile.password = match.groupValues[2] profile.host = javaURI.host ?: ""
// bug in Android: https://code.google.com/p/android/issues/detail?id=192855 if (profile.host.firstOrNull() == '[' && profile.host.lastOrNull() == ']')
val javaURI = URI(it.value) profile.host = profile.host.substring(1, profile.host.length - 1)
profile.host = javaURI.host profile.remotePort = javaURI.port
if (profile.host.firstOrNull() == '[' && profile.host.lastOrNull() == ']') profile.plugin = uri.getQueryParameter(Key.plugin)
profile.host = profile.host.substring(1, profile.host.length - 1) profile.name = uri.fragment ?: ""
profile.remotePort = javaURI.port profile
profile.plugin = uri.getQueryParameter(Key.plugin) } catch (e: URISyntaxException) {
profile.name = uri.fragment ?: "" Log.e(TAG, "Invalid URI: ${it.value}")
profile null
} else { }
Log.e(TAG, "Unknown user info: ${it.value}") } else {
null Log.e(TAG, "Unknown user info: ${it.value}")
null
}
} }
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Invalid base64 detected: ${it.value}")
null
} }
}.filterNotNull() }.filterNotNull()
} }
......
...@@ -25,79 +25,77 @@ import com.github.shadowsocks.App.Companion.app ...@@ -25,79 +25,77 @@ import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.ProfilesFragment import com.github.shadowsocks.ProfilesFragment
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot import com.github.shadowsocks.utils.DirectBoot
import java.sql.SQLException
/**
* SQLExceptions are not caught (and therefore will cause crash) for insert/update transactions
* to ensure we are in a consistent state.
*/
object ProfileManager { object ProfileManager {
private const val TAG = "ProfileManager" private const val TAG = "ProfileManager"
@Throws(SQLException::class)
fun createProfile(p: Profile? = null): Profile { fun createProfile(p: Profile? = null): Profile {
val profile = p ?: Profile() val profile = p ?: Profile()
profile.id = 0 profile.id = 0
try { val oldProfile = app.currentProfile
val oldProfile = app.currentProfile if (oldProfile != null) {
if (oldProfile != null) { // Copy Feature Settings from old profile
// Copy Feature Settings from old profile profile.route = oldProfile.route
profile.route = oldProfile.route profile.ipv6 = oldProfile.ipv6
profile.ipv6 = oldProfile.ipv6 profile.proxyApps = oldProfile.proxyApps
profile.proxyApps = oldProfile.proxyApps profile.bypass = oldProfile.bypass
profile.bypass = oldProfile.bypass profile.individual = oldProfile.individual
profile.individual = oldProfile.individual profile.udpdns = oldProfile.udpdns
profile.udpdns = oldProfile.udpdns
}
val last = PrivateDatabase.profileDao.queryRaw(PrivateDatabase.profileDao.queryBuilder()
.selectRaw("MAX(userOrder)").prepareStatementString()).firstResult
if (last != null && last.size == 1 && last[0] != null) profile.userOrder = last[0].toLong() + 1
PrivateDatabase.profileDao.createOrUpdate(profile)
ProfilesFragment.instance?.profilesAdapter?.add(profile)
} catch (ex: Exception) {
Log.e(TAG, "addProfile", ex)
app.track(ex)
} }
val last = safeWrapper {
PrivateDatabase.profileDao.queryRaw(PrivateDatabase.profileDao.queryBuilder()
.selectRaw("MAX(userOrder)").prepareStatementString()).firstResult
}
if (last != null && last.size == 1 && last[0] != null) profile.userOrder = last[0].toLong() + 1
PrivateDatabase.profileDao.replaceSafe(profile)
ProfilesFragment.instance?.profilesAdapter?.add(profile)
return profile return profile
} }
/** /**
* Note: It's caller's responsibility to update DirectBoot profile if necessary. * Note: It's caller's responsibility to update DirectBoot profile if necessary.
*/ */
fun updateProfile(profile: Profile): Boolean = try { @Throws(SQLException::class)
PrivateDatabase.profileDao.update(profile) fun updateProfile(profile: Profile) = PrivateDatabase.profileDao.updateSafe(profile)
true
} catch (ex: Exception) {
Log.e(TAG, "updateProfile", ex)
app.track(ex)
false
}
fun getProfile(id: Int): Profile? = try { fun getProfile(id: Int): Profile? = try {
PrivateDatabase.profileDao.queryForId(id) PrivateDatabase.profileDao.queryByIdSafe(id)
} catch (ex: Exception) { } catch (ex: SQLException) {
Log.e(TAG, "getProfile", ex) Log.e(TAG, "getProfile", ex)
app.track(ex) app.track(ex)
null null
} }
fun delProfile(id: Int): Boolean = try { @Throws(SQLException::class)
PrivateDatabase.profileDao.deleteById(id) fun delProfile(id: Int) {
PrivateDatabase.profileDao.deleteByIdSafe(id)
ProfilesFragment.instance?.profilesAdapter?.removeId(id) ProfilesFragment.instance?.profilesAdapter?.removeId(id)
if (id == DataStore.profileId && DataStore.directBootAware) DirectBoot.clean() if (id == DataStore.profileId && DataStore.directBootAware) DirectBoot.clean()
true
} catch (ex: Exception) {
Log.e(TAG, "delProfile", ex)
app.track(ex)
false
} }
fun getFirstProfile(): Profile? = try { fun getFirstProfile(): Profile? = try {
val result = PrivateDatabase.profileDao.query(PrivateDatabase.profileDao.queryBuilder().limit(1L).prepare()) safeWrapper {
if (result.size == 1) result[0] else null PrivateDatabase.profileDao.query(
} catch (ex: Exception) { PrivateDatabase.profileDao.queryBuilder().limit(1L).prepare()).singleOrNull()
Log.e(TAG, "getAllProfiles", ex) }
} catch (ex: SQLException) {
Log.e(TAG, "getFirstProfile", ex)
app.track(ex) app.track(ex)
null null
} }
fun getAllProfiles(): List<Profile>? = try { fun getAllProfiles(): List<Profile>? = try {
PrivateDatabase.profileDao.query(PrivateDatabase.profileDao.queryBuilder().orderBy("userOrder", true).prepare()) safeWrapper {
} catch (ex: Exception) { PrivateDatabase.profileDao.query(
PrivateDatabase.profileDao.queryBuilder().orderBy("userOrder", true).prepare())
}
} catch (ex: SQLException) {
Log.e(TAG, "getAllProfiles", ex) Log.e(TAG, "getAllProfiles", ex)
app.track(ex) app.track(ex)
null null
......
...@@ -34,20 +34,21 @@ object PublicDatabase : OrmLiteSqliteOpenHelper(app.deviceContext, Key.DB_PUBLIC ...@@ -34,20 +34,21 @@ object PublicDatabase : OrmLiteSqliteOpenHelper(app.deviceContext, Key.DB_PUBLIC
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val kvPairDao: Dao<KeyValuePair, String?> by lazy { getDao(KeyValuePair::class.java) as Dao<KeyValuePair, String?> } val kvPairDao: Dao<KeyValuePair, String?> by lazy { getDao(KeyValuePair::class.java) as Dao<KeyValuePair, String?> }
override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) { override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource) {
TableUtils.createTable(connectionSource, KeyValuePair::class.java) connectionSource.createTableSafe<KeyValuePair>()
} }
override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?, override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?,
oldVersion: Int, newVersion: Int) { oldVersion: Int, newVersion: Int) {
if (oldVersion < 1) { if (oldVersion < 1) {
PrivateDatabase.kvPairDao.queryBuilder().where().`in`("key", safeWrapper {
PrivateDatabase.kvPairDao.queryBuilder().where().`in`("key",
Key.id, Key.tfo, Key.serviceMode, Key.portProxy, Key.portLocalDns, Key.portTransproxy).query() Key.id, Key.tfo, Key.serviceMode, Key.portProxy, Key.portLocalDns, Key.portTransproxy).query()
.forEach { kvPairDao.createOrUpdate(it) } }.forEach { kvPairDao.replaceSafe(it) }
} }
if (oldVersion < 2) { if (oldVersion < 2) {
kvPairDao.createOrUpdate(KeyValuePair(Acl.CUSTOM_RULES).put(Acl().fromId(Acl.CUSTOM_RULES).toString())) kvPairDao.replaceSafe(KeyValuePair(Acl.CUSTOM_RULES).put(Acl().fromId(Acl.CUSTOM_RULES).toString()))
} }
} }
......
...@@ -25,7 +25,7 @@ import android.os.Bundle ...@@ -25,7 +25,7 @@ import android.os.Bundle
class NativePlugin(resolveInfo: ResolveInfo) : ResolvedPlugin(resolveInfo) { class NativePlugin(resolveInfo: ResolveInfo) : ResolvedPlugin(resolveInfo) {
init { init {
assert(resolveInfo.providerInfo != null) check(resolveInfo.providerInfo != null)
} }
override val metaData: Bundle get() = resolveInfo.providerInfo.metaData override val metaData: Bundle get() = resolveInfo.providerInfo.metaData
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
package com.github.shadowsocks.plugin package com.github.shadowsocks.plugin
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
...@@ -84,11 +85,16 @@ object PluginManager { ...@@ -84,11 +85,16 @@ object PluginManager {
""", Base64.DEFAULT)) """, Base64.DEFAULT))
} }
private val receiver by lazy { app.listenForPackageChanges { synchronized(this) { cachedPlugins = null } } } private var receiver: BroadcastReceiver? = null
private var cachedPlugins: Map<String, Plugin>? = null private var cachedPlugins: Map<String, Plugin>? = null
fun fetchPlugins(): Map<String, Plugin> { fun fetchPlugins(): Map<String, Plugin> {
receiver
return synchronized(this) { return synchronized(this) {
if (receiver == null) receiver = app.listenForPackageChanges {
synchronized(this) {
receiver = null
cachedPlugins = null
}
}
if (cachedPlugins == null) { if (cachedPlugins == null) {
val pm = app.packageManager val pm = app.packageManager
cachedPlugins = (pm.queryIntentContentProviders(Intent(PluginContract.ACTION_NATIVE_PLUGIN), cachedPlugins = (pm.queryIntentContentProviders(Intent(PluginContract.ACTION_NATIVE_PLUGIN),
...@@ -128,7 +134,7 @@ object PluginManager { ...@@ -128,7 +134,7 @@ object PluginManager {
private fun initNative(options: PluginOptions): String? { private fun initNative(options: PluginOptions): String? {
val providers = app.packageManager.queryIntentContentProviders( val providers = app.packageManager.queryIntentContentProviders(
Intent(PluginContract.ACTION_NATIVE_PLUGIN, buildUri(options.id)), 0) Intent(PluginContract.ACTION_NATIVE_PLUGIN, buildUri(options.id)), 0)
assert(providers.size == 1) check(providers.size == 1)
val uri = Uri.Builder() val uri = Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT) .scheme(ContentResolver.SCHEME_CONTENT)
.authority(providers[0].providerInfo.authority) .authority(providers[0].providerInfo.authority)
...@@ -148,7 +154,7 @@ object PluginManager { ...@@ -148,7 +154,7 @@ object PluginManager {
out.putString(PluginContract.EXTRA_OPTIONS, options.id) out.putString(PluginContract.EXTRA_OPTIONS, options.id)
val result = cr.call(uri, PluginContract.METHOD_GET_EXECUTABLE, null, out) val result = cr.call(uri, PluginContract.METHOD_GET_EXECUTABLE, null, out)
.getString(PluginContract.EXTRA_ENTRY) .getString(PluginContract.EXTRA_ENTRY)
assert(File(result).canExecute()) check(File(result).canExecute())
return result return result
} }
...@@ -167,7 +173,7 @@ object PluginManager { ...@@ -167,7 +173,7 @@ object PluginManager {
do { do {
val path = cursor.getString(0) val path = cursor.getString(0)
val file = File(pluginDir, path) val file = File(pluginDir, path)
assert(file.absolutePath.startsWith(pluginDirPath)) check(file.absolutePath.startsWith(pluginDirPath))
cr.openInputStream(uri.buildUpon().path(path).build()).use { inStream -> cr.openInputStream(uri.buildUpon().path(path).build()).use { inStream ->
file.outputStream().use { outStream -> inStream.copyTo(outStream) } file.outputStream().use { outStream -> inStream.copyTo(outStream) }
} }
......
...@@ -33,5 +33,7 @@ abstract class ResolvedPlugin(protected val resolveInfo: ResolveInfo) : Plugin() ...@@ -33,5 +33,7 @@ abstract class ResolvedPlugin(protected val resolveInfo: ResolveInfo) : Plugin()
override val icon: Drawable by lazy { resolveInfo.loadIcon(app.packageManager) } override val icon: Drawable by lazy { resolveInfo.loadIcon(app.packageManager) }
override val defaultConfig: String by lazy { metaData.getString(PluginContract.METADATA_KEY_DEFAULT_CONFIG) } override val defaultConfig: String by lazy { metaData.getString(PluginContract.METADATA_KEY_DEFAULT_CONFIG) }
override val packageName: String get() = resolveInfo.resolvePackageName override val packageName: String get() = resolveInfo.resolvePackageName
override val trusted by lazy { app.info.signatures.any(PluginManager.trustedSignatures::contains) } override val trusted by lazy {
app.getPackageInfo(packageName).signatures.any(PluginManager.trustedSignatures::contains)
}
} }
...@@ -101,8 +101,8 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() { ...@@ -101,8 +101,8 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
private var clickedIndex = -1 private var clickedIndex = -1
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val activity = activity val activity = requireActivity()
val dialog = BottomSheetDialog(activity!!, theme) val dialog = BottomSheetDialog(activity, theme)
val recycler = RecyclerView(activity) val recycler = RecyclerView(activity)
val padding = resources.getDimensionPixelOffset(R.dimen.bottom_sheet_padding) val padding = resources.getDimensionPixelOffset(R.dimen.bottom_sheet_padding)
recycler.setPadding(0, padding, 0, padding) recycler.setPadding(0, padding, 0, padding)
......
...@@ -52,7 +52,7 @@ object DataStore { ...@@ -52,7 +52,7 @@ object DataStore {
/** /**
* Setter is defined in MainActivity.onPreferenceDataStoreChanged. * Setter is defined in MainActivity.onPreferenceDataStoreChanged.
*/ */
val directBootAware: Boolean get() = BootReceiver.enabled && (publicStore.getBoolean(Key.directBootAware) ?: false) val directBootAware: Boolean get() = BootReceiver.enabled && publicStore.getBoolean(Key.directBootAware) == true
var serviceMode: String var serviceMode: String
get() = publicStore.getString(Key.serviceMode) ?: Key.modeVpn get() = publicStore.getString(Key.serviceMode) ?: Key.modeVpn
set(value) = publicStore.putString(Key.serviceMode, value) set(value) = publicStore.putString(Key.serviceMode, value)
......
...@@ -28,11 +28,7 @@ import android.util.AttributeSet ...@@ -28,11 +28,7 @@ import android.util.AttributeSet
class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPreference(context, attrs) { class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPreference(context, attrs) {
var entryIcons: Array<Drawable?>? = null var entryIcons: Array<Drawable?>? = null
val selectedEntry: Int get() = entryValues.indexOf(value) val selectedEntry: Int get() = entryValues.indexOf(value)
val entryIcon: Drawable? get() = try { val entryIcon: Drawable? get() = entryIcons?.getOrNull(selectedEntry)
entryIcons?.get(selectedEntry)
} catch (_: ArrayIndexOutOfBoundsException) {
null
}
// fun setEntryIcons(@ArrayRes entryIconsResId: Int) { // fun setEntryIcons(@ArrayRes entryIconsResId: Int) {
// val array = getContext().getResources().obtainTypedArray(entryIconsResId) // val array = getContext().getResources().obtainTypedArray(entryIconsResId)
// entryIcons = Array(array.length(), { i -> array.getDrawable(i) }) // entryIcons = Array(array.length(), { i -> array.getDrawable(i) })
...@@ -49,7 +45,7 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr ...@@ -49,7 +45,7 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr
} }
init { init {
super.setOnPreferenceChangeListener({ preference, newValue -> super.setOnPreferenceChangeListener { preference, newValue ->
val listener = listener val listener = listener
if (listener == null || listener.onPreferenceChange(preference, newValue)) { if (listener == null || listener.onPreferenceChange(preference, newValue)) {
value = newValue.toString() value = newValue.toString()
...@@ -57,7 +53,7 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr ...@@ -57,7 +53,7 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr
if (entryIcons != null) icon = entryIcon if (entryIcons != null) icon = entryIcon
true true
} else false } else false
}) }
// val a = context.obtainStyledAttributes(attrs, R.styleable.IconListPreference) // val a = context.obtainStyledAttributes(attrs, R.styleable.IconListPreference)
// val entryIconsResId: Int = a.getResourceId(R.styleable.IconListPreference_entryIcons, -1) // val entryIconsResId: Int = a.getResourceId(R.styleable.IconListPreference_entryIcons, -1)
// if (entryIconsResId != -1) entryIcons = entryIconsResId // if (entryIconsResId != -1) entryIcons = entryIconsResId
......
...@@ -22,17 +22,20 @@ package com.github.shadowsocks.preference ...@@ -22,17 +22,20 @@ package com.github.shadowsocks.preference
import android.support.v7.preference.PreferenceDataStore import android.support.v7.preference.PreferenceDataStore
import com.github.shadowsocks.database.KeyValuePair import com.github.shadowsocks.database.KeyValuePair
import com.github.shadowsocks.database.deleteByIdSafe
import com.github.shadowsocks.database.queryByIdSafe
import com.github.shadowsocks.database.replaceSafe
import com.j256.ormlite.dao.Dao import com.j256.ormlite.dao.Dao
import java.util.HashSet import java.util.HashSet
@Suppress("MemberVisibilityCanPrivate", "unused") @Suppress("MemberVisibilityCanPrivate", "unused")
open class OrmLitePreferenceDataStore(private val kvPairDao: Dao<KeyValuePair, String?>) : PreferenceDataStore() { open class OrmLitePreferenceDataStore(private val kvPairDao: Dao<KeyValuePair, String?>) : PreferenceDataStore() {
fun getBoolean(key: String?) = kvPairDao.queryForId(key)?.boolean fun getBoolean(key: String?) = kvPairDao.queryByIdSafe(key)?.boolean
fun getFloat(key: String?) = kvPairDao.queryForId(key)?.float fun getFloat(key: String?) = kvPairDao.queryByIdSafe(key)?.float
fun getInt(key: String?) = kvPairDao.queryForId(key)?.int fun getInt(key: String?) = kvPairDao.queryByIdSafe(key)?.int
fun getLong(key: String?) = kvPairDao.queryForId(key)?.long fun getLong(key: String?) = kvPairDao.queryByIdSafe(key)?.long
fun getString(key: String?) = kvPairDao.queryForId(key)?.string fun getString(key: String?) = kvPairDao.queryByIdSafe(key)?.string
fun getStringSet(key: String?) = kvPairDao.queryForId(key)?.stringSet fun getStringSet(key: String?) = kvPairDao.queryByIdSafe(key)?.stringSet
override fun getBoolean(key: String?, defValue: Boolean) = getBoolean(key) ?: defValue override fun getBoolean(key: String?, defValue: Boolean) = getBoolean(key) ?: defValue
override fun getFloat(key: String?, defValue: Float) = getFloat(key) ?: defValue override fun getFloat(key: String?, defValue: Float) = getFloat(key) ?: defValue
...@@ -46,32 +49,32 @@ open class OrmLitePreferenceDataStore(private val kvPairDao: Dao<KeyValuePair, S ...@@ -46,32 +49,32 @@ open class OrmLitePreferenceDataStore(private val kvPairDao: Dao<KeyValuePair, S
fun putInt(key: String?, value: Int?) = if (value == null) remove(key) else putInt(key, value) fun putInt(key: String?, value: Int?) = if (value == null) remove(key) else putInt(key, value)
fun putLong(key: String?, value: Long?) = if (value == null) remove(key) else putLong(key, value) fun putLong(key: String?, value: Long?) = if (value == null) remove(key) else putLong(key, value)
override fun putBoolean(key: String?, value: Boolean) { override fun putBoolean(key: String?, value: Boolean) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value)) kvPairDao.replaceSafe(KeyValuePair(key).put(value))
fireChangeListener(key) fireChangeListener(key)
} }
override fun putFloat(key: String?, value: Float) { override fun putFloat(key: String?, value: Float) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value)) kvPairDao.replaceSafe(KeyValuePair(key).put(value))
fireChangeListener(key) fireChangeListener(key)
} }
override fun putInt(key: String?, value: Int) { override fun putInt(key: String?, value: Int) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value)) kvPairDao.replaceSafe(KeyValuePair(key).put(value))
fireChangeListener(key) fireChangeListener(key)
} }
override fun putLong(key: String?, value: Long) { override fun putLong(key: String?, value: Long) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value)) kvPairDao.replaceSafe(KeyValuePair(key).put(value))
fireChangeListener(key) fireChangeListener(key)
} }
override fun putString(key: String?, value: String?) = if (value == null) remove(key) else { override fun putString(key: String?, value: String?) = if (value == null) remove(key) else {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value)) kvPairDao.replaceSafe(KeyValuePair(key).put(value))
fireChangeListener(key) fireChangeListener(key)
} }
override fun putStringSet(key: String?, values: MutableSet<String>?) = if (values == null) remove(key) else { override fun putStringSet(key: String?, values: MutableSet<String>?) = if (values == null) remove(key) else {
kvPairDao.createOrUpdate(KeyValuePair(key).put(values)) kvPairDao.replaceSafe(KeyValuePair(key).put(values))
fireChangeListener(key) fireChangeListener(key)
} }
fun remove(key: String?) { fun remove(key: String?) {
kvPairDao.deleteById(key) kvPairDao.deleteByIdSafe(key)
fireChangeListener(key) fireChangeListener(key)
} }
......
...@@ -40,8 +40,9 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat ...@@ -40,8 +40,9 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat
super.onPrepareDialogBuilder(builder) super.onPrepareDialogBuilder(builder)
val intent = PluginManager.buildIntent(arguments!!.getString(PLUGIN_ID_FRAGMENT_TAG), val intent = PluginManager.buildIntent(arguments!!.getString(PLUGIN_ID_FRAGMENT_TAG),
PluginContract.ACTION_HELP) PluginContract.ACTION_HELP)
if (intent.resolveActivity(activity!!.packageManager) != null) builder.setNeutralButton("?", { _, _ -> val activity = requireActivity()
activity!!.startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS, editText.text.toString()), if (intent.resolveActivity(activity.packageManager) != null) builder.setNeutralButton("?", { _, _ ->
activity.startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS, editText.text.toString()),
ProfileConfigActivity.REQUEST_CODE_PLUGIN_HELP) ProfileConfigActivity.REQUEST_CODE_PLUGIN_HELP)
}) })
} }
......
...@@ -85,12 +85,12 @@ class ConfigActivity : AppCompatActivity() { ...@@ -85,12 +85,12 @@ class ConfigActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
try { val intent = intent
taskerOption = Settings.fromIntent(intent!!) if (intent == null) {
} catch (_: Exception) {
finish() finish()
return return
} }
taskerOption = Settings.fromIntent(intent)
setContentView(R.layout.layout_tasker) setContentView(R.layout.layout_tasker)
val toolbar = findViewById<Toolbar>(R.id.toolbar) val toolbar = findViewById<Toolbar>(R.id.toolbar)
......
...@@ -44,8 +44,8 @@ class Settings(bundle: Bundle?) { ...@@ -44,8 +44,8 @@ class Settings(bundle: Bundle?) {
if (profileId >= 0) bundle.putInt(KEY_PROFILE_ID, profileId) if (profileId >= 0) bundle.putInt(KEY_PROFILE_ID, profileId)
val profile = ProfileManager.getProfile(profileId) val profile = ProfileManager.getProfile(profileId)
return Intent().putExtra(ApiIntent.EXTRA_BUNDLE, bundle).putExtra(ApiIntent.EXTRA_STRING_BLURB, return Intent().putExtra(ApiIntent.EXTRA_BUNDLE, bundle).putExtra(ApiIntent.EXTRA_STRING_BLURB,
if (profile != null) if (profile != null) context.getString(if (switchOn) R.string.start_service else R.string.stop_service,
context.getString(if (switchOn) R.string.start_service else R.string.stop_service, profile.formattedName) profile.formattedName)
else context.getString(if (switchOn) R.string.start_service_default else R.string.stop)) else context.getString(if (switchOn) R.string.start_service_default else R.string.stop))
} }
} }
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
package com.github.shadowsocks.utils package com.github.shadowsocks.utils
import java.util.ArrayList import java.util.*
import java.util.Arrays
import java.util.StringTokenizer
/** /**
* Commandline objects help handling command lines specifying processes to * Commandline objects help handling command lines specifying processes to
...@@ -86,9 +84,7 @@ object Commandline { ...@@ -86,9 +84,7 @@ object Commandline {
* @return empty string for null or no command, else every argument split * @return empty string for null or no command, else every argument split
* by spaces and quoted by quoting rules. * by spaces and quoted by quoting rules.
*/ */
fun toString(args: Array<String>): String { fun toString(args: Array<String>) = toString(args.asIterable()) // thanks to Java, arrays aren't iterable
return toString(Arrays.asList(*args)) // thanks to Java, arrays aren't iterable
}
/** /**
* Crack a command line. * Crack a command line.
......
...@@ -7,7 +7,7 @@ import com.github.shadowsocks.database.Profile ...@@ -7,7 +7,7 @@ import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.IOException
import java.io.ObjectInputStream import java.io.ObjectInputStream
import java.io.ObjectOutputStream import java.io.ObjectOutputStream
...@@ -17,7 +17,7 @@ object DirectBoot { ...@@ -17,7 +17,7 @@ object DirectBoot {
fun getDeviceProfile(): Profile? = try { fun getDeviceProfile(): Profile? = try {
ObjectInputStream(file.inputStream()).use { it.readObject() as Profile } ObjectInputStream(file.inputStream()).use { it.readObject() as Profile }
} catch (_: FileNotFoundException) { null } } catch (_: IOException) { null }
fun clean() { fun clean() {
file.delete() file.delete()
......
...@@ -52,4 +52,5 @@ object TcpFastOpen { ...@@ -52,4 +52,5 @@ object TcpFastOpen {
"else", "else",
" echo Failed.", " echo Failed.",
"fi"), null, true)?.joinToString("\n") "fi"), null, true)?.joinToString("\n")
fun enabledAsync(value: Boolean) = thread { enabled(value) }.join(1000)
} }
...@@ -28,8 +28,8 @@ fun String.parseNumericAddress(): InetAddress? { ...@@ -28,8 +28,8 @@ fun String.parseNumericAddress(): InetAddress? {
} }
fun parsePort(str: String?, default: Int, min: Int = 1025): Int { fun parsePort(str: String?, default: Int, min: Int = 1025): Int {
val x = str?.toIntOrNull() ?: default val value = str?.toIntOrNull() ?: default
return if (x < min || x > 65535) default else x return if (value < min || value > 65535) default else value
} }
fun broadcastReceiver(callback: (Context, Intent) -> Unit): BroadcastReceiver = object : BroadcastReceiver() { fun broadcastReceiver(callback: (Context, Intent) -> Unit): BroadcastReceiver = object : BroadcastReceiver() {
...@@ -72,6 +72,6 @@ private class SortedListIterable<out T>(private val list: SortedList<T>) : Itera ...@@ -72,6 +72,6 @@ private class SortedListIterable<out T>(private val list: SortedList<T>) : Itera
private class SortedListIterator<out T>(private val list: SortedList<T>) : Iterator<T> { private class SortedListIterator<out T>(private val list: SortedList<T>) : Iterator<T> {
private var count = 0 private var count = 0
override fun hasNext() = count < list.size() override fun hasNext() = count < list.size()
override fun next(): T = list[count++] override fun next(): T = if (hasNext()) list[count++] else throw NoSuchElementException()
} }
fun <T> SortedList<T>.asIterable(): Iterable<T> = SortedListIterable(this) fun <T> SortedList<T>.asIterable(): Iterable<T> = SortedListIterable(this)
...@@ -29,7 +29,6 @@ import android.support.graphics.drawable.AnimatedVectorDrawableCompat ...@@ -29,7 +29,6 @@ import android.support.graphics.drawable.AnimatedVectorDrawableCompat
import android.support.v7.widget.TooltipCompat import android.support.v7.widget.TooltipCompat
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.R import com.github.shadowsocks.R
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import java.util.* import java.util.*
...@@ -84,9 +83,7 @@ class ServiceButton @JvmOverloads constructor(context: Context, attrs: Attribute ...@@ -84,9 +83,7 @@ class ServiceButton @JvmOverloads constructor(context: Context, attrs: Attribute
TooltipCompat.setTooltipText(this, context.getString(R.string.connect)) TooltipCompat.setTooltipText(this, context.getString(R.string.connect))
} }
refreshDrawableState() refreshDrawableState()
isEnabled = false isEnabled = state == BaseService.CONNECTED || state == BaseService.STOPPED
if (state == BaseService.CONNECTED || state == BaseService.STOPPED) app.handler.postDelayed(
{ isEnabled = state == BaseService.CONNECTED || state == BaseService.STOPPED }, 1000)
} }
private fun counters(a: AnimatedVectorDrawableCompat, b: AnimatedVectorDrawableCompat): Boolean = private fun counters(a: AnimatedVectorDrawableCompat, b: AnimatedVectorDrawableCompat): Boolean =
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#f5f5f5"
android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0Z" />
<path
android:fillColor="#546e7a"
android:pathData="M24,21.8 C25.7673,21.8,27.2,23.2327,27.2,25 C27.2,26.7673,25.7673,28.2,24,28.2
C22.2327,28.2,20.8,26.7673,20.8,25 C20.8,23.2327,22.2327,21.8,24,21.8 Z" />
<path
android:fillColor="#546e7a"
android:pathData="M21,15 L19.17,17 L16,17 A2,2,0,0,0,14,19 L14,31 A2,2,0,0,0,16,33 L32,33
A2,2,0,0,0,34,31 L34,19 A2,2,0,0,0,32,17 L28.83,17 L27,15 Z M24,30
A5,5,0,1,1,29,25 A5,5,0,0,1,24,30 Z" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
...@@ -8,8 +9,15 @@ ...@@ -8,8 +9,15 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:labelFor="@+id/content" android:labelFor="@+id/content"
android:entries="@array/acl_rule_templates"/> android:entries="@array/acl_rule_templates"/>
<EditText android:id="@+id/content" <android.support.design.widget.TextInputLayout
android:layout_width="match_parent" android:id="@+id/content_layout"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:inputType="textNoSuggestions|textMultiLine"/> android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions|textMultiLine"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout> </LinearLayout>
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="fill_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:duplicateParentState="false"> android:duplicateParentState="false">
<include layout="@layout/toolbar_light_dark"/> <include layout="@layout/toolbar_light_dark"/>
...@@ -41,28 +41,36 @@ ...@@ -41,28 +41,36 @@
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="18sp"/> android:textSize="18sp"/>
</LinearLayout> </LinearLayout>
<FrameLayout android:layout_width="fill_parent" <android.support.design.widget.CoordinatorLayout
android:layout_height="0dp" android:id="@+id/snackbar"
android:layout_weight="1"> android:background="@color/material_primary_700"
<ProgressBar android:id="@+id/loading" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="0dp"
android:layout_height="wrap_content" android:layout_weight="1">
android:layout_gravity="center" /> <FrameLayout android:layout_width="match_parent"
<android.support.v7.widget.RecyclerView android:layout_height="match_parent"
android:layout_width="fill_parent" android:background="?android:attr/windowBackground"
android:layout_height="fill_parent" app:layout_behavior="com.github.shadowsocks.widget.ShrinkUpwardBehavior">
android:id="@+id/list" <ProgressBar android:id="@+id/loading"
tools:listitem="@layout/layout_apps_item"/> android:layout_width="wrap_content"
<com.futuremind.recyclerviewfastscroll.FastScroller android:layout_height="wrap_content"
android:id="@+id/fastscroller" android:layout_gravity="center" />
android:orientation="vertical" <android.support.v7.widget.RecyclerView
android:layout_width="wrap_content" android:layout_width="fill_parent"
android:layout_height="match_parent" android:layout_height="fill_parent"
android:layout_gravity="end" android:id="@+id/list"
android:layout_marginTop="8dp" tools:listitem="@layout/layout_apps_item"/>
android:layout_marginBottom="8dp" <com.futuremind.recyclerviewfastscroll.FastScroller
app:fastscroll__handleColor="@color/material_primary_500" android:id="@+id/fastscroller"
app:fastscroll__bubbleColor="@color/material_primary_500" android:orientation="vertical"
app:fastscroll__bubbleTextAppearance="@style/StyledScrollerTextAppearance"/> android:layout_width="wrap_content"
</FrameLayout> android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:fastscroll__handleColor="@color/material_primary_500"
app:fastscroll__bubbleColor="@color/material_primary_500"
app:fastscroll__bubbleTextAppearance="@style/StyledScrollerTextAppearance"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar_light_dark" /> <include layout="@layout/toolbar_light_dark" />
<me.dm7.barcodescanner.zxing.ZXingScannerView android:id="@+id/scanner" <fragment
android:layout_width="match_parent" android:id="@+id/barcode"
android:layout_height="0dp" android:name="com.google.android.gms.samples.vision.barcodereader.BarcodeCapture"
android:layout_weight="1"/> android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:gvb_auto_focus="true"
app:gvb_code_format="qr_code"/>
</LinearLayout> </LinearLayout>
<menu xmlns:tools="http://schemas.android.com/tools" <menu
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_apply_all" <item android:id="@+id/action_apply_all"
android:title="@string/action_apply_all" android:title="@string/action_apply_all"
android:alphabeticShortcut="a" android:alphabeticShortcut="a"
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_import"
android:title="@string/action_import_file"
android:icon="@drawable/ic_image_photo"
android:alphabeticShortcut="p"
android:numericShortcut="1"
app:showAsAction="always"/>
</menu>
\ No newline at end of file
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
<string name="action_apply_all">Apply Settings to All Profiles</string> <string name="action_apply_all">Apply Settings to All Profiles</string>
<string name="action_export">Export to Clipboard</string> <string name="action_export">Export to Clipboard</string>
<string name="action_import">Import from Clipboard</string> <string name="action_import">Import from Clipboard</string>
<string name="action_import_file">Import from file…</string>
<string name="action_export_msg">Successfully export!</string> <string name="action_export_msg">Successfully export!</string>
<string name="action_export_err">Failed to export.</string> <string name="action_export_err">Failed to export.</string>
<string name="action_import_msg">Successfully import!</string> <string name="action_import_msg">Successfully import!</string>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Translucent" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
<style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance"> <style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance">
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
......
...@@ -8,4 +8,12 @@ ...@@ -8,4 +8,12 @@
android:targetPackage="com.github.shadowsocks" android:targetPackage="com.github.shadowsocks"
android:targetClass="com.github.shadowsocks.QuickToggleShortcut" /> android:targetClass="com.github.shadowsocks.QuickToggleShortcut" />
</shortcut> </shortcut>
<shortcut android:shortcutId="scan"
android:icon="@drawable/ic_qu_camera_launcher"
android:shortcutShortLabel="@string/add_profile_methods_scan_qr_code"
android:shortcutLongLabel="@string/add_profile_methods_scan_qr_code">
<intent android:action="android.intent.action.MAIN"
android:targetPackage="com.github.shadowsocks"
android:targetClass="com.github.shadowsocks.ScannerActivity" />
</shortcut>
</shortcuts> </shortcuts>
...@@ -61,7 +61,7 @@ abstract class NativePluginProvider : ContentProvider() { ...@@ -61,7 +61,7 @@ abstract class NativePluginProvider : ContentProvider() {
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?,
sortOrder: String?): Cursor { sortOrder: String?): Cursor {
assert(selection == null && selectionArgs == null && sortOrder == null) check(selection == null && selectionArgs == null && sortOrder == null)
val result = MatrixCursor(projection) val result = MatrixCursor(projection)
populateFiles(PathProvider(uri, result)) populateFiles(PathProvider(uri, result))
return result return result
...@@ -70,8 +70,8 @@ abstract class NativePluginProvider : ContentProvider() { ...@@ -70,8 +70,8 @@ abstract class NativePluginProvider : ContentProvider() {
/** /**
* Returns executable entry absolute path. This is used if plugin is sharing UID with the host. * Returns executable entry absolute path. This is used if plugin is sharing UID with the host.
* *
* Default behavior is throwing UnsupportedOperationException. If you don't wish to use this feature, use the default * Default behavior is throwing UnsupportedOperationException. If you don't wish to use this feature, use the
* behavior. * default behavior.
* *
* @return Absolute path for executable entry. * @return Absolute path for executable entry.
*/ */
...@@ -79,7 +79,7 @@ abstract class NativePluginProvider : ContentProvider() { ...@@ -79,7 +79,7 @@ abstract class NativePluginProvider : ContentProvider() {
abstract fun openFile(uri: Uri?): ParcelFileDescriptor abstract fun openFile(uri: Uri?): ParcelFileDescriptor
override fun openFile(uri: Uri?, mode: String?): ParcelFileDescriptor { override fun openFile(uri: Uri?, mode: String?): ParcelFileDescriptor {
assert(mode == "r") check(mode == "r")
return openFile(uri) return openFile(uri)
} }
......
...@@ -29,13 +29,11 @@ import android.widget.Toast ...@@ -29,13 +29,11 @@ import android.widget.Toast
* Activity that's capable of getting EXTRA_OPTIONS input. * Activity that's capable of getting EXTRA_OPTIONS input.
*/ */
abstract class OptionsCapableActivity : AppCompatActivity() { abstract class OptionsCapableActivity : AppCompatActivity() {
protected fun pluginOptions(intent: Intent = this.intent): PluginOptions { protected fun pluginOptions(intent: Intent = this.intent) = try {
return try { PluginOptions(intent.getStringExtra(PluginContract.EXTRA_OPTIONS))
PluginOptions(intent.getStringExtra(PluginContract.EXTRA_OPTIONS)) } catch (exc: IllegalArgumentException) {
} catch (exc: IllegalArgumentException) { Toast.makeText(this, exc.message, Toast.LENGTH_SHORT).show()
Toast.makeText(this, exc.message, Toast.LENGTH_SHORT).show() PluginOptions()
PluginOptions()
}
} }
/** /**
......
...@@ -4,4 +4,4 @@ release=$1 ...@@ -4,4 +4,4 @@ release=$1
cp mobile/build/outputs/apk/release/mobile-armeabi-v7a-release.apk shadowsocks-armeabi-v7a-${release}.apk cp mobile/build/outputs/apk/release/mobile-armeabi-v7a-release.apk shadowsocks-armeabi-v7a-${release}.apk
cp mobile/build/outputs/apk/release/mobile-arm64-v8a-release.apk shadowsocks-arm64-v8a-${release}.apk cp mobile/build/outputs/apk/release/mobile-arm64-v8a-release.apk shadowsocks-arm64-v8a-${release}.apk
cp mobile/build/outputs/apk/release/mobile-x86-release.apk shadowsocks-x86-${release}.apk cp mobile/build/outputs/apk/release/mobile-x86-release.apk shadowsocks-x86-${release}.apk
cp mobile/build/outputs/apk/release/mobile-universal-release.apk shadowsocks-universal-${release}.apk cp mobile/build/outputs/apk/release/mobile-universal-release.apk shadowsocks--universal-${release}.apk
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment