Commit 0c335293 authored by Mygod's avatar Mygod

Merge branch 'master' into split-abi

parents cd1f94f4 0d02a39b
......@@ -3,9 +3,8 @@
Cannot connect to server:
1. Stop battery saver if it's active;
2. If an upgrade breaks anything, do a manual reset first by pressing Reset at the end of the list;
3. Check your config;
4. Wipe app data.
2. Check your config;
3. Wipe app data.
Crash: [Submit an issue](https://github.com/shadowsocks/shadowsocks-android/issues/new) with logcat attached, or submit a crash report to Google Play. Then, try wiping app data.
......
### Решение проблем
Не получается подключиться к серверу:
1. Выключите режим энергосбережения, если он активен;
2. Проверьте настройки;
3. Сотрите данные приложения.
Не работает: [Добавьте отчет](https://github.com/shadowsocks/shadowsocks-android/issues/new) прикрепив лог (logcat), или отправьте отзыв в Google Play. Затем попробуйте стереть данные приложения.
### Как добавить виджет и/или переключать профиль на основании состояния сети?
Использйте интеграцию с [Tasker](http://tasker.dinglisch.net/).
### Как добавить QR код из локальной галереи?
Отсканируйте его при помощи стороннего сканера, например [QuickMark Barcode Scanner](https://play.google.com/store/apps/details?id=tw.com.quickmark) и нажмите на `ss` ссылку.
### Почему режим NAT более не поддерживается?
1. Требуются ROOT права;
2. Нет поддержки IPv6;
3. Нет поддержки UDP relay.
### Как убрать восклицательный знак когда используется режим VPN?
Восклицательный знак на значке Wi-Fi/Сотовой связи появляется, потому что система не может подключиться к portal-серверу (по-умолчанию к `clients3.google.com`) без VPN подключения. Чтобы убрать его, следуйте инструкциям в [этом топике](https://www.noisyfox.cn/45.html). (на упрощенном китайском)
### Почему мой ROM не поддерживается?
1. Некоторые ROM используют неправильную реализацию службы VPN, особенно IPv6;
2. Некоторые ROM используют агрессивную (или так называемую неправильную) фоновую службу с ошибочной политикой остановки;
3. Если вы используете фреймворк Xposed и/или приложения для энергосбережения, вероятно наше приложение не будет нормально работать с ними.
* Иправления для MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
* Иправления для Huawei: [#1091 (комментарий)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836)
* Вызванные из-за Xposed: [#1414](https://github.com/shadowsocks/shadowsocks-android/issues/1414)
* Samsung и/или Brevent: [#1410](https://github.com/shadowsocks/shadowsocks-android/issues/1410)
* Не устанавливайте это приложение на SD карту, из-за проблем с разрешениями: [#1124 (комментарий)](https://github.com/shadowsocks/shadowsocks-android/issues/1124#issuecomment-307556453)
### Как приостановить службу Shadowsocks?
* Для Android 7.0+: Используйте переключатель в быстрых настройках;
* Используйте интеграцию с Tasker;
* Добавьте профиль c выбранными приложениями, которые будут работать через Shadowsocks прокси, выключив обходной режим.
### Почему Shadowsocks потребляет так много энергии на Android 5.0+?
Так как Shadowsocks работает со всем траффиком устройства, заряд батареи используемый другими приложениями также считается за тот, что использует Shadowsocks. Таким образом использование батареи Shadowsocks'ом равен сумме всей активности устройства в сети. Shadowsocks сам по себе в общем-то является приложением связанного процесса ввода/вывода на современных Android устройствах, которое, ожидаемо, не потребляет значительного количества энергии.
Так что если вы заметите значительное увеличение потребляемой энергии после того, как вы использовали Shadowsocks, это скорее всего вызванно другими приложениями. Например, сервисы Google Play могут потреблять больше энергии после того, как подключатся к Google, и т.д.
Больше информации: https://kb.adguard.com/en/android/solving-problems/battery
### Оно прекрасно работает при Wi-Fi но не может подключиться через сотовую связь?
Разрешите этому приложению передачу данных в фоновом режиме в настройках приложения.
Если у вас оперератор Yota, то измените точку доступа APN с `yota.ru` на `client.yota.ru`
### Почему требуется разрешение камере на устройствах младше Android 6.0?
Чтобы сканировать QR код через встроенный QR сканер.
Кстати, обновите уже свою версию Android.
### Как использовать режим Transproxy (прозрачный прокси)?
1. Установите [AFWall+](https://github.com/ukanth/afwall);
2. Настройте пользовательский скрипт:
```sh
IP6TABLES=/system/bin/ip6tables
IPTABLES=/system/bin/iptables
ULIMIT=/system/bin/ulimit
SHADOWSOCKS_UID=`dumpsys package com.github.shadowsocks | grep userId | cut -d= -f2 - | cut -d' ' -f1 -`
PORT_DNS=5450
PORT_TRANSPROXY=8200
$ULIMIT -n 4096
$IP6TABLES -F
$IP6TABLES -A INPUT -j DROP
$IP6TABLES -A OUTPUT -j DROP
$IPTABLES -t nat -F OUTPUT
$IPTABLES -t nat -A OUTPUT -o lo -j RETURN
$IPTABLES -t nat -A OUTPUT -d 127.0.0.1 -j RETURN
$IPTABLES -t nat -A OUTPUT -m owner --uid-owner $SHADOWSOCKS_UID -j RETURN
$IPTABLES -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 127.0.0.1:$PORT_DNS
$IPTABLES -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:$PORT_DNS
$IPTABLES -t nat -A OUTPUT -p tcp -j DNAT --to-destination 127.0.0.1:$PORT_TRANSPROXY
$IPTABLES -t nat -A OUTPUT -p udp -j DNAT --to-destination 127.0.0.1:$PORT_TRANSPROXY
```
3. Настройте пользовательский скрипт отключения:
```sh
IP6TABLES=/system/bin/ip6tables
IPTABLES=/system/bin/iptables
$IPTABLES -t nat -F OUTPUT
$IP6TABLES -F
```
4. Убедитесь, что траффик для Shadowsocks разрешен;
5. Запустите службу прозрачного прокси (transproxy) в Shadowsocks и включите брандмауэр.
......@@ -5,34 +5,29 @@ jdk:
env:
global:
- NDK_VERSION=r16
- NDK_CCACHE=ccache
- GOROOT_BOOTSTRAP=$GOROOT
- ANDROID_NDK_HOME=$HOME/.android/android-ndk-${NDK_VERSION}
- PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle
android:
components:
- tools
- android-27
- build-tools-26.0.2
- build-tools-27.0.0
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
install:
- >
if [ ! -d "$ANDROID_NDK_HOME" ]; then
mkdir -p $ANDROID_NDK_HOME;
pushd $HOME/.android;
export ARCH=`uname -m`;
wget -q http://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux-${ARCH}.zip;
unzip -q android-ndk-${NDK_VERSION}-linux-${ARCH}.zip;
popd;
fi
- >
- pushd $ANDROID_HOME
- rm -rf tools
- wget -q https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip -O tools.zip
- unzip -q tools.zip
- popd
- touch $HOME/.android/repositories.cfg
- yes | sdkmanager
"build-tools;27.0.3"
ndk-bundle
"platforms;android-27"
>/dev/null
script:
- ./gradlew assembleDebug
- ./gradlew assembleDebug check
## Shadowsocks for 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)
[![Releases](https://img.shields.io/github/downloads/shadowsocks/shadowsocks-android/total.svg)](https://github.com/shadowsocks/shadowsocks-android/releases)
[![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 href="https://play.google.com/store/apps/details?id=com.github.shadowsocks"><img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" height="48"></a>
......
......@@ -2,12 +2,13 @@
buildscript {
ext {
kotlinVersion = '1.2.0'
minSdkVersion = 19
kotlinVersion = '1.2.20'
minSdkVersion = 21
sdkVersion = 27
buildToolsVersion = '27.0.3'
supportLibraryVersion = '27.0.2'
takisoftFixVersion = '27.0.2.0'
playServicesVersion = '11.6.2'
playServicesVersion = '11.8.0'
junitVersion = '4.12'
androidTestVersion = '1.0.1'
androidEspressoVersion = '3.0.1'
......
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.library'
android {
buildToolsVersion rootProject.buildToolsVersion
compileSdkVersion rootProject.sdkVersion
defaultConfig {
......@@ -33,18 +36,28 @@ android {
}
task goBuild(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
executable "cmd.exe"
args "/c", "src/overture/make.bat " + minSdkVersion
} else {
executable "sh"
args "-c", "src/overture/make.bash " + minSdkVersion
}
}
task goClean(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
executable "cmd.exe"
args "/c", "src/overture/clean.bat"
} else {
executable "sh"
args "-c", "src/overture/clean.bash"
}
}
tasks.whenTaskAdded { task ->
if (task.name == 'generateJsonModelDebug' ||
task.name == 'generateJsonModelRelease') {
if ((task.name == 'generateJsonModelDebug' ||
task.name == 'generateJsonModelRelease')) {
task.dependsOn(goBuild)
}
}
......
......@@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.github.shadowsockscorelibraries.test", appContext.getPackageName());
assertEquals("com.github.shadowsocks.core.test", appContext.getPackageName());
}
}
......@@ -39,6 +39,8 @@
package com.github.shadowsocks;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.system.ErrnoException;
public class JniHelper {
......@@ -47,15 +49,14 @@ public class JniHelper {
}
@Deprecated // Use Process.destroy() since API 24
public static void sigtermCompat(Process process) throws Exception {
public static void sigtermCompat(@NonNull Process process) throws Exception {
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
int errno = sigterm(process);
if (errno != 0) throw Build.VERSION.SDK_INT >= 21
? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno);
if (errno != 0) throw new ErrnoException("kill", errno);
}
@Deprecated // only implemented for before API 24
public static boolean waitForCompat(Process process, long millis) throws Exception {
public static boolean waitForCompat(@NonNull Process process, long millis) throws Exception {
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
final Object mutex = getExitValueMutex(process);
synchronized (mutex) {
......@@ -68,6 +69,8 @@ public class JniHelper {
private static native int sigterm(Process process);
private static native Integer getExitValue(Process process);
private static native Object getExitValueMutex(Process process);
public static native int sendFd(int fd, String path);
public static native int sendFd(int fd, @NonNull String path);
public static native void close(int fd);
@Nullable
public static native byte[] parseNumericAddress(@NonNull String str);
}
......@@ -62,7 +62,7 @@ LOCAL_CFLAGS += -I$(LOCAL_PATH)/libsodium/src/libsodium/include \
-I$(LOCAL_PATH)/include/sodium \
-I$(LOCAL_PATH)/libsodium/src/libsodium/include/sodium \
-DPACKAGE_NAME=\"libsodium\" -DPACKAGE_TARNAME=\"libsodium\" \
-DPACKAGE_VERSION=\"1.0.15\" -DPACKAGE_STRING=\"libsodium\ 1.0.15\" \
-DPACKAGE_VERSION=\"1.0.15\" -DPACKAGE_STRING=\"libsodium-1.0.15\" \
-DPACKAGE_BUGREPORT=\"https://github.com/jedisct1/libsodium/issues\" \
-DPACKAGE_URL=\"https://github.com/jedisct1/libsodium\" \
-DPACKAGE=\"libsodium\" -DVERSION=\"1.0.15\" \
......@@ -318,6 +318,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE:= jni-helper
LOCAL_CFLAGS := -std=c++11
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libancillary
LOCAL_SRC_FILES:= jni-helper.cpp
......@@ -450,7 +452,6 @@ LOCAL_CFLAGS += -DHAVE_CONFIG_H
LOCAL_C_INCLUDES := $(LOCAL_PATH)/pcre/dist $(LOCAL_PATH)/pcre
libpcre_src_files := \
pcre_chartables.c \
dist/pcre_byte_order.c \
dist/pcre_compile.c \
dist/pcre_config.c \
......@@ -472,7 +473,7 @@ libpcre_src_files := \
dist/pcre_version.c \
dist/pcre_xclass.c
LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files))
LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files)) $(LOCAL_PATH)/patch/pcre/pcre_chartables.c
include $(BUILD_STATIC_LIBRARY)
......
APP_ABI := armeabi-v7a arm64-v8a x86
APP_PLATFORM := android-21
APP_STL := c++_static
NDK_TOOLCHAIN_VERSION := clang
......@@ -16,8 +16,8 @@
# executable program
#
# Modified by @Mygod, based on:
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-shared-library.mk
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-executable.mk
# https://android.googlesource.com/platform/ndk/+/a355a4e/build/core/build-shared-library.mk
# https://android.googlesource.com/platform/ndk/+/a355a4e/build/core/build-executable.mk
LOCAL_BUILD_SCRIPT := BUILD_EXECUTABLE
LOCAL_MAKEFILE := $(local-makefile)
$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
......
......@@ -4,33 +4,33 @@
#include <android/log.h>
#include <sys/system_properties.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cerrno>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ancillary.h>
using namespace std;
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
#define THROW(env, clazz, msg) do { env->ThrowNew(env->FindClass(clazz), msg); } while (0)
static int sdk_version;
static jclass ProcessImpl;
static jfieldID ProcessImpl_pid, ProcessImpl_exitValue, ProcessImpl_exitValueMutex;
static int sdk_version() {
char version[PROP_VALUE_MAX + 1];
__system_property_get("ro.build.version.sdk", version);
return atoi(version);
}
#pragma clang diagnostic ignored "-Wunused-parameter"
extern "C" {
JNIEXPORT jint JNICALL Java_com_github_shadowsocks_JniHelper_sigkill(JNIEnv *env, jobject thiz, jint pid) {
// Suppress "No such process" errors. We just want the process killed. It's fine if it's already killed.
......@@ -103,6 +103,22 @@ JNIEXPORT jint JNICALL
env->ReleaseStringUTFChars(path, sock_str);
return 0;
}
JNIEXPORT jbyteArray JNICALL
Java_com_github_shadowsocks_JniHelper_parseNumericAddress(JNIEnv *env, jobject thiz, jstring str) {
const char *src = env->GetStringUTFChars(str, 0);
jbyte dst[max(sizeof(in_addr), sizeof(in6_addr))];
jbyteArray arr = nullptr;
if (inet_pton(AF_INET, src, dst) == 1) {
arr = env->NewByteArray(sizeof(in_addr));
env->SetByteArrayRegion(arr, 0, sizeof(in_addr), dst);
} else if (inet_pton(AF_INET6, src, dst) == 1) {
arr = env->NewByteArray(sizeof(in6_addr));
env->SetByteArrayRegion(arr, 0, sizeof(in6_addr), dst);
}
env->ReleaseStringUTFChars(str, src);
return arr;
}
}
/*
......@@ -114,6 +130,7 @@ typedef union {
void* venv;
} UnionJNIEnvToVoid;
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
......@@ -126,24 +143,27 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
}
env = uenv.env;
if (sdk_version() < 24) {
if (!(ProcessImpl = env->FindClass("java/lang/ProcessManager$ProcessImpl"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl not found");
goto bail;
}
ProcessImpl = (jclass) env->NewGlobalRef((jobject) ProcessImpl);
if (!(ProcessImpl_pid = env->GetFieldID(ProcessImpl, "pid", "I"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.pid not found");
goto bail;
}
if (!(ProcessImpl_exitValue = env->GetFieldID(ProcessImpl, "exitValue", "Ljava/lang/Integer;"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.exitValue not found");
goto bail;
}
if (!(ProcessImpl_exitValueMutex = env->GetFieldID(ProcessImpl, "exitValueMutex", "Ljava/lang/Object;"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.exitValueMutex not found");
goto bail;
char version[PROP_VALUE_MAX + 1];
__system_property_get("ro.build.version.sdk", version);
sdk_version = atoi(version);
#define FIND_CLASS(out, name) \
if (!(out = env->FindClass(name))) { \
THROW(env, "java/lang/RuntimeException", name " not found"); \
goto bail; \
} \
out = reinterpret_cast<jclass>(env->NewGlobalRef(reinterpret_cast<jobject>(out)))
#define GET_FIELD(out, clazz, name, sig) \
if (!(out = env->GetFieldID(clazz, name, sig))) { \
THROW(env, "java/lang/RuntimeException", "Field " #clazz "." name " with type " sig " not found"); \
goto bail; \
}
if (sdk_version < 24) {
FIND_CLASS(ProcessImpl, "java/lang/ProcessManager$ProcessImpl");
GET_FIELD(ProcessImpl_pid, ProcessImpl, "pid", "I")
GET_FIELD(ProcessImpl_exitValue, ProcessImpl, "exitValue", "Ljava/lang/Integer;")
GET_FIELD(ProcessImpl_exitValueMutex, ProcessImpl, "exitValueMutex", "Ljava/lang/Object;")
}
result = JNI_VERSION_1_6;
......
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* This file contains character tables that are used when no external tables
are passed to PCRE by the application that calls it. The tables are used only
for characters whose code values are less than 256.
This is a default version of the tables that assumes ASCII encoding. A program
called dftables (which is distributed with PCRE) can be used to build
alternative versions of this file. This is necessary if you are running in an
EBCDIC environment, or if you want to default to a different encoding, for
example ISO-8859-1. When dftables is run, it creates these tables in the
current locale. If PCRE is configured with --enable-rebuild-chartables, this
happens automatically.
The following #includes are present because without them gcc 4.x may remove the
array definition from the final binary if PCRE is built into a static library
and dead code stripping is activated. This leads to link errors. Pulling in the
header ensures that the array gets flagged as "someone outside this compilation
unit might reference this" and so it will always be supplied to the linker. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "pcre_internal.h"
const pcre_uint8 PRIV(default_tables)[] = {
/* This table is a lower casing table. */
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122, 91, 92, 93, 94, 95,
96, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255,
/* This table is a case flipping table. */
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122, 91, 92, 93, 94, 95,
96, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255,
/* This table contains bit maps for various character classes. Each map is 32
bytes long and the bits run from the least significant end of each byte. The
classes that have their own maps are: space, xdigit, digit, upper, lower, word,
graph, print, punct, and cntrl. Other classes are built from combinations. */
0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* This table identifies various classes of character by individual bits:
0x01 white space character
0x02 letter
0x04 decimal digit
0x08 hexadecimal digit
0x10 alphanumeric or '_'
0x80 regular expression metacharacter or binary zero
*/
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
/* End of pcre_chartables.c */
Subproject commit 0c3cf8beb3a9309603c595a047d89c366d3cd383
Subproject commit 6040be9d0af812382934defe317c2e28434494ad
@ECHO OFF
SET DIR=%CD%
SET DEPS=%DIR%\.deps
RD /SQ %DEPS%
RD /SQ %DIR%\go\bin
RD /SQ %DIR%\bin
ECHO "Successfully clean overture"
......@@ -12,7 +12,7 @@ TARGET=$DIR/bin
DEPS=$DIR/.deps
ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-21-arm64
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm64
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang
......@@ -35,7 +35,7 @@ fi
if [ ! -f "$ANDROID_ARM64_CC" ]; then
echo "Make standalone toolchain for ARM64 arch"
$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch arm64 \
--api 21 --install-dir $ANDROID_ARM64_TOOLCHAIN
--api $MIN_API --install-dir $ANDROID_ARM64_TOOLCHAIN
fi
if [ ! -f "$ANDROID_X86_CC" ]; then
......@@ -44,7 +44,7 @@ if [ ! -f "$ANDROID_X86_CC" ]; then
--api $MIN_API --install-dir $ANDROID_X86_TOOLCHAIN
fi
if [ ! -d "$DIR/go/bin" ]; then
if [ ! -f "$DIR/go/bin/go" ]; then
echo "Build the custom go"
pushd $DIR/go/src
......@@ -56,33 +56,38 @@ export GOROOT=$DIR/go
export GOPATH=$DIR
export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
echo "Get dependences for overture"
go get -u github.com/tools/godep
if [ ! -f "$TARGET/armeabi-v7a/liboverture.so" ] || [ ! -f "$TARGET/arm64-v8a/liboverture.so" ] ||
[ ! -f "$TARGET/x86/liboverture.so" ]; then
pushd $GOPATH/src/github.com/shadowsocks/overture/main
godep restore
echo "Get dependences for overture"
go get -u github.com/tools/godep
echo "Cross compile overture for arm"
if [ ! -f "$TARGET/armeabi-v7a/liboverture.so" ]; then
pushd $GOPATH/src/github.com/shadowsocks/overture/main
godep restore
echo "Cross compile overture for arm"
if [ ! -f "$TARGET/armeabi-v7a/liboverture.so" ]; then
try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-s -w"
try $ANDROID_ARM_STRIP main
try mv main $TARGET/armeabi-v7a/liboverture.so
fi
fi
echo "Cross compile overture for arm64"
if [ ! -f "$TARGET/arm64-v8a/liboverture.so" ]; then
echo "Cross compile overture for arm64"
if [ ! -f "$TARGET/arm64-v8a/liboverture.so" ]; then
try env CGO_ENABLED=1 CC=$ANDROID_ARM64_CC GOOS=android GOARCH=arm64 go build -ldflags="-s -w"
try $ANDROID_ARM64_STRIP main
try mv main $TARGET/arm64-v8a/liboverture.so
fi
fi
echo "Cross compile overture for x86"
if [ ! -f "$TARGET/x86/liboverture.so" ]; then
echo "Cross compile overture for x86"
if [ ! -f "$TARGET/x86/liboverture.so" ]; then
try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build -ldflags="-s -w"
try $ANDROID_X86_STRIP main
try mv main $TARGET/x86/liboverture.so
fi
fi
popd
popd
fi
echo "Successfully build overture"
@ECHO OFF
SETLOCAL
IF NOT DEFINED ANDROID_NDK_HOME (
SET ANDROID_NDK_HOME=%ANDROID_HOME%\ndk-bundle
)
SET DIR=%CD%
SET MIN_API=%1%
SET TARGET=%DIR%\bin
SET DEPS=%DIR%\.deps
SET ANDROID_ARM_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm
SET ANDROID_ARM64_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm64
SET ANDROID_X86_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-x86
SET ANDROID_ARM_CC=%ANDROID_ARM_TOOLCHAIN%\bin\arm-linux-androideabi-clang
SET ANDROID_ARM_STRIP=%ANDROID_ARM_TOOLCHAIN%\bin\arm-linux-androideabi-strip
SET ANDROID_ARM64_CC=%ANDROID_ARM64_TOOLCHAIN%\bin\aarch64-linux-android-clang
SET ANDROID_ARM64_STRIP=%ANDROID_ARM64_TOOLCHAIN%\bin\aarch64-linux-android-strip
SET ANDROID_X86_CC=%ANDROID_X86_TOOLCHAIN%\bin\i686-linux-android-clang
SET ANDROID_X86_STRIP=%ANDROID_X86_TOOLCHAIN%\bin\i686-linux-android-strip
MKDIR %DEPS%>nul 2>nul
MKDIR %TARGET%\armeabi-v7a>nul 2>nul
MKDIR %TARGET%\x86>nul 2>nul
MKDIR %TARGET%\arm64-v8a>nul 2>nul
IF NOT EXIST %ANDROID_ARM_CC% (
ECHO "Make standalone toolchain for ARM arch"
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch arm ^
--api %MIN_API% --install-dir %ANDROID_ARM_TOOLCHAIN%
)
IF NOT EXIST %ANDROID_ARM64_CC% (
ECHO "Make standalone toolchain for ARM64 arch"
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch arm64 ^
--api %MIN_API% --install-dir %ANDROID_ARM64_TOOLCHAIN%
)
IF NOT EXIST %ANDROID_X86_CC% (
ECHO "Make standalone toolchain for X86 arch"
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch x86 ^
--api %MIN_API% --install-dir %ANDROID_X86_TOOLCHAIN%
)
IF NOT EXIST %DIR%\go\bin\go.exe (
ECHO "Build the custom go"
PUSHD %DIR%\go\src
CALL make.bat
POPD
)
SET GOROOT=%DIR%\go
SET GOPATH=%DIR%
SET PATH=%GOROOT%\bin;%GOPATH%\bin;%PATH%
SET BUILD=1
IF EXIST "%TARGET%\armeabi-v7a\liboverture.so" (
IF EXIST "%TARGET%\arm64-v8a\liboverture.so" (
IF EXIST "%TARGET%\x86\liboverture.so" (
SET BUILD=0
)
)
)
IF %BUILD% == 1 (
ECHO "Get dependences for overture"
go.exe get -u github.com\tools\godep
PUSHD %GOPATH%\src\github.com\shadowsocks\overture\main
godep.exe restore
ECHO "Cross compile overture for arm"
IF NOT EXIST "%TARGET%\armeabi-v7a\liboverture.so" (
SETLOCAL
SET CGO_ENABLED=1
SET CC=%ANDROID_ARM_CC%
SET GOOS=android
SET GOARCH=arm
SET GOARM=7
go.exe build -ldflags="-s -w"
%ANDROID_ARM_STRIP% main
MOVE main %TARGET%\armeabi-v7a\liboverture.so>nul 2>nul
ENDLOCAL
)
ECHO "Cross compile overture for arm64"
IF NOT EXIST "%TARGET%\arm64-v8a\liboverture.so" (
SETLOCAL
SET CGO_ENABLED=1
SET CC=%ANDROID_ARM64_CC%
SET GOOS=android
SET GOARCH=arm64
go.exe build -ldflags="-s -w"
%ANDROID_ARM64_STRIP% main
MOVE main %TARGET%\arm64-v8a\liboverture.so>nul 2>nul
ENDLOCAL
)
ECHO "Cross compile overture for x86"
IF NOT EXIST "%TARGET%\x86\liboverture.so" (
SETLOCAL
SET CGO_ENABLED=1
SET CC=%ANDROID_X86_CC%
SET GOOS=android
SET GOARCH=386
go.exe build -ldflags="-s -w"
%ANDROID_X86_STRIP% main
MOVE main %TARGET%\x86\liboverture.so>nul 2>nul
ENDLOCAL
)
POPD
)
ECHO "Successfully build overture"
ENDLOCAL
\ No newline at end of file
Subproject commit c8ec480cf716be70bc3cae2c4cd7f2733901ab09
Subproject commit 466f9902c9779b8801f521f88db1d1522c880c26
package com.github.shadowsocks;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
#Fri Dec 01 17:03:17 PST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
......@@ -6,20 +6,38 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
warn () {
echo "$*"
}
die ( ) {
die () {
echo
echo "$*"
echo
......@@ -30,6 +48,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
......@@ -40,26 +59,11 @@ case "`uname`" in
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
......@@ -85,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
......@@ -150,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
exec "$JAVACMD" "$@"
......@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
......@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
......@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
......
......@@ -6,25 +6,26 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
def getCurrentFlavor() {
Matcher matcher = Pattern.compile("(assemble|generate)(\\w+)(Release|Debug)")
.matcher(getGradle().getStartParameter().getTaskRequests().toString())
String task = getGradle().getStartParameter().getTaskRequests().toString()
Matcher matcher = Pattern.compile("(assemble|generate)\\w*(Release|Debug)").matcher(task)
if (matcher.find()) return matcher.group(1).toLowerCase() else {
println "NO MATCH FOUND"
return ""
println "Warning: No match found for $task"
return "debug"
}
}
android {
buildToolsVersion rootProject.buildToolsVersion
compileSdkVersion rootProject.sdkVersion
defaultConfig {
applicationId "com.github.shadowsocks"
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion
versionCode 1
versionName "4.4.0"
versionName "4.4.5"
testApplicationId "com.github.shadowsocks.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary true
resConfigs "fa", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
}
buildTypes {
debug {
......@@ -36,16 +37,12 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
checkReleaseBuilds false
}
lintOptions.checkReleaseBuilds false
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86'
universalApk false
}
}
sourceSets.main.jniLibs.srcDirs +=
......@@ -59,18 +56,13 @@ dependencies {
implementation "com.android.support:design:$supportLibraryVersion"
implementation "com.android.support:gridlayout-v7:$supportLibraryVersion"
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
implementation 'com.evernote:android-job:1.2.1'
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01'
implementation 'com.evernote:android-job:1.2.2'
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-gcm:$playServicesVersion"
implementation "com.google.firebase:firebase-config:$playServicesVersion"
implementation 'com.j256.ormlite:ormlite-android:5.0'
implementation 'com.mikepenz:crossfader:1.5.1'
implementation 'com.mikepenz:fastadapter:3.0.4'
implementation 'com.mikepenz:iconics-core:3.0.0'
implementation 'com.mikepenz:materialdrawer:6.0.2'
implementation 'com.mikepenz:materialize:1.1.2'
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
......
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="InvalidPackage">
<ignore regexp="ormlite-core" />
</issue>
<issue id="ImpliedQuantity" severity="warning" />
<issue id="ExtraTranslation" severity="warning" />
<issue id="MissingTranslation" severity="informational" />
</lint>
package com.github.shadowsocks;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.github.shadowsocks", appContext.getPackageName());
}
}
/*******************************************************************************
* *
* 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.acl
import org.junit.Assert
import org.junit.Test
class AclTest {
companion object {
private const val INPUT1 = """[proxy_all]
[bypass_list]
1.0.1.0/24
(^|\.)4tern\.com${'$'}
"""
}
@Test
fun parse() {
Assert.assertEquals(INPUT1, Acl().fromReader(INPUT1.reader()).toString());
}
}
/*******************************************************************************
* *
* 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.net.Uri
import org.junit.Assert
import org.junit.Test
class ProfileTest {
@Test
fun parsing() {
val results = Profile.findAll("garble ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server garble")
.toList()
Assert.assertEquals(1, results.size)
Assert.assertEquals(Uri.parse("ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888#example-server"),
results.single().toUri())
}
}
package com.github.shadowsocks.utils
import com.github.shadowsocks.utils.Subnet
import org.junit.Assert
import org.junit.Test
import java.net.InetAddress
object SubnetTest {
class SubnetTest {
@Test
fun parsingAndEquals() {
Assert.assertEquals(Subnet(InetAddress.getByName("1.10.11.12"), 25), Subnet.fromString("1.10.11.12/25"))
......@@ -17,16 +16,13 @@ object SubnetTest {
Assert.assertNotEquals(Subnet.fromString("1.2.3.4/12"), Subnet.fromString("1.2.3.5/12"))
}
@Test(expected = IllegalArgumentException::class)
fun invalidParsing1() {
Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/129")
}
@Test(expected = IllegalArgumentException::class)
fun invalidParsing2() {
Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/-99")
}
@Test(expected = IllegalArgumentException::class)
fun invalidParsing3() {
Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/1/0")
@Test
fun invalidParsings() {
Assert.assertEquals(null, Subnet.fromString("1.2.3.456"))
Assert.assertEquals(null, Subnet.fromString("ffff::f0000"))
Assert.assertEquals(null, Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/129"))
Assert.assertEquals(null, Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/129"))
Assert.assertEquals(null, Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/-99"))
Assert.assertEquals(null, Subnet.fromString("caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78/1/0"))
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.github.shadowsocks">
package="com.github.shadowsocks"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
......@@ -19,11 +20,14 @@
<application
android:name=".App"
android:icon="@mipmap/ic_launcher"
android:allowBackup="true"
android:backupAgent=".ConfigBackupHelper"
android:fullBackupContent="@xml/backup_descriptor"
android:fullBackupOnly="true"
android:label="@string/app_name"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:banner="@drawable/ic_start_connected">
android:banner="@drawable/ic_service_active">
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="true" />
......@@ -31,9 +35,6 @@
android:value="@integer/google_play_services_version"/>
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI_zVxZthz2HDuz9toTvkYvL0L5GA-OjeUIfBeXg"/>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts"/>
<activity
android:name=".MainActivity"
......@@ -111,6 +112,7 @@
<service
android:name=".bg.VpnService"
android:process=":bg"
android:directBootAware="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_VPN_SERVICE"
android:exported="false">
......@@ -122,31 +124,41 @@
<service
android:name=".bg.TransproxyService"
android:process=":bg"
android:directBootAware="true"
android:exported="false">
</service>
<service
android:name=".bg.ProxyService"
android:process=":bg"
android:directBootAware="true"
android:exported="false">
</service>
<service android:name=".bg.TileService" android:label="@string/quick_toggle"
android:process=":bg"
android:icon="@drawable/ic_start_connected"
android:directBootAware="true"
android:icon="@drawable/ic_service_active"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<receiver android:name=".BootReceiver" android:process=":bg" android:enabled="false">
<receiver android:name=".BootReceiver"
android:process=":bg"
android:directBootAware="true"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".tasker.ActionListener" android:process=":bg" tools:ignore="ExportedReceiver">
<receiver android:name=".tasker.ActionListener"
android:process=":bg"
android:directBootAware="true"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING"/>
</intent-filter>
......@@ -154,16 +166,24 @@
<!-- android-job components -->
<service android:name="com.evernote.android.job.v21.PlatformJobService"
android:process=":bg"/>
android:process=":bg"
android:directBootAware="true"/>
<service android:name="com.evernote.android.job.v14.PlatformAlarmService"
android:process=":bg"/>
android:process=":bg"
android:directBootAware="true"/>
<service android:name="com.evernote.android.job.v14.PlatformAlarmServiceExact"
android:process=":bg"
android:directBootAware="true"/>
<service android:name="com.evernote.android.job.gcm.PlatformGcmService"
android:process=":bg"/>
tools:node="remove"/>
<service android:name="com.evernote.android.job.JobRescheduleService"
android:process=":bg"/>
android:process=":bg"
android:directBootAware="true"/>
<receiver android:name="com.evernote.android.job.v14.PlatformAlarmReceiver"
android:process=":bg"/>
android:process=":bg"
android:directBootAware="true"/>
<receiver android:name="com.evernote.android.job.JobBootReceiver"
android:process=":bg"/>
android:process=":bg"
android:directBootAware="true"/>
</application>
</manifest>
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
[proxy_all]
[bypass_list]
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
......
......@@ -48,8 +48,6 @@
1.192.0.0/13
1.202.0.0/15
1.204.0.0/14
12.118.130.86/32
12.126.40.58/32
14.0.0.0/21
14.0.12.0/22
14.1.0.0/22
......@@ -66,8 +64,7 @@
14.130.0.0/15
14.134.0.0/15
14.144.0.0/12
14.192.4.0/22
14.192.60.0/22
14.192.56.0/21
14.192.76.0/22
14.196.0.0/15
14.204.0.0/15
......@@ -105,6 +102,7 @@
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
......@@ -143,7 +141,7 @@
36.255.164.0/22
36.255.172.0/22
36.255.176.0/22
36.255.192.0/22
36.255.220.0/22
39.0.0.0/24
39.0.2.0/23
39.0.4.0/22
......@@ -168,7 +166,7 @@
40.198.10.0/24
40.198.16.0/21
40.198.24.0/23
40.250.16.0/23
40.251.225.0/24
40.251.227.0/24
42.0.0.0/22
42.0.8.0/21
......@@ -289,7 +287,6 @@
43.226.240.0/20
43.227.0.0/21
43.227.8.0/22
43.227.28.0/22
43.227.32.0/19
43.227.64.0/19
43.227.96.0/21
......@@ -313,16 +310,12 @@
43.228.136.0/22
43.228.148.0/22
43.228.152.0/22
43.228.180.0/22
43.228.188.0/22
43.228.204.0/22
43.228.240.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.108.0/22
43.229.120.0/22
43.229.136.0/21
43.229.144.0/22
......@@ -421,6 +414,7 @@
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
......@@ -488,6 +482,7 @@
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
......@@ -526,7 +521,6 @@
43.255.8.0/22
43.255.16.0/22
43.255.48.0/22
43.255.60.0/22
43.255.64.0/20
43.255.84.0/22
43.255.96.0/22
......@@ -541,6 +535,7 @@
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
......@@ -569,7 +564,8 @@
45.114.40.0/22
45.114.52.0/22
45.114.96.0/22
45.114.104.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
......@@ -595,15 +591,12 @@
45.116.24.0/22
45.116.32.0/21
45.116.52.0/22
45.116.60.0/22
45.116.64.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.40.0/22
45.117.68.0/22
45.117.124.0/22
45.117.252.0/22
......@@ -613,11 +606,9 @@
45.119.72.0/22
45.119.104.0/22
45.119.116.0/22
45.119.160.0/22
45.119.232.0/22
45.120.100.0/22
45.120.140.0/22
45.120.156.0/22
45.120.164.0/22
45.120.220.0/22
45.120.240.0/22
......@@ -704,14 +695,103 @@
45.127.144.0/21
45.127.156.0/22
45.127.216.0/22
45.221.0.0/16
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
......@@ -730,11 +810,11 @@
49.239.192.0/18
49.246.224.0/19
52.80.0.0/14
52.95.216.105/32
52.95.249.0/24
52.95.255.144/28
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
......@@ -803,8 +883,6 @@
61.14.216.0/21
61.14.240.0/21
61.28.0.0/17
61.28.195.0/24
61.28.196.0/24
61.29.128.0/17
61.45.128.0/18
61.45.224.0/20
......@@ -815,13 +893,14 @@
61.232.0.0/14
61.236.0.0/15
61.240.0.0/14
65.55.209.0/24
72.21.221.241/32
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
......@@ -926,6 +1005,7 @@
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
......@@ -933,7 +1013,7 @@
103.7.140.0/22
103.7.212.0/22
103.7.216.0/21
103.8.4.0/22
103.8.0.0/21
103.8.8.0/22
103.8.32.0/22
103.8.52.0/22
......@@ -946,12 +1026,14 @@
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
......@@ -967,6 +1049,7 @@
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
......@@ -985,6 +1068,7 @@
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
......@@ -1025,6 +1109,7 @@
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
......@@ -1057,24 +1142,23 @@
103.27.24.0/22
103.27.56.0/22
103.27.96.0/22
103.27.208.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.144.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.48.0/22
103.30.96.0/22
103.30.148.0/22
103.30.200.0/22
103.30.216.0/22
103.30.228.0/22
103.30.234.0/23
103.30.234.0/24
103.30.236.0/22
103.31.0.0/22
103.31.48.0/20
......@@ -1092,6 +1176,7 @@
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
......@@ -1123,6 +1208,7 @@
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
......@@ -1165,7 +1251,6 @@
103.41.0.0/22
103.41.16.0/22
103.41.52.0/22
103.41.116.0/22
103.41.140.0/22
103.41.148.0/22
103.41.152.0/22
......@@ -1187,7 +1272,6 @@
103.43.96.0/21
103.43.104.0/22
103.43.124.0/22
103.43.132.0/22
103.43.184.0/22
103.43.192.0/21
103.43.208.0/22
......@@ -1239,10 +1323,7 @@
103.47.116.0/22
103.47.120.0/22
103.47.136.0/21
103.47.200.0/22
103.47.212.0/22
103.47.220.0/22
103.47.248.0/22
103.48.20.0/22
103.48.52.0/22
103.48.92.0/22
......@@ -1299,14 +1380,12 @@
103.53.160.0/22
103.53.180.0/22
103.53.204.0/22
103.53.208.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.53.0/24
103.54.54.0/23
103.54.60.0/22
103.54.160.0/21
103.54.212.0/22
......@@ -1328,18 +1407,14 @@
103.56.52.0/22
103.56.56.0/21
103.56.72.0/21
103.56.100.0/22
103.56.104.0/22
103.56.140.0/22
103.56.152.0/22
103.56.184.0/22
103.56.200.0/22
103.56.216.0/22
103.57.12.0/22
103.57.52.0/22
103.57.56.0/22
103.57.76.0/22
103.57.108.0/22
103.57.136.0/22
103.57.196.0/22
103.58.24.0/22
......@@ -1350,7 +1425,6 @@
103.59.128.0/22
103.59.148.0/22
103.59.164.0/22
103.59.216.0/22
103.60.32.0/22
103.60.44.0/22
103.60.164.0/22
......@@ -1390,6 +1464,461 @@
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
......@@ -1430,11 +1959,13 @@
103.196.88.0/21
103.196.96.0/22
103.196.168.0/22
103.196.184.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.252.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
......@@ -1547,8 +2078,8 @@
103.209.200.0/22
103.209.208.0/22
103.209.216.0/22
103.209.232.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
......@@ -1613,6 +2144,69 @@
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
......@@ -1646,6 +2240,7 @@
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
......@@ -1653,6 +2248,7 @@
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
......@@ -1677,6 +2273,7 @@
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
......@@ -1734,7 +2331,7 @@
103.238.204.0/22
103.238.252.0/22
103.239.0.0/22
103.239.40.0/21
103.239.44.0/22
103.239.68.0/22
103.239.96.0/22
103.239.152.0/21
......@@ -1752,6 +2349,7 @@
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
......@@ -1760,7 +2358,6 @@
103.241.160.0/22
103.241.184.0/21
103.241.220.0/22
103.242.8.0/22
103.242.64.0/22
103.242.128.0/21
103.242.160.0/22
......@@ -1840,6 +2437,7 @@
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
......@@ -1860,6 +2458,7 @@
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
......@@ -1867,6 +2466,8 @@
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
......@@ -1890,6 +2491,10 @@
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
......@@ -2090,6 +2695,7 @@
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
......@@ -2097,6 +2703,7 @@
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
......@@ -2117,6 +2724,9 @@
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
......@@ -2194,7 +2804,9 @@
118.103.164.0/22
118.103.168.0/21
118.103.176.0/22
118.103.244.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
......@@ -2210,11 +2822,8 @@
118.190.0.0/15
118.192.0.0/16
118.193.0.0/20
118.193.28.0/22
118.193.32.0/19
118.193.64.0/20
118.193.93.0/24
118.193.94.0/23
118.193.96.0/19
118.193.128.0/17
118.194.0.0/15
......@@ -2222,7 +2831,7 @@
118.202.0.0/15
118.204.0.0/14
118.212.0.0/15
118.215.192.0/19
118.215.192.0/18
118.224.0.0/14
118.228.0.0/15
118.230.0.0/16
......@@ -2237,8 +2846,6 @@
119.4.0.0/14
119.8.0.0/16
119.10.0.0/17
119.10.144.0/22
119.10.148.0/23
119.15.136.0/21
119.16.0.0/16
119.18.192.0/20
......@@ -2257,6 +2864,7 @@
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
......@@ -2312,7 +2920,6 @@
120.136.16.0/21
120.136.128.0/18
120.137.0.0/17
120.138.32.224/29
120.143.128.0/19
120.192.0.0/10
121.0.8.0/21
......@@ -2333,6 +2940,7 @@
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
......@@ -2348,7 +2956,6 @@
121.100.128.0/17
121.101.0.0/18
121.101.208.0/20
121.189.3.102/32
121.192.0.0/13
121.200.192.0/21
121.201.0.0/16
......@@ -2360,7 +2967,7 @@
122.0.128.0/17
122.4.0.0/14
122.8.0.0/15
122.10.0.0/16
122.10.128.0/17
122.11.0.0/17
122.12.0.0/15
122.14.0.0/16
......@@ -2466,6 +3073,7 @@
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
......@@ -2503,16 +3111,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
129.250.66.10/32
129.250.66.54/32
129.250.66.62/32
129.250.66.90/32
131.228.142.105/32
131.228.142.106/32
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
......@@ -2581,6 +3192,7 @@
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
......@@ -2591,12 +3203,13 @@
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.152.0/22
150.129.192.0/22
150.129.216.0/22
150.129.252.0/22
......@@ -2625,6 +3238,7 @@
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
......@@ -2632,6 +3246,9 @@
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
......@@ -2650,6 +3267,10 @@
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
......@@ -2675,6 +3296,7 @@
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
......@@ -2690,6 +3312,7 @@
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
......@@ -2697,19 +3320,22 @@
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.10.240.0/22
168.159.144.0/20
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.251.184.0/23
170.252.152.0/21
170.252.160.0/24
171.8.0.0/13
171.34.0.0/15
171.36.0.0/14
......@@ -2718,6 +3344,7 @@
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
......@@ -2763,6 +3390,7 @@
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
......@@ -2816,6 +3444,8 @@
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
......@@ -2835,18 +3465,20 @@
183.182.0.0/19
183.184.0.0/13
183.192.0.0/10
188.128.15.214/32
188.254.55.229/32
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.46.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
......@@ -2855,16 +3487,18 @@
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.170.79.0/24
192.188.170.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
198.17.7.0/24
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
......@@ -2965,7 +3599,7 @@
202.20.117.0/24
202.20.120.0/24
202.20.125.0/24
202.20.127.0/24
202.20.126.0/23
202.21.48.0/20
202.21.131.0/24
202.21.132.0/24
......@@ -2979,7 +3613,10 @@
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
......@@ -3018,6 +3655,7 @@
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
......@@ -3029,6 +3667,7 @@
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
......@@ -3047,6 +3686,12 @@
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
......@@ -3054,10 +3699,10 @@
202.58.0.0/24
202.58.104.0/22
202.58.112.0/22
202.59.0.0/24
202.59.0.0/23
202.59.212.0/22
202.59.232.0/23
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
......@@ -3067,16 +3712,16 @@
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.81.0/24
202.63.82.0/23
202.63.84.0/22
202.63.88.0/21
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
......@@ -3094,6 +3739,9 @@
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
......@@ -3101,7 +3749,6 @@
202.75.252.0/22
202.76.247.0/24
202.76.252.0/22
202.77.39.0/24
202.77.80.0/21
202.77.92.0/22
202.78.8.0/21
......@@ -3113,6 +3760,7 @@
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
......@@ -3122,13 +3770,18 @@
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
......@@ -3140,6 +3793,8 @@
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
......@@ -3159,6 +3814,7 @@
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
......@@ -3174,7 +3830,9 @@
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
......@@ -3199,7 +3857,9 @@
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
......@@ -3215,12 +3875,15 @@
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
......@@ -3228,7 +3891,9 @@
202.162.75.0/24
202.164.0.0/20
202.164.96.0/19
202.165.96.0/20
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
......@@ -3245,9 +3910,12 @@
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
......@@ -3477,7 +4145,6 @@
203.13.80.0/21
203.13.88.0/23
203.13.92.0/22
203.13.145.0/24
203.13.173.0/24
203.13.224.0/23
203.13.227.0/24
......@@ -3521,6 +4188,7 @@
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
......@@ -3542,7 +4210,7 @@
203.17.190.0/23
203.17.231.0/24
203.17.233.0/24
203.17.248.0/24
203.17.248.0/23
203.17.255.0/24
203.18.2.0/23
203.18.4.0/24
......@@ -3567,6 +4235,7 @@
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
......@@ -3584,6 +4253,7 @@
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
......@@ -3596,6 +4266,7 @@
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
......@@ -4029,6 +4700,7 @@
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
......@@ -4081,6 +4753,7 @@
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
......@@ -4096,12 +4769,16 @@
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
......@@ -4111,6 +4788,7 @@
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
......@@ -4125,6 +4803,8 @@
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
......@@ -4151,6 +4831,7 @@
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
......@@ -4176,29 +4857,31 @@
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.7.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.181.102.42/32
203.181.102.58/32
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
......@@ -4209,8 +4892,12 @@
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
......@@ -4220,6 +4907,8 @@
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
......@@ -4228,13 +4917,9 @@
203.208.0.0/20
203.208.16.0/22
203.208.32.0/19
203.208.146.1/32
203.208.146.77/32
203.208.171.81/32
203.209.224.0/19
203.212.0.0/20
203.212.80.0/20
203.215.146.0/24
203.215.232.0/21
203.217.164.0/22
203.222.192.0/20
......@@ -4246,6 +4931,7 @@
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
......@@ -4278,44 +4964,15 @@
210.87.128.0/18
210.185.192.0/18
210.192.96.0/19
211.22.33.61/32
211.22.33.97/32
211.22.33.105/32
211.22.33.109/32
211.22.33.113/32
211.22.33.225/32
211.64.0.0/13
211.72.233.105/32
211.72.233.109/32
211.72.233.113/32
211.72.233.117/32
211.72.233.121/32
211.72.233.125/32
211.72.233.129/32
211.72.233.133/32
211.72.233.137/32
211.72.233.173/32
211.72.233.177/32
211.72.233.181/32
211.72.233.185/32
211.72.233.189/32
211.72.233.193/32
211.72.233.197/32
211.72.233.201/32
211.72.233.205/32
211.72.233.209/32
211.72.233.213/32
211.72.233.217/32
211.72.233.221/32
211.72.233.225/32
211.72.233.229/32
211.72.233.237/32
211.72.233.241/32
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
......@@ -4361,8 +5018,6 @@
221.12.128.0/18
221.13.0.0/16
221.14.0.0/15
221.111.179.214/32
221.111.202.70/32
221.122.0.0/15
221.128.128.0/17
221.129.0.0/16
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -10,8 +10,7 @@
1.1.32.0/19
1.2.0.0/23
1.2.2.0/24
1.2.5.0/24
1.2.6.0/23
1.2.4.0/22
1.2.8.0/21
1.2.16.0/20
1.2.32.0/19
......@@ -24,29 +23,7 @@
1.4.16.0/20
1.4.32.0/19
1.4.64.0/18
1.8.0.0/24
1.8.2.0/23
1.8.4.0/22
1.8.9.0/24
1.8.10.0/23
1.8.12.0/22
1.8.16.0/20
1.8.32.0/19
1.8.64.0/19
1.8.96.0/22
1.8.100.0/23
1.8.107.0/24
1.8.112.0/20
1.8.128.0/20
1.8.144.0/22
1.8.148.0/23
1.8.154.0/23
1.8.156.0/22
1.8.160.0/19
1.8.192.0/19
1.8.224.0/20
1.8.244.0/22
1.8.248.0/21
1.8.0.0/16
1.10.0.0/21
1.10.8.0/23
1.10.11.0/24
......@@ -56,7 +33,6 @@
1.10.64.0/18
1.12.0.0/14
1.24.0.0/13
1.32.230.0/24
1.45.0.0/16
1.48.0.0/14
1.56.0.0/13
......@@ -73,9 +49,11 @@
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
......@@ -121,6 +99,7 @@
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
......@@ -130,6 +109,7 @@
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
......@@ -146,13 +126,7 @@
36.37.48.0/20
36.40.0.0/13
36.48.0.0/15
36.51.0.0/17
36.51.128.0/18
36.51.192.0/19
36.51.224.0/20
36.51.240.0/21
36.51.248.0/22
36.51.252.0/23
36.51.0.0/16
36.56.0.0/13
36.96.0.0/11
36.128.0.0/10
......@@ -164,6 +138,7 @@
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
......@@ -182,7 +157,7 @@
40.0.248.0/22
40.0.252.0/23
40.0.255.0/24
40.72.0.0/16
40.72.0.0/15
40.125.128.0/17
40.126.64.0/18
40.198.10.0/24
......@@ -195,22 +170,12 @@
42.0.16.0/21
42.0.24.0/22
42.0.32.0/19
42.0.128.0/19
42.0.160.0/20
42.0.176.0/21
42.0.184.0/24
42.0.186.0/23
42.0.188.0/22
42.0.192.0/20
42.0.208.0/21
42.0.216.0/22
42.0.220.0/23
42.0.223.0/24
42.0.224.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
......@@ -225,15 +190,7 @@
42.83.80.0/22
42.83.88.0/21
42.83.96.0/19
42.83.128.0/23
42.83.130.0/24
42.83.132.0/24
42.83.134.0/23
42.83.140.0/24
42.83.142.0/23
42.83.144.0/20
42.83.160.0/19
42.83.192.0/18
42.83.128.0/17
42.84.0.0/14
42.88.0.0/13
42.96.64.0/19
......@@ -255,13 +212,7 @@
42.123.40.0/21
42.123.48.0/20
42.123.64.0/18
42.123.128.0/19
42.123.160.0/22
42.123.164.0/24
42.123.166.0/23
42.123.168.0/21
42.123.176.0/20
42.123.192.0/18
42.123.128.0/17
42.128.0.0/12
42.156.0.0/19
42.156.36.0/22
......@@ -289,21 +240,7 @@
42.224.0.0/12
42.240.0.0/16
42.242.0.0/15
42.244.0.0/15
42.246.0.0/16
42.247.0.0/22
42.247.4.0/24
42.247.5.0/25
42.247.5.128/26
42.247.5.204/30
42.247.5.208/28
42.247.5.224/27
42.247.6.0/23
42.247.8.0/21
42.247.16.0/20
42.247.32.0/19
42.247.64.0/18
42.247.128.0/17
42.244.0.0/14
42.248.0.0/13
43.224.12.0/22
43.224.24.0/22
......@@ -321,10 +258,13 @@
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/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
......@@ -337,14 +277,17 @@
43.226.96.0/20
43.226.112.0/21
43.226.120.0/22
43.226.128.0/19
43.226.160.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
......@@ -359,15 +302,20 @@
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
......@@ -379,6 +327,8 @@
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
......@@ -397,7 +347,9 @@
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
......@@ -408,6 +360,7 @@
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
......@@ -418,12 +371,14 @@
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/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
......@@ -431,6 +386,7 @@
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
......@@ -440,18 +396,23 @@
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
......@@ -486,7 +447,9 @@
43.248.228.0/22
43.248.232.0/22
43.248.244.0/22
43.249.4.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
......@@ -499,13 +462,14 @@
43.250.12.0/22
43.250.16.0/21
43.250.28.0/22
43.250.32.0/22
43.250.32.0/21
43.250.72.0/22
43.250.96.0/20
43.250.112.0/22
43.250.112.0/21
43.250.128.0/22
43.250.144.0/21
43.250.160.0/22
43.250.168.0/22
43.250.168.0/21
43.250.176.0/22
43.250.200.0/22
43.250.212.0/22
......@@ -513,13 +477,17 @@
43.250.236.0/22
43.250.244.0/22
43.251.4.0/22
43.251.12.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/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
......@@ -539,7 +507,7 @@
43.254.168.0/21
43.254.180.0/22
43.254.184.0/21
43.254.192.0/22
43.254.192.0/21
43.254.200.0/22
43.254.208.0/22
43.254.220.0/22
......@@ -553,7 +521,9 @@
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
......@@ -562,21 +532,23 @@
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/22
45.112.216.0/21
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/24
45.113.176.0/22
45.113.184.0/22
45.113.200.0/21
45.113.208.0/20
......@@ -584,10 +556,13 @@
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
......@@ -604,8 +579,11 @@
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
......@@ -619,22 +597,28 @@
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
......@@ -653,7 +637,7 @@
45.123.48.0/20
45.123.64.0/20
45.123.80.0/21
45.123.90.0/23
45.123.88.0/22
45.123.120.0/22
45.123.128.0/21
45.123.136.0/22
......@@ -679,26 +663,37 @@
45.124.172.0/22
45.124.176.0/22
45.124.208.0/22
45.124.248.0/22
45.125.24.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/22
45.248.80.0/21
45.248.88.0/22
45.248.96.0/20
45.248.128.0/21
......@@ -709,7 +704,9 @@
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
......@@ -746,6 +743,7 @@
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
......@@ -778,13 +776,8 @@
45.254.236.0/22
45.254.240.0/22
45.254.248.0/22
45.255.0.0/18
45.255.64.0/19
45.255.96.0/20
45.255.112.0/21
45.255.120.0/22
45.255.125.0/24
45.255.126.0/23
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
......@@ -792,15 +785,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
......@@ -808,10 +805,13 @@
49.232.0.0/14
49.239.0.0/18
49.239.192.0/18
52.80.0.0/16
52.94.249.0/28
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
......@@ -819,15 +819,7 @@
58.32.0.0/11
58.65.232.0/21
58.66.0.0/15
58.68.128.0/19
58.68.160.0/23
58.68.163.0/24
58.68.164.0/22
58.68.179.0/24
58.68.180.0/24
58.68.200.0/21
58.68.208.0/20
58.68.224.0/19
58.68.128.0/17
58.82.0.0/17
58.83.0.0/16
58.87.64.0/18
......@@ -841,26 +833,9 @@
58.240.0.0/12
59.32.0.0/11
59.64.0.0/12
59.80.0.0/15
59.82.0.0/17
59.82.128.0/18
59.82.192.0/19
59.82.224.0/20
59.82.240.0/22
59.82.248.0/21
59.83.0.0/18
59.83.128.0/17
59.80.0.0/14
59.107.0.0/16
59.108.0.0/15
59.110.0.0/16
59.111.0.0/17
59.111.128.0/18
59.111.192.0/19
59.111.224.0/20
59.111.240.0/21
59.111.248.0/22
59.111.252.0/23
59.111.255.0/24
59.108.0.0/14
59.151.0.0/17
59.152.16.0/20
59.152.32.0/21
......@@ -868,6 +843,7 @@
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
......@@ -881,6 +857,7 @@
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
......@@ -896,19 +873,14 @@
60.252.0.0/16
60.253.128.0/17
60.255.0.0/16
61.4.81.0/24
61.4.82.0/23
61.4.84.0/22
61.4.88.0/21
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/18
61.29.192.0/19
61.29.224.0/20
61.29.128.0/17
61.45.128.0/18
61.45.224.0/20
61.47.128.0/18
......@@ -918,39 +890,22 @@
61.232.0.0/14
61.236.0.0/15
61.240.0.0/14
65.55.209.0/24
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/15
101.34.0.0/16
101.35.0.0/20
101.35.16.0/22
101.35.21.0/24
101.35.22.0/23
101.35.24.0/21
101.35.32.0/19
101.35.64.0/20
101.35.80.0/23
101.35.84.0/22
101.35.88.0/21
101.35.96.0/19
101.35.128.0/17
101.36.0.0/18
101.36.64.0/20
101.36.88.0/21
101.36.96.0/19
101.36.128.0/17
101.37.0.0/16
101.38.0.0/15
101.40.0.0/13
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
......@@ -993,17 +948,7 @@
101.130.0.0/15
101.132.0.0/14
101.144.0.0/12
101.192.0.0/14
101.196.0.0/17
101.196.128.0/19
101.196.160.0/22
101.196.164.0/23
101.196.166.0/24
101.196.168.0/21
101.196.176.0/20
101.196.192.0/18
101.197.0.0/16
101.198.0.0/15
101.192.0.0/13
101.200.0.0/15
101.203.128.0/19
101.203.160.0/21
......@@ -1016,23 +961,14 @@
101.234.76.0/22
101.234.80.0/20
101.234.96.0/19
101.236.0.0/17
101.236.128.0/18
101.236.192.0/19
101.236.224.0/20
101.236.240.0/21
101.237.0.0/16
101.238.0.0/15
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/19
101.251.96.0/20
101.251.116.0/22
101.251.120.0/21
101.251.64.0/18
101.251.128.0/17
101.252.0.0/15
101.254.0.0/16
......@@ -1056,42 +992,64 @@
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.4.0/22
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.248.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
......@@ -1107,29 +1065,33 @@
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/22
103.19.45.0/24
103.19.46.0/23
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.46.0/24
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.140.0/22
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
......@@ -1144,15 +1106,16 @@
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/23
103.24.222.0/24
103.24.220.0/22
103.24.228.0/22
103.24.252.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
......@@ -1165,6 +1128,8 @@
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
......@@ -1174,11 +1139,12 @@
103.27.24.0/22
103.27.56.0/22
103.27.96.0/22
103.27.185.0/24
103.27.186.0/23
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
......@@ -1187,12 +1153,12 @@
103.30.20.0/22
103.30.96.0/22
103.30.148.0/22
103.30.202.0/23
103.30.200.0/22
103.30.228.0/22
103.30.234.0/24
103.30.236.0/22
103.31.48.0/21
103.31.60.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
......@@ -1206,7 +1172,11 @@
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
......@@ -1219,6 +1189,7 @@
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
......@@ -1228,16 +1199,19 @@
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.252.0/22
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
......@@ -1248,11 +1222,12 @@
103.38.220.0/22
103.38.224.0/21
103.38.232.0/22
103.38.252.0/23
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/22
103.39.104.0/21
103.39.160.0/19
103.39.200.0/21
103.39.208.0/20
......@@ -1262,6 +1237,8 @@
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
......@@ -1269,6 +1246,7 @@
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
......@@ -1278,11 +1256,14 @@
103.41.224.0/21
103.41.232.0/22
103.42.8.0/22
103.42.24.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
......@@ -1293,10 +1274,13 @@
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
......@@ -1305,6 +1289,7 @@
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
......@@ -1328,15 +1313,18 @@
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.148.0/22
103.48.144.0/20
103.48.202.0/23
103.48.216.0/21
103.48.224.0/20
......@@ -1344,10 +1332,13 @@
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
......@@ -1376,8 +1367,10 @@
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
......@@ -1385,14 +1378,17 @@
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
......@@ -1402,12 +1398,15 @@
103.55.228.0/22
103.55.236.0/22
103.55.240.0/22
103.56.20.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
......@@ -1416,10 +1415,13 @@
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
......@@ -1432,7 +1434,9 @@
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
......@@ -1468,8 +1472,8 @@
103.64.192.0/18
103.65.0.0/20
103.65.16.0/22
103.65.38.0/23
103.65.42.0/23
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
......@@ -1481,8 +1485,10 @@
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
......@@ -1494,19 +1500,26 @@
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.119.0/24
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
......@@ -1524,13 +1537,14 @@
103.72.48.0/21
103.72.112.0/20
103.72.128.0/21
103.72.149.0/24
103.72.150.0/23
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
......@@ -1539,9 +1553,7 @@
103.73.176.0/22
103.73.204.0/22
103.73.208.0/22
103.73.240.0/23
103.73.242.0/24
103.73.244.0/22
103.73.240.0/21
103.73.248.0/22
103.74.24.0/21
103.74.32.0/20
......@@ -1554,7 +1566,6 @@
103.74.204.0/22
103.74.232.0/22
103.75.16.0/22
103.75.85.0/24
103.75.87.0/24
103.75.88.0/21
103.75.104.0/21
......@@ -1567,7 +1578,9 @@
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
......@@ -1588,21 +1601,24 @@
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.28.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
......@@ -1614,7 +1630,8 @@
103.81.148.0/22
103.81.164.0/22
103.81.168.0/22
103.81.187.0/24
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
......@@ -1622,6 +1639,283 @@
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
......@@ -1639,17 +1933,24 @@
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
......@@ -1657,6 +1958,7 @@
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
......@@ -1676,7 +1978,9 @@
103.199.164.0/22
103.199.196.0/22
103.199.228.0/22
103.199.252.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
......@@ -1713,6 +2017,8 @@
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
......@@ -1731,10 +2037,13 @@
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
......@@ -1744,8 +2053,11 @@
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
......@@ -1764,30 +2076,32 @@
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/23
103.211.98.0/24
103.211.100.0/22
103.211.96.0/21
103.211.156.0/22
103.211.165.0/24
103.211.166.0/24
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.230.0/23
103.212.228.0/22
103.212.252.0/22
103.213.40.0/21
103.213.48.0/20
......@@ -1797,19 +2111,25 @@
103.213.136.0/21
103.213.144.0/20
103.213.160.0/19
103.213.252.0/22
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.108.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
......@@ -1825,11 +2145,13 @@
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
......@@ -1844,8 +2166,7 @@
103.220.48.0/20
103.220.64.0/22
103.220.92.0/22
103.220.96.0/22
103.220.104.0/21
103.220.96.0/20
103.220.116.0/22
103.220.120.0/21
103.220.128.0/20
......@@ -1874,12 +2195,7 @@
103.222.240.0/21
103.223.16.0/20
103.223.32.0/19
103.223.64.0/19
103.223.96.0/20
103.223.112.0/21
103.223.121.0/24
103.223.123.0/24
103.223.124.0/22
103.223.64.0/18
103.223.128.0/21
103.223.140.0/22
103.223.144.0/20
......@@ -1887,11 +2203,16 @@
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
......@@ -1908,21 +2229,23 @@
103.227.132.0/22
103.227.136.0/22
103.227.196.0/22
103.227.204.0/23
103.227.206.0/24
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/23
103.229.62.0/24
103.229.60.0/22
103.229.136.0/22
103.229.148.0/22
103.229.172.0/22
......@@ -1943,11 +2266,12 @@
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.212.0/23
103.232.214.0/24
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
......@@ -1962,10 +2286,14 @@
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
......@@ -1975,9 +2303,12 @@
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
......@@ -1999,8 +2330,9 @@
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.180.0/22
103.239.176.0/21
103.239.184.0/22
103.239.192.0/21
103.239.204.0/22
......@@ -2012,15 +2344,19 @@
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.128.0/23
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
......@@ -2035,6 +2371,7 @@
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
......@@ -2047,21 +2384,24 @@
103.246.8.0/21
103.246.120.0/21
103.246.132.0/22
103.246.152.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.64.0/23
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.12.0/22
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
......@@ -2069,7 +2409,7 @@
103.249.168.0/21
103.249.176.0/22
103.249.188.0/22
103.249.193.0/24
103.249.192.0/22
103.249.244.0/22
103.249.252.0/22
103.250.32.0/22
......@@ -2081,16 +2421,20 @@
103.250.224.0/22
103.250.236.0/22
103.250.248.0/21
103.251.32.0/22
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
......@@ -2105,16 +2449,22 @@
103.253.232.0/22
103.254.8.0/22
103.254.20.0/22
103.254.64.0/21
103.254.76.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/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
......@@ -2122,87 +2472,40 @@
106.0.16.0/20
106.0.44.0/22
106.0.64.0/18
106.2.0.0/23
106.2.3.0/24
106.2.4.0/22
106.2.8.0/21
106.2.16.0/20
106.2.32.0/19
106.2.64.0/18
106.2.128.0/17
106.3.16.0/20
106.3.32.0/19
106.3.64.0/20
106.3.80.0/22
106.3.88.0/21
106.3.96.0/19
106.3.128.0/17
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/21
106.48.8.0/22
106.48.16.0/20
106.48.32.0/20
106.48.52.0/22
106.48.56.0/21
106.48.64.0/18
106.48.128.0/17
106.49.1.0/24
106.49.2.0/23
106.49.4.0/22
106.49.8.0/21
106.49.16.0/20
106.49.32.0/19
106.49.64.0/19
106.49.96.0/24
106.49.98.0/23
106.49.100.0/22
106.49.104.0/21
106.49.112.0/20
106.49.128.0/17
106.48.0.0/15
106.50.0.0/16
106.52.0.0/14
106.56.0.0/13
106.74.0.0/16
106.75.0.0/17
106.75.128.0/18
106.75.201.0/24
106.75.204.0/22
106.75.208.0/20
106.75.224.0/19
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/17
110.48.128.0/19
110.48.161.0/24
110.48.162.0/23
110.48.164.0/22
110.48.168.0/21
110.48.176.0/20
110.48.192.0/18
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/20
110.76.16.0/22
110.76.20.0/24
110.76.22.0/24
110.76.24.0/21
110.76.32.0/19
110.76.0.0/18
110.76.132.0/22
110.76.156.0/22
110.76.184.0/22
......@@ -2216,11 +2519,12 @@
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/19
110.173.64.0/18
110.173.192.0/19
110.176.0.0/12
110.192.0.0/11
......@@ -2234,20 +2538,12 @@
111.68.64.0/19
111.72.0.0/13
111.85.0.0/16
111.91.192.0/22
111.91.197.0/24
111.91.198.0/23
111.91.200.0/21
111.91.208.0/20
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/20
111.119.80.0/23
111.119.82.0/24
111.119.84.0/22
111.119.88.0/21
111.119.96.0/19
111.119.64.0/18
111.119.128.0/19
111.120.0.0/14
111.124.0.0/16
......@@ -2271,13 +2567,10 @@
111.224.0.0/13
111.235.96.0/19
111.235.156.0/22
111.235.160.0/21
111.235.170.0/23
111.235.172.0/22
111.235.176.0/20
111.235.160.0/19
112.0.0.0/10
112.64.0.0/14
112.73.64.0/18
112.73.0.0/16
112.74.0.0/15
112.80.0.0/12
112.96.0.0/13
......@@ -2298,15 +2591,13 @@
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/22
113.52.164.0/23
113.52.166.0/24
113.52.168.0/21
113.52.176.0/20
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
......@@ -2320,8 +2611,7 @@
113.132.0.0/14
113.136.0.0/13
113.194.0.0/15
113.197.100.0/23
113.197.102.0/24
113.197.100.0/22
113.200.0.0/15
113.202.0.0/16
113.204.0.0/14
......@@ -2339,17 +2629,11 @@
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.1.0/24
114.68.2.0/23
114.68.4.0/22
114.68.8.0/21
114.68.16.0/20
114.68.32.0/19
114.68.64.0/18
114.68.128.0/17
114.68.0.0/16
114.79.64.0/18
114.80.0.0/12
114.96.0.0/13
......@@ -2358,47 +2642,12 @@
114.110.64.0/18
114.111.0.0/19
114.111.160.0/19
114.112.4.0/22
114.112.8.0/22
114.112.12.0/23
114.112.24.0/21
114.112.32.0/19
114.112.64.0/19
114.112.96.0/20
114.112.116.0/22
114.112.120.0/21
114.112.136.0/21
114.112.144.0/20
114.112.160.0/19
114.112.192.0/19
114.113.0.0/17
114.113.128.0/21
114.113.140.0/22
114.113.144.0/20
114.113.160.0/19
114.113.196.0/22
114.113.200.0/21
114.113.208.0/20
114.113.224.0/20
114.114.0.0/16
114.115.0.0/18
114.115.68.0/22
114.115.72.0/21
114.115.80.0/20
114.115.96.0/19
114.115.128.0/17
114.116.0.0/14
114.132.0.0/18
114.132.64.0/19
114.132.96.0/21
114.132.104.0/22
114.132.108.0/23
114.132.110.0/24
114.132.112.0/20
114.132.128.0/17
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
......@@ -2413,11 +2662,7 @@
115.48.0.0/12
115.69.64.0/20
115.84.0.0/18
115.84.192.0/21
115.84.201.0/24
115.84.202.0/23
115.84.204.0/22
115.84.208.0/20
115.84.192.0/19
115.85.192.0/18
115.100.0.0/14
115.104.0.0/14
......@@ -2428,6 +2673,7 @@
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
......@@ -2445,16 +2691,16 @@
116.58.128.0/20
116.58.208.0/20
116.60.0.0/14
116.66.0.0/18
116.66.64.0/19
116.66.96.0/20
116.66.120.0/22
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
......@@ -2464,31 +2710,24 @@
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/21
116.196.8.0/22
116.196.12.0/23
116.196.16.0/20
116.196.33.0/24
116.196.34.0/23
116.196.36.0/22
116.196.40.0/21
116.196.48.0/20
116.196.64.0/18
116.196.128.0/17
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/20
116.199.144.0/22
116.199.149.0/24
116.199.150.0/23
116.199.152.0/21
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
......@@ -2500,7 +2739,9 @@
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
......@@ -2510,14 +2751,11 @@
117.32.0.0/13
117.40.0.0/14
117.44.0.0/15
117.48.0.0/15
117.50.0.0/16
117.51.64.0/18
117.51.128.0/17
117.48.0.0/14
117.53.48.0/20
117.53.176.0/20
117.57.0.0/16
117.58.0.0/18
117.58.0.0/17
117.59.0.0/16
117.60.0.0/14
117.64.0.0/13
......@@ -2536,39 +2774,16 @@
117.104.188.0/24
117.106.0.0/15
117.112.0.0/13
117.120.64.0/20
117.120.80.0/22
117.120.84.0/23
117.120.86.0/24
117.120.88.0/21
117.120.96.0/19
117.120.64.0/18
117.120.128.0/17
117.121.0.0/19
117.121.32.0/21
117.121.40.0/22
117.121.44.0/23
117.121.46.0/24
117.121.48.0/20
117.121.64.0/18
117.121.128.0/20
117.121.148.0/22
117.121.152.0/21
117.121.160.0/19
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/16
118.25.96.0/19
118.25.128.0/17
118.26.0.0/19
118.26.36.0/22
118.26.40.0/21
118.26.48.0/20
118.26.64.0/19
118.26.96.0/20
118.26.112.0/21
118.26.128.0/17
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
......@@ -2580,81 +2795,42 @@
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.244.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.1.0/24
118.126.2.0/23
118.126.4.0/22
118.126.8.0/21
118.126.16.0/23
118.126.18.0/24
118.126.32.0/19
118.126.64.0/18
118.126.128.0/17
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.5.0/24
118.184.8.0/23
118.184.10.0/24
118.184.12.0/24
118.184.54.0/24
118.184.56.0/22
118.184.60.0/23
118.184.62.0/24
118.184.80.0/20
118.184.96.0/19
118.184.128.0/17
118.184.0.0/16
118.186.0.0/15
118.188.0.0/16
118.190.0.0/16
118.191.0.0/17
118.191.128.0/18
118.191.192.0/20
118.191.208.0/21
118.191.248.0/21
118.190.0.0/15
118.192.0.0/16
118.193.0.0/22
118.193.40.0/21
118.193.56.0/21
118.193.68.0/22
118.193.72.0/24
118.193.77.0/24
118.193.0.0/20
118.193.32.0/19
118.193.64.0/20
118.193.96.0/19
118.194.0.0/20
118.194.16.0/21
118.194.24.0/22
118.194.29.0/24
118.194.30.0/23
118.194.32.0/19
118.194.64.0/18
118.194.128.0/18
118.194.192.0/19
118.194.232.0/21
118.194.240.0/20
118.195.0.0/16
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/19
118.215.192.0/18
118.224.0.0/14
118.228.0.0/17
118.228.128.0/20
118.228.144.0/21
118.228.156.0/22
118.228.160.0/19
118.228.192.0/18
118.229.0.0/16
118.228.0.0/15
118.230.0.0/16
118.239.0.0/16
118.242.0.0/16
......@@ -2671,45 +2847,26 @@
119.16.0.0/16
119.18.192.0/20
119.18.208.0/21
119.18.224.0/22
119.18.228.0/24
119.18.230.0/23
119.18.233.0/24
119.18.234.0/24
119.18.236.0/23
119.18.239.0/24
119.18.240.0/20
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.122.0/23
119.29.0.0/16
119.28.0.0/15
119.30.48.0/20
119.31.192.0/19
119.32.0.0/14
119.36.0.0/15
119.38.0.0/17
119.38.128.0/18
119.38.192.0/19
119.39.0.0/16
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/18
119.57.64.0/19
119.57.97.0/24
119.57.98.0/23
119.57.100.0/22
119.57.104.0/21
119.57.112.0/20
119.57.128.0/17
119.57.0.0/16
119.58.0.0/16
119.59.128.0/17
119.60.0.0/15
......@@ -2729,45 +2886,21 @@
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/21
119.235.136.0/24
119.235.138.0/23
119.235.140.0/22
119.235.144.0/20
119.235.160.0/20
119.235.176.0/22
119.235.184.0/22
119.235.128.0/18
119.248.0.0/14
119.252.96.0/21
119.252.240.0/21
119.252.248.0/22
119.252.252.0/23
119.252.254.0/24
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/18
120.30.64.0/20
120.30.80.0/21
120.30.88.0/22
120.30.92.0/23
120.30.94.0/24
120.30.96.0/19
120.30.128.0/17
120.31.0.0/17
120.31.128.0/20
120.31.145.0/24
120.31.146.0/23
120.31.148.0/22
120.31.152.0/21
120.31.160.0/19
120.31.192.0/18
120.30.0.0/15
120.32.0.0/12
120.48.0.0/15
120.52.0.0/14
......@@ -2780,23 +2913,10 @@
120.90.0.0/15
120.92.0.0/16
120.94.0.0/15
120.128.0.0/14
120.132.0.0/17
120.132.128.0/18
120.132.192.0/19
120.132.224.0/21
120.132.232.0/22
120.132.240.0/20
120.133.0.0/16
120.134.0.0/15
120.128.0.0/13
120.136.16.0/21
120.136.128.0/18
120.137.0.0/18
120.137.64.0/21
120.137.72.0/22
120.137.76.0/24
120.137.78.0/23
120.137.80.0/20
120.137.96.0/19
120.137.0.0/17
120.143.128.0/19
120.192.0.0/10
121.0.8.0/21
......@@ -2830,18 +2950,12 @@
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/18
121.201.64.0/20
121.201.80.0/21
121.201.88.0/22
121.201.92.0/23
121.201.94.0/24
121.201.96.0/19
121.201.128.0/17
121.201.0.0/16
121.204.0.0/14
121.224.0.0/12
121.248.0.0/14
......@@ -2849,34 +2963,11 @@
122.0.64.0/18
122.0.128.0/17
122.4.0.0/14
122.8.15.0/24
122.8.16.0/20
122.8.32.0/19
122.8.64.0/20
122.8.80.0/22
122.8.86.0/23
122.8.88.0/24
122.8.91.0/24
122.8.92.0/22
122.8.96.0/19
122.8.196.0/22
122.8.200.0/21
122.8.208.0/20
122.8.224.0/19
122.10.132.0/22
122.10.136.0/21
122.10.144.0/20
122.10.160.0/22
122.10.196.0/23
122.10.216.0/22
122.10.228.0/22
122.10.232.0/21
122.10.240.0/21
122.10.248.0/22
122.8.0.0/15
122.10.128.0/17
122.11.0.0/17
122.12.0.0/15
122.14.0.0/17
122.14.192.0/18
122.14.0.0/16
122.48.0.0/16
122.49.0.0/18
122.51.0.0/16
......@@ -2891,21 +2982,7 @@
122.98.240.0/20
122.102.0.0/20
122.102.64.0/19
122.112.0.0/18
122.112.64.0/19
122.112.96.0/22
122.112.101.0/24
122.112.109.0/24
122.112.118.0/24
122.112.122.0/23
122.112.124.0/23
122.112.128.0/17
122.113.0.0/16
122.114.0.0/16
122.115.0.0/18
122.115.80.0/20
122.115.96.0/19
122.115.128.0/17
122.112.0.0/14
122.119.0.0/16
122.128.100.0/22
122.128.120.0/21
......@@ -2916,6 +2993,7 @@
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
......@@ -2924,40 +3002,14 @@
122.248.24.0/21
122.248.48.0/20
122.255.64.0/21
123.0.128.0/21
123.0.136.0/23
123.0.139.0/24
123.0.140.0/22
123.0.145.0/24
123.0.147.0/24
123.0.148.0/22
123.0.152.0/21
123.0.160.0/20
123.0.176.0/22
123.0.181.0/24
123.0.182.0/24
123.0.184.0/24
123.0.191.0/24
123.0.128.0/18
123.4.0.0/14
123.8.0.0/13
123.49.130.0/24
123.49.136.0/22
123.49.141.0/24
123.49.143.0/24
123.49.152.0/21
123.49.160.0/19
123.49.192.0/18
123.49.128.0/17
123.50.160.0/19
123.52.0.0/14
123.56.0.0/15
123.58.0.0/18
123.58.64.0/20
123.58.80.0/21
123.58.88.0/22
123.58.96.0/19
123.58.128.0/17
123.59.0.0/16
123.61.0.0/16
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
......@@ -2966,20 +3018,12 @@
123.100.0.0/19
123.100.232.0/24
123.101.0.0/16
123.103.0.0/20
123.103.16.0/21
123.103.24.0/22
123.103.28.0/23
123.103.30.0/24
123.103.32.0/19
123.103.64.0/18
123.108.134.0/24
123.108.138.0/23
123.108.140.0/24
123.108.142.0/24
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
......@@ -2995,9 +3039,11 @@
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
......@@ -3008,13 +3054,13 @@
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/15
124.70.0.0/22
124.68.0.0/14
124.72.0.0/13
124.88.0.0/13
124.108.8.0/21
......@@ -3024,6 +3070,7 @@
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
......@@ -3040,12 +3087,7 @@
124.243.192.0/18
124.248.0.0/17
124.249.0.0/16
124.250.0.0/17
124.250.136.0/21
124.250.144.0/20
124.250.160.0/19
124.250.192.0/18
124.251.0.0/16
124.250.0.0/15
124.254.0.0/18
125.31.192.0/18
125.32.0.0/12
......@@ -3059,48 +3101,43 @@
125.112.0.0/12
125.169.0.0/16
125.171.0.0/16
125.208.0.0/19
125.208.37.0/24
125.208.39.0/24
125.208.40.0/24
125.208.48.0/20
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/19
139.159.32.0/21
139.159.40.0/22
139.159.50.0/23
139.159.52.0/22
139.159.56.0/21
139.159.64.0/19
139.159.96.0/20
139.159.112.0/22
139.159.116.0/23
139.159.120.0/21
139.159.128.0/17
139.159.0.0/16
139.170.0.0/16
139.176.0.0/16
139.183.0.0/16
......@@ -3117,14 +3154,7 @@
140.75.0.0/16
140.101.208.0/24
140.143.0.0/16
140.205.0.0/18
140.205.64.0/19
140.205.96.0/20
140.205.112.0/21
140.205.120.0/23
140.205.123.0/24
140.205.124.0/22
140.205.128.0/17
140.205.0.0/16
140.206.0.0/15
140.210.0.0/16
140.224.0.0/16
......@@ -3142,23 +3172,27 @@
144.7.0.0/16
144.12.0.0/16
144.36.146.0/23
144.48.12.0/22
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/22
146.196.72.0/21
146.196.92.0/22
146.196.112.0/21
146.196.124.0/22
......@@ -3166,11 +3200,15 @@
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
......@@ -3191,11 +3229,13 @@
150.242.168.0/22
150.242.184.0/21
150.242.192.0/22
150.242.232.0/21
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
......@@ -3203,14 +3243,18 @@
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
......@@ -3220,7 +3264,10 @@
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
......@@ -3232,10 +3279,10 @@
160.62.10.0/24
160.83.109.0/24
160.83.110.0/23
160.202.60.0/23
160.202.62.0/24
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
......@@ -3246,6 +3293,7 @@
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
......@@ -3261,6 +3309,7 @@
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
......@@ -3268,8 +3317,11 @@
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
......@@ -3277,6 +3329,8 @@
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
......@@ -3287,6 +3341,7 @@
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
......@@ -3298,43 +3353,30 @@
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/24
180.76.2.0/23
180.76.5.0/24
180.76.16.0/20
180.76.32.0/19
180.76.64.0/21
180.76.72.0/22
180.76.77.0/24
180.76.78.0/23
180.76.80.0/20
180.76.96.0/19
180.76.128.0/18
180.76.192.0/19
180.76.224.0/20
180.76.240.0/21
180.76.248.0/22
180.76.252.0/23
180.76.255.0/24
180.77.0.0/16
180.78.0.0/15
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
......@@ -3345,9 +3387,11 @@
180.148.216.0/21
180.148.224.0/19
180.149.128.0/19
180.150.176.0/20
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
......@@ -3356,8 +3400,8 @@
180.201.0.0/16
180.202.0.0/15
180.208.0.0/15
180.210.233.0/24
180.210.236.0/22
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
......@@ -3366,6 +3410,8 @@
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
......@@ -3373,18 +3419,12 @@
182.32.0.0/12
182.48.96.0/19
182.49.0.0/16
182.50.0.0/22
182.50.8.0/21
182.50.0.0/20
182.50.112.0/20
182.51.0.0/17
182.51.128.0/18
182.51.192.0/21
182.51.204.0/22
182.51.208.0/20
182.51.224.0/19
182.51.0.0/16
182.54.0.0/17
182.61.0.0/18
182.61.128.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
......@@ -3392,22 +3432,22 @@
182.128.0.0/12
182.144.0.0/13
182.157.0.0/16
182.160.64.0/21
182.160.72.0/22
182.160.76.0/23
182.160.78.0/24
182.160.80.0/20
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
......@@ -3419,8 +3459,11 @@
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
......@@ -3428,10 +3471,11 @@
192.23.191.0/24
192.55.10.0/23
192.55.40.0/24
192.55.46.0/23
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
......@@ -3440,11 +3484,14 @@
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
198.17.7.0/24
195.78.82.0/23
198.175.100.0/22
198.208.17.0/24
199.7.72.0/24
......@@ -3452,6 +3499,7 @@
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
......@@ -3486,9 +3534,8 @@
202.9.54.0/24
202.9.57.0/24
202.9.58.0/23
202.10.64.0/21
202.10.74.0/23
202.10.76.0/22
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
......@@ -3524,6 +3571,7 @@
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
......@@ -3548,7 +3596,7 @@
202.20.117.0/24
202.20.120.0/24
202.20.125.0/24
202.20.127.0/24
202.20.126.0/23
202.21.48.0/20
202.21.131.0/24
202.21.132.0/24
......@@ -3562,7 +3610,10 @@
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
......@@ -3601,14 +3652,19 @@
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
......@@ -3619,20 +3675,31 @@
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/24
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
......@@ -3642,35 +3709,43 @@
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.81.0/24
202.63.82.0/23
202.63.84.0/22
202.63.88.0/21
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/23
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.39.0/24
202.77.80.0/21
202.77.92.0/22
202.78.8.0/21
......@@ -3678,28 +3753,35 @@
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.4.0/22
202.84.8.0/21
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.112.0/20
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/21
202.91.184.0/23
202.91.186.0/24
202.91.188.0/22
202.91.176.0/20
202.91.224.0/19
202.92.0.0/22
202.92.8.0/21
......@@ -3708,6 +3790,8 @@
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
......@@ -3727,6 +3811,7 @@
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
......@@ -3742,19 +3827,25 @@
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.59.0/24
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
......@@ -3763,7 +3854,9 @@
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
......@@ -3779,12 +3872,16 @@
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
......@@ -3810,15 +3907,20 @@
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
......@@ -4029,6 +4131,7 @@
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
......@@ -4036,9 +4139,7 @@
203.13.18.0/24
203.13.24.0/24
203.13.44.0/23
203.13.80.192/26
203.13.82.0/23
203.13.84.0/22
203.13.80.0/21
203.13.88.0/23
203.13.92.0/22
203.13.173.0/24
......@@ -4054,7 +4155,7 @@
203.14.114.0/23
203.14.118.0/24
203.14.162.0/24
203.14.186.0/23
203.14.184.0/21
203.14.192.0/24
203.14.194.0/23
203.14.214.0/24
......@@ -4084,6 +4185,7 @@
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
......@@ -4105,7 +4207,7 @@
203.17.190.0/23
203.17.231.0/24
203.17.233.0/24
203.17.248.0/24
203.17.248.0/23
203.17.255.0/24
203.18.2.0/23
203.18.4.0/24
......@@ -4130,9 +4232,11 @@
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
......@@ -4146,6 +4250,7 @@
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
......@@ -4158,6 +4263,7 @@
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
......@@ -4196,6 +4302,7 @@
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
......@@ -4412,6 +4519,7 @@
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
......@@ -4485,7 +4593,7 @@
203.32.212.0/24
203.33.4.0/24
203.33.7.0/24
203.33.12.0/22
203.33.8.0/21
203.33.21.0/24
203.33.26.0/24
203.33.32.0/24
......@@ -4566,8 +4674,7 @@
203.56.38.0/24
203.56.40.0/24
203.56.46.0/24
203.56.50.0/23
203.56.52.0/22
203.56.48.0/21
203.56.68.0/23
203.56.82.0/23
203.56.84.0/23
......@@ -4590,6 +4697,7 @@
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
......@@ -4633,48 +4741,51 @@
203.76.168.0/22
203.76.208.0/21
203.76.216.0/22
203.76.247.0/24
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.138.0/23
203.80.140.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.12.0/22
203.83.8.0/21
203.83.56.0/21
203.83.224.0/20
203.86.0.0/18
203.86.64.0/19
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/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.97.0/24
203.91.98.0/23
203.91.100.0/22
203.91.104.0/24
203.91.106.0/23
203.91.108.0/22
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
......@@ -4688,9 +4799,9 @@
203.99.16.0/20
203.99.80.0/20
203.100.32.0/20
203.100.49.0/24
203.100.50.0/23
203.100.52.0/22
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
......@@ -4708,8 +4819,8 @@
203.118.192.0/19
203.118.241.0/24
203.118.248.0/22
203.119.24.0/24
203.119.34.0/23
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
......@@ -4717,20 +4828,21 @@
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.130.32.0/20
203.129.8.0/21
203.130.32.0/19
203.132.32.0/19
203.134.240.0/22
203.134.244.0/23
203.134.246.0/24
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
......@@ -4742,19 +4854,23 @@
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
......@@ -4762,16 +4878,23 @@
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
......@@ -4780,8 +4903,12 @@
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
......@@ -4790,38 +4917,31 @@
203.209.224.0/19
203.212.0.0/20
203.212.80.0/20
203.215.234.0/24
203.215.236.0/22
203.215.232.0/21
203.217.164.0/22
203.222.192.0/20
203.223.0.0/20
203.223.16.0/22
203.223.20.0/23
203.223.22.0/24
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
210.2.0.0/23
210.2.2.0/24
210.2.6.0/23
210.2.8.0/21
210.2.24.0/21
207.89.20.0/24
210.2.0.0/19
210.5.0.0/19
210.5.56.0/24
210.5.59.0/24
210.5.60.0/24
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.128.0/21
210.16.136.0/22
210.16.156.0/22
210.16.160.0/19
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
......@@ -4843,83 +4963,26 @@
210.192.96.0/19
211.64.0.0/13
211.80.0.0/12
211.96.0.0/15
211.98.0.0/16
211.99.0.0/18
211.99.64.0/19
211.99.128.0/17
211.100.0.0/14
211.96.0.0/13
211.136.0.0/13
211.144.0.0/13
211.152.0.0/15
211.154.0.0/19
211.154.32.0/20
211.154.49.0/24
211.154.52.0/22
211.154.56.0/21
211.154.64.0/18
211.154.128.0/17
211.155.0.0/18
211.155.67.0/24
211.155.68.0/24
211.155.72.0/21
211.155.80.0/20
211.155.96.0/19
211.155.128.0/17
211.156.0.0/18
211.156.64.0/19
211.156.96.0/21
211.156.104.0/22
211.156.108.0/23
211.156.112.0/20
211.156.128.0/17
211.157.0.0/16
211.158.0.0/15
211.144.0.0/12
211.160.0.0/13
218.0.0.0/12
218.16.0.0/13
218.24.0.0/14
218.28.0.0/15
218.30.0.0/19
218.30.64.0/18
218.30.128.0/17
218.31.0.0/16
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/15
218.98.32.0/19
218.98.96.0/19
218.98.128.0/19
218.98.192.0/18
218.99.0.0/16
218.100.90.0/23
218.100.92.0/23
218.100.94.0/24
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/22
218.185.196.0/23
218.185.198.0/24
218.185.200.0/21
218.185.208.0/20
218.185.245.0/24
218.185.246.0/23
218.185.192.0/19
218.185.240.0/21
218.192.0.0/12
218.240.0.0/14
218.244.0.0/15
218.246.0.0/17
218.246.129.0/24
218.246.131.0/24
218.246.132.0/23
218.246.134.0/24
218.246.139.0/24
218.246.160.0/19
218.246.192.0/18
218.247.0.0/18
218.247.96.0/19
218.247.128.0/17
218.240.0.0/13
218.249.0.0/16
219.72.0.0/16
219.82.0.0/16
......@@ -4928,43 +4991,13 @@
219.90.72.0/21
219.128.0.0/11
219.216.0.0/13
219.224.0.0/13
219.232.0.0/15
219.234.0.0/21
219.234.26.0/23
219.234.28.0/22
219.234.32.0/19
219.234.64.0/18
219.234.128.0/17
219.235.0.0/16
219.236.0.0/14
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/17
220.154.128.0/21
220.154.136.0/22
220.154.140.0/24
220.154.142.0/23
220.154.144.0/21
220.154.152.0/24
220.154.154.0/23
220.154.156.0/22
220.154.160.0/19
220.154.192.0/18
220.155.0.0/21
220.155.9.0/24
220.155.10.0/23
220.155.12.0/22
220.155.16.0/21
220.155.24.0/22
220.155.28.0/23
220.155.31.0/24
220.155.32.0/19
220.155.64.0/18
220.155.128.0/17
220.154.0.0/15
220.158.240.0/22
220.160.0.0/11
220.192.0.0/12
......@@ -4972,18 +5005,7 @@
220.231.128.0/17
220.232.64.0/18
220.234.0.0/16
220.242.0.0/16
220.243.0.0/17
220.243.128.0/18
220.243.200.0/24
220.243.202.0/24
220.243.204.0/24
220.243.208.0/22
220.243.214.0/23
220.243.216.0/22
220.243.221.0/24
220.243.222.0/24
220.243.238.0/24
220.242.0.0/15
220.247.136.0/21
220.248.0.0/14
220.252.0.0/16
......@@ -5000,17 +5022,7 @@
221.133.224.0/19
221.136.0.0/15
221.172.0.0/14
221.176.0.0/19
221.176.32.0/20
221.176.48.0/21
221.176.56.0/24
221.176.58.0/23
221.176.60.0/22
221.176.64.0/18
221.176.128.0/17
221.177.0.0/16
221.178.0.0/15
221.180.0.0/14
221.176.0.0/13
221.192.0.0/14
221.196.0.0/15
221.198.0.0/16
......@@ -5025,23 +5037,7 @@
222.32.0.0/11
222.64.0.0/11
222.125.0.0/16
222.126.128.0/19
222.126.160.0/21
222.126.168.0/22
222.126.172.0/23
222.126.178.0/23
222.126.180.0/22
222.126.184.0/21
222.126.192.0/21
222.126.206.0/23
222.126.208.0/22
222.126.212.0/23
222.126.216.0/21
222.126.224.0/20
222.126.240.0/24
222.126.242.0/23
222.126.244.0/22
222.126.248.0/21
222.126.128.0/17
222.128.0.0/12
222.160.0.0/14
222.168.0.0/13
......@@ -5060,62 +5056,22 @@
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/18
223.201.64.0/21
223.201.72.0/24
223.201.74.0/23
223.201.76.0/22
223.201.80.0/20
223.201.96.0/23
223.201.99.0/24
223.201.100.0/22
223.201.104.0/21
223.201.112.0/20
223.201.128.0/21
223.201.136.0/23
223.201.139.0/24
223.201.140.0/22
223.201.144.0/20
223.201.160.0/19
223.201.192.0/19
223.201.224.0/20
223.201.240.0/22
223.201.245.0/24
223.201.246.0/23
223.201.248.0/21
223.202.0.0/17
223.202.128.0/18
223.202.192.0/19
223.202.224.0/20
223.202.240.0/21
223.202.248.0/23
223.202.250.0/24
223.203.0.0/16
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/19
223.252.192.0/18
223.254.0.0/17
223.254.128.0/18
223.254.192.0/20
223.254.208.0/21
223.254.216.0/22
223.254.220.0/23
223.254.222.0/24
223.254.224.0/20
223.254.240.0/21
223.254.248.0/23
223.254.251.0/24
223.254.252.0/22
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
This source diff could not be displayed because it is too large. You can view the blob instead.
package android.support.design.widget
import android.view.animation.Interpolator
object SnackbarAnimation {
val FAST_OUT_SLOW_IN_INTERPOLATOR: Interpolator get() = AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR
const val ANIMATION_DURATION = BaseTransientBottomBar.ANIMATION_DURATION.toLong()
}
/*******************************************************************************
* *
* 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.evernote.android.job
object JobConstants {
const val DATABASE_NAME = JobStorage.DATABASE_NAME
const val PREF_FILE_NAME = JobStorage.PREF_FILE_NAME
}
......@@ -24,6 +24,7 @@ import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInfo
......@@ -31,12 +32,14 @@ import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Build
import android.os.Handler
import android.os.LocaleList
import android.os.Looper
import android.support.annotation.RequiresApi
import android.support.v4.os.UserManagerCompat
import android.support.v7.app.AppCompatDelegate
import android.util.Log
import com.evernote.android.job.JobConstants
import com.evernote.android.job.JobManager
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.AclSyncJob
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile
......@@ -44,10 +47,7 @@ import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.BottomSheetPreferenceDialogFragment
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.preference.IconListPreference
import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.TcpFastOpen
import com.github.shadowsocks.utils.broadcastReceiver
import com.github.shadowsocks.utils.*
import com.google.android.gms.analytics.GoogleAnalytics
import com.google.android.gms.analytics.HitBuilders
import com.google.android.gms.analytics.StandardExceptionParser
......@@ -58,25 +58,17 @@ import com.j256.ormlite.logger.LocalLog
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat
import java.io.File
import java.io.IOException
import java.util.*
class App : Application() {
companion object {
lateinit var app: App
private const val TAG = "ShadowsocksApplication"
// The ones in Locale doesn't have script included
private val SIMPLIFIED_CHINESE by lazy {
if (Build.VERSION.SDK_INT >= 21) Locale.forLanguageTag("zh-Hans-CN") else Locale.SIMPLIFIED_CHINESE
}
private val TRADITIONAL_CHINESE by lazy {
if (Build.VERSION.SDK_INT >= 21) Locale.forLanguageTag("zh-Hant-TW") else Locale.TRADITIONAL_CHINESE
}
}
val handler by lazy { Handler(Looper.getMainLooper()) }
val deviceContext: Context by lazy { if (Build.VERSION.SDK_INT < 24) this else DeviceContext(this) }
val remoteConfig: FirebaseRemoteConfig by lazy { FirebaseRemoteConfig.getInstance() }
private val tracker: Tracker by lazy { GoogleAnalytics.getInstance(this).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) }
fun startService() {
......@@ -86,7 +78,8 @@ class App : Application() {
fun reloadService() = sendBroadcast(Intent(Action.RELOAD))
fun stopService() = sendBroadcast(Intent(Action.CLOSE))
val currentProfile: Profile? get() = ProfileManager.getProfile(DataStore.profileId)
val currentProfile: Profile? get() =
if (DataStore.directBootAware) DirectBoot.getDeviceProfile() else ProfileManager.getProfile(DataStore.profileId)
fun switchProfile(id: Int): Profile {
val result = ProfileManager.getProfile(id) ?: ProfileManager.createProfile()
......@@ -109,86 +102,58 @@ class App : Application() {
t.printStackTrace()
}
private fun checkChineseLocale(config: Configuration) {
fun check(locale: Locale): Locale? {
if (locale.language != "zh") return null
when (locale.country) { "CN", "TW" -> return null }
if (Build.VERSION.SDK_INT >= 21) when (locale.script) {
"Hans" -> return SIMPLIFIED_CHINESE
"Hant" -> return TRADITIONAL_CHINESE
else -> Log.w(TAG, "Unknown zh locale script: ${locale.script}. Falling back to trying countries...")
}
when (locale.country) {
"SG" -> return SIMPLIFIED_CHINESE
"HK", "MO" -> return TRADITIONAL_CHINESE
}
Log.w(TAG, "Unknown zh locale: %s. Falling back to zh-Hans-CN..."
.format(Locale.ENGLISH, if (Build.VERSION.SDK_INT >= 21) locale.toLanguageTag() else locale))
return SIMPLIFIED_CHINESE
}
if (Build.VERSION.SDK_INT >= 24) @RequiresApi(24) {
val localeList = config.locales
var changed = false
val newList = Array<Locale>(localeList.size(), { i ->
val locale = localeList[i]
val newLocale = check(locale)
if (newLocale == null) locale else {
changed = true
newLocale
}
})
if (changed) {
val newConfig = Configuration(config)
newConfig.locales = LocaleList(*(newList.distinct().toTypedArray()))
val res = resources
res.updateConfiguration(newConfig, res.displayMetrics)
}
} else {
@Suppress("DEPRECATION")
val newLocale = check(config.locale)
if (newLocale != null) {
val newConfig = Configuration(config)
@Suppress("DEPRECATION")
newConfig.locale = newLocale
val res = resources
res.updateConfiguration(newConfig, res.displayMetrics)
}
}
}
override fun onCreate() {
super.onCreate()
app = this
if (!BuildConfig.DEBUG) System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR")
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
checkChineseLocale(resources.configuration)
PreferenceFragmentCompat.registerPreferenceFragment(IconListPreference::class.java,
BottomSheetPreferenceDialogFragment::class.java)
if (Build.VERSION.SDK_INT >= 24) { // migrate old files
deviceContext.moveDatabaseFrom(this, Key.DB_PUBLIC)
deviceContext.moveDatabaseFrom(this, JobConstants.DATABASE_NAME)
deviceContext.moveSharedPreferencesFrom(this, JobConstants.PREF_FILE_NAME)
val old = Acl.getFile(Acl.CUSTOM_RULES, this)
if (old.canRead()) {
Acl.getFile(Acl.CUSTOM_RULES).writeText(old.readText())
old.delete()
}
}
FirebaseApp.initializeApp(this)
FirebaseApp.initializeApp(deviceContext)
remoteConfig.setDefaults(R.xml.default_configs)
remoteConfig.fetch().addOnCompleteListener {
if (it.isSuccessful) remoteConfig.activateFetched() else Log.e(TAG, "Failed to fetch config")
}
JobManager.create(deviceContext).addJobCreator(AclSyncJob)
JobManager.create(this).addJobCreator(AclSyncJob)
PreferenceFragmentCompat.registerPreferenceFragment(IconListPreference::class.java,
BottomSheetPreferenceDialogFragment::class.java)
TcpFastOpen.enabled(DataStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
if (DataStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) {
// handle data restored
if (DataStore.directBootAware && UserManagerCompat.isUserUnlocked(this)) DirectBoot.update()
TcpFastOpen.enabled(DataStore.publicStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) {
val assetManager = assets
for (dir in arrayOf("acl", "overture"))
try {
for (file in assetManager.list(dir)) assetManager.open(dir + '/' + file).use { input ->
File(filesDir, file).outputStream().use { output -> input.copyTo(output) }
File(deviceContext.filesDir, file).outputStream().use { output -> input.copyTo(output) }
}
} catch (e: IOException) {
Log.e(TAG, e.message)
app.track(e)
}
DataStore.putLong(Key.assetUpdateTime, info.lastUpdateTime)
DataStore.publicStore.putLong(Key.assetUpdateTime, info.lastUpdateTime)
}
updateNotificationChannels()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
updateNotificationChannels()
}
private fun updateNotificationChannels() {
if (Build.VERSION.SDK_INT >= 26) @RequiresApi(26) {
val nm = getSystemService(NotificationManager::class.java)
nm.createNotificationChannels(listOf(
......@@ -202,11 +167,6 @@ class App : Application() {
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
checkChineseLocale(newConfig)
}
fun listenForPackageChanges(callback: () -> Unit): BroadcastReceiver {
val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED)
filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
......
......@@ -28,6 +28,8 @@ import android.content.BroadcastReceiver
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Bundle
......@@ -47,34 +49,39 @@ import com.futuremind.recyclerviewfastscroll.SectionTitleProvider
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.resolveResourceId
import com.github.shadowsocks.utils.thread
import java.util.concurrent.atomic.AtomicBoolean
class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
companion object {
data class ProxiedApp(val name: String, val packageName: String, val icon: Drawable)
@SuppressLint("StaticFieldLeak")
private var instance: AppManager? = null
private var receiver: BroadcastReceiver? = null
private var cachedApps: Array<ProxiedApp>? = null
private fun getApps(pm: PackageManager): Array<ProxiedApp> {
private var cachedApps: List<PackageInfo>? = null
private fun getApps(pm: PackageManager): List<ProxiedApp> {
if (receiver == null) receiver = app.listenForPackageChanges {
synchronized(AppManager) { cachedApps = null }
AppManager.instance?.reloadApps()
}
return synchronized(AppManager) {
// Labels and icons can change on configuration (locale, etc.) changes, therefore they are not cached.
val cachedApps = cachedApps ?: pm.getInstalledPackages(PackageManager.GET_PERMISSIONS)
.filter { it.requestedPermissions?.contains(Manifest.permission.INTERNET) ?: false }
.map { ProxiedApp(pm.getApplicationLabel(it.applicationInfo).toString(), it.packageName,
it.applicationInfo.loadIcon(pm)) }
.toTypedArray()
.filter { it.packageName != app.packageName &&
it.requestedPermissions?.contains(Manifest.permission.INTERNET) ?: false }
this.cachedApps = cachedApps
cachedApps
}.map { ProxiedApp(pm, it.applicationInfo, it.packageName) }
}
}
private class ProxiedApp(private val pm: PackageManager, private val appInfo: ApplicationInfo,
val packageName: String) {
val name: CharSequence = appInfo.loadLabel(pm) // cached for sorting
val icon: Drawable get() = appInfo.loadIcon(pm)
}
private inner class AppViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
......@@ -113,13 +120,8 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
private var apps = listOf<ProxiedApp>()
fun reload() {
apps = getApps(packageManager).sortedWith(Comparator { a, b ->
when (Pair(proxiedApps.contains(a.packageName), proxiedApps.contains(b.packageName))) {
Pair(true, false) -> -1
Pair(false, true) -> 1
else -> a.name.compareTo(b.name, true)
}
})
apps = getApps(packageManager)
.sortedWith(compareBy({ !proxiedApps.contains(it.packageName) }, { it.name.toString() }))
}
override fun onBindViewHolder(holder: AppViewHolder, position: Int) = holder.bind(apps[position])
......@@ -179,7 +181,7 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
setContentView(R.layout.layout_apps)
toolbar = findViewById(R.id.toolbar)
toolbar.setTitle(R.string.proxied_apps)
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material)
toolbar.setNavigationIcon(theme.resolveResourceId(R.attr.homeAsUpIndicator))
toolbar.setNavigationOnClickListener {
val intent = parentActivityIntent
if (shouldUpRecreateTask(intent) || isTaskRoot)
......@@ -228,6 +230,7 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
it.individual = proxiedAppString
ProfileManager.updateProfile(it)
}
if (DataStore.directBootAware) DirectBoot.update()
Toast.makeText(this, R.string.action_apply_all, Toast.LENGTH_SHORT).show()
} else Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show()
return true
......
......@@ -26,6 +26,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.preference.DataStore
class BootReceiver : BroadcastReceiver() {
companion object {
......@@ -39,6 +40,11 @@ class BootReceiver : BroadcastReceiver() {
}
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) app.startService()
val locked = when (intent.action) {
Intent.ACTION_BOOT_COMPLETED -> false
Intent.ACTION_LOCKED_BOOT_COMPLETED -> true // constant will be folded so no need to do version checks
else -> return
}
if (DataStore.directBootAware == locked) app.startService()
}
}
......@@ -22,10 +22,10 @@ package com.github.shadowsocks
import android.app.backup.BackupAgentHelper
import android.app.backup.FileBackupHelper
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.utils.Key
@Deprecated("Only used in API level < 23. For 6.0+, Auto Backup for Apps is used.")
class ConfigBackupHelper : BackupAgentHelper() {
override fun onCreate() = addHelper("com.github.shadowsocks.database.profile",
FileBackupHelper(this, "../databases/" + Key.PROFILE, Acl.CUSTOM_RULES + ".acl"))
override fun onCreate() = addHelper("com.github.shadowsocks.database.profile", FileBackupHelper(this,
"../databases/" + Key.DB_PROFILE, "../databases/" + Key.DB_PUBLIC))
}
......@@ -20,27 +20,40 @@
package com.github.shadowsocks
import android.app.admin.DevicePolicyManager
import android.os.Build
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v14.preference.SwitchPreference
import android.support.v7.preference.Preference
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.TcpFastOpen
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompatDividers
class GlobalSettingsPreferenceFragment : PreferenceFragmentCompatDividers() {
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore
preferenceManager.preferenceDataStore = DataStore.publicStore
DataStore.initGlobal()
addPreferencesFromResource(R.xml.pref_global)
val switch = findPreference(Key.isAutoConnect) as SwitchPreference
switch.setOnPreferenceChangeListener { _, value ->
BootReceiver.enabled = value as Boolean
val boot = findPreference(Key.isAutoConnect) as SwitchPreference
val directBootAwareListener = Preference.OnPreferenceChangeListener { _, newValue ->
if (newValue as Boolean) DirectBoot.update() else DirectBoot.clean()
true
}
switch.isChecked = BootReceiver.enabled
boot.setOnPreferenceChangeListener { _, value ->
BootReceiver.enabled = value as Boolean
directBootAwareListener.onPreferenceChange(null, DataStore.directBootAware)
}
boot.isChecked = BootReceiver.enabled
val dba = findPreference(Key.directBootAware)
if (Build.VERSION.SDK_INT >= 24 && context!!.getSystemService(DevicePolicyManager::class.java)
.storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER)
dba.onPreferenceChangeListener = directBootAwareListener else dba.parent!!.removePreference(dba)
val tfo = findPreference(Key.tfo) as SwitchPreference
tfo.isChecked = TcpFastOpen.sendEnabled
......
......@@ -31,19 +31,15 @@ import android.nfc.NfcAdapter
import android.os.Bundle
import android.os.SystemClock
import android.support.customtabs.CustomTabsIntent
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.support.v7.content.res.AppCompatResources
import android.support.v7.preference.PreferenceDataStore
import android.support.v7.widget.TooltipCompat
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.TextView
import com.github.jorgecastilloprz.FABProgressCircle
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.CustomRulesFragment
......@@ -59,6 +55,7 @@ import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.responseLength
import com.github.shadowsocks.utils.thread
import com.github.shadowsocks.widget.ServiceButton
import com.mikepenz.crossfader.Crossfader
import com.mikepenz.crossfader.view.CrossFadeSlidingPaneLayout
import com.mikepenz.materialdrawer.Drawer
......@@ -88,8 +85,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
// UI
private lateinit var fab: FloatingActionButton
private lateinit var fabProgressCircle: FABProgressCircle
private lateinit var fab: ServiceButton
internal var crossfader: Crossfader<CrossFadeSlidingPaneLayout>? = null
internal lateinit var drawer: Drawer
private var previousSelectedDrawer: Long = 0 // it's actually lateinit
......@@ -111,19 +107,12 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
} catch (_: ActivityNotFoundException) { } // ignore
fun launchUrl(uri: String) = launchUrl(Uri.parse(uri))
private val greyTint by lazy { ContextCompat.getColorStateList(this, R.color.material_primary_500) }
private val greenTint by lazy { ContextCompat.getColorStateList(this, R.color.material_green_700) }
private fun hideCircle() = try {
fabProgressCircle.hide()
} catch (_: NullPointerException) { } // ignore
// service
var state = BaseService.IDLE
override val serviceCallback: IShadowsocksServiceCallback.Stub by lazy {
object : IShadowsocksServiceCallback.Stub() {
override fun stateChanged(state: Int, profileName: String?, msg: String?) {
app.handler.post { changeState(state, msg) }
app.handler.post { changeState(state, msg, true) }
}
override fun trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
app.handler.post { updateTraffic(profileId, txRate, rxRate, txTotal, rxTotal) }
......@@ -134,27 +123,13 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
}
fun changeState(state: Int, msg: String? = null) {
fun changeState(state: Int, msg: String? = null, animate: Boolean = false) {
fab.changeState(state, animate)
when (state) {
BaseService.CONNECTING -> {
fab.setImageResource(R.drawable.ic_start_busy)
fabProgressCircle.show()
statusText.setText(R.string.connecting)
}
BaseService.CONNECTED -> {
if (this.state == BaseService.CONNECTING) fabProgressCircle.beginFinalAnimation()
else fabProgressCircle.postDelayed(this::hideCircle, 1000)
fab.setImageResource(R.drawable.ic_start_connected)
statusText.setText(R.string.vpn_connected)
}
BaseService.STOPPING -> {
fab.setImageResource(R.drawable.ic_start_busy)
if (this.state == BaseService.CONNECTED) fabProgressCircle.show() // ignore for stopped
statusText.setText(R.string.stopping)
}
BaseService.CONNECTING -> statusText.setText(R.string.connecting)
BaseService.CONNECTED -> statusText.setText(R.string.vpn_connected)
BaseService.STOPPING -> statusText.setText(R.string.stopping)
else -> {
fab.setImageResource(R.drawable.ic_start_idle)
fabProgressCircle.postDelayed(this::hideCircle, 1000)
if (msg != null) {
Snackbar.make(findViewById(R.id.snackbar),
getString(R.string.vpn_error).format(Locale.ENGLISH, msg), Snackbar.LENGTH_LONG).show()
......@@ -164,20 +139,12 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
}
this.state = state
if (state == BaseService.CONNECTED) {
fab.backgroundTintList = greenTint
TooltipCompat.setTooltipText(fab, getString(R.string.stop))
} else {
fab.backgroundTintList = greyTint
TooltipCompat.setTooltipText(fab, getString(R.string.connect))
if (state != BaseService.CONNECTED) {
updateTraffic(-1, 0, 0, 0, 0)
testCount += 1 // suppress previous test messages
}
ProfilesFragment.instance?.profilesAdapter?.notifyDataSetChanged() // refresh button enabled state
stateListener?.invoke(state)
fab.isEnabled = false
if (state == BaseService.CONNECTED || state == BaseService.STOPPED) app.handler.postDelayed(
{ fab.isEnabled = state == BaseService.CONNECTED || state == BaseService.STOPPED }, 1000)
}
fun updateTraffic(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
txText.text = TrafficMonitor.formatTraffic(txTotal)
......@@ -225,6 +192,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
}
override val listenForDeath: Boolean get() = true
override fun onServiceConnected(service: IShadowsocksService) = changeState(service.state)
override fun onServiceDisconnected() = changeState(BaseService.IDLE)
override fun binderDied() {
......@@ -322,7 +290,6 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
fab = findViewById(R.id.fab)
fabProgressCircle = findViewById(R.id.fabProgressCircle)
fab.setOnClickListener {
if (state == BaseService.CONNECTED) app.stopService() else thread {
if (BaseService.usingVpnMode) {
......@@ -335,7 +302,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
changeState(BaseService.IDLE) // reset everything to init state
app.handler.post { connection.connect() }
DataStore.registerChangeListener(this)
DataStore.publicStore.registerChangeListener(this)
val intent = this.intent
if (intent != null) handleShareIntent(intent)
......@@ -355,7 +322,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
}
else -> null
}
if (TextUtils.isEmpty(sharedStr)) return
if (sharedStr.isNullOrEmpty()) return
val profiles = Profile.findAll(sharedStr).toList()
if (profiles.isEmpty()) {
Snackbar.make(findViewById(R.id.snackbar), R.string.profile_invalid_input, Snackbar.LENGTH_LONG).show()
......@@ -404,7 +371,6 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
override fun onResume() {
super.onResume()
app.remoteConfig.fetch()
if (state !in arrayOf(BaseService.STOPPING, BaseService.CONNECTING)) hideCircle()
}
override fun onStart() {
......@@ -434,7 +400,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
override fun onDestroy() {
super.onDestroy()
DataStore.unregisterChangeListener(this)
DataStore.publicStore.unregisterChangeListener(this)
connection.disconnect()
BackupManager(this).dataChanged()
app.handler.removeCallbacksAndMessages(null)
......
......@@ -33,7 +33,6 @@ import android.support.v7.preference.PreferenceDataStore
import android.support.v7.widget.Toolbar
import android.view.MenuItem
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.plugin.PluginConfiguration
......@@ -45,6 +44,7 @@ import com.github.shadowsocks.preference.IconListPreference
import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import com.github.shadowsocks.preference.PluginConfigurationDialogFragment
import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.takisoft.fix.support.v7.preference.EditTextPreference
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompatDividers
......@@ -62,7 +62,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
private lateinit var pluginConfiguration: PluginConfiguration
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore
preferenceManager.preferenceDataStore = DataStore.privateStore
val activity = activity!!
val profile = ProfileManager.getProfile(activity.intent.getIntExtra(Action.EXTRA_PROFILE_ID, -1))
if (profile == null) {
......@@ -77,15 +77,16 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
findPreference(Key.remotePort).summary = "1337"
findPreference(Key.password).summary = "\u2022".repeat(32)
}
val serviceMode = DataStore.serviceMode
findPreference(Key.remoteDns).isEnabled = serviceMode != Key.modeProxy
isProxyApps = findPreference(Key.proxyApps) as SwitchPreference
if (Build.VERSION.SDK_INT < 21) isProxyApps.parent!!.removePreference(isProxyApps) else {
isProxyApps.isEnabled = BaseService.usingVpnMode
isProxyApps.isEnabled = serviceMode == Key.modeVpn
isProxyApps.setOnPreferenceClickListener {
startActivity(Intent(activity, AppManager::class.java))
isProxyApps.isChecked = true
false
}
}
findPreference(Key.udpdns).isEnabled = serviceMode != Key.modeProxy
plugin = findPreference(Key.plugin) as IconListPreference
pluginConfigure = findPreference(Key.pluginConfigure) as EditTextPreference
plugin.unknownValueSummary = getString(R.string.plugin_unknown)
......@@ -102,7 +103,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
pluginConfigure.onPreferenceChangeListener = this
initPlugins()
app.listenForPackageChanges { initPlugins() }
DataStore.registerChangeListener(this)
DataStore.privateStore.registerChangeListener(this)
}
private fun initPlugins() {
......@@ -130,6 +131,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
profile.deserialize()
ProfileManager.updateProfile(profile)
ProfilesFragment.instance?.profilesAdapter?.deepRefreshId(profile.id)
if (DataStore.profileId == profile.id && DataStore.directBootAware) DirectBoot.update()
activity!!.finish()
}
......@@ -141,7 +143,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
override fun onPreferenceChange(preference: Preference?, newValue: Any?): Boolean = try {
val selected = pluginConfiguration.selected
pluginConfiguration = PluginConfiguration(pluginConfiguration.pluginsOptions +
(pluginConfiguration.selected to PluginOptions(selected, newValue as String?)), selected)
(pluginConfiguration.selected to PluginOptions(selected, newValue as? String?)), selected)
DataStore.plugin = pluginConfiguration.toString()
DataStore.dirty = true
true
......@@ -201,7 +203,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
}
override fun onDestroy() {
DataStore.unregisterChangeListener(this)
DataStore.privateStore.unregisterChangeListener(this)
super.onDestroy()
}
}
......@@ -76,7 +76,8 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
}
@SuppressLint("ValidFragment")
private class QRCodeDialog() : DialogFragment() {
class QRCodeDialog() : DialogFragment() {
constructor(url: String) : this() {
val bundle = Bundle()
bundle.putString(KEY_URL, url)
......@@ -104,9 +105,11 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
}
override fun onDetach() {
super.onDetach()
val activity = activity
if (activity != null && !activity.isFinishing && !activity.isDestroyed)
adapter?.setNdefPushMessage(null, activity)
adapter = null
super.onDetach()
}
}
......@@ -174,10 +177,13 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
val params =
LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
params.gravity = Gravity.CENTER_HORIZONTAL
adView = AdView(activity)
val context = context!!
adView = AdView(context)
adView.layoutParams = params
adView.adUnitId = "ca-app-pub-9097031975646651/7760346322"
adView.adSize = AdSize.FLUID
val padding = context.resources.getDimensionPixelOffset(R.dimen.profile_padding)
adView.setPadding(padding, 0, 0, padding)
itemView.findViewById<LinearLayout>(R.id.content).addView(adView)
......@@ -217,6 +223,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
inner class ProfilesAdapter : RecyclerView.Adapter<ProfileViewHolder>() {
internal val profiles = ProfileManager.getAllProfiles()?.toMutableList() ?: mutableListOf()
private val updated = HashSet<Profile>()
init {
setHasStableIds(true) // see: http://stackoverflow.com/a/32488059/2245107
......@@ -246,13 +253,17 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
next.userOrder = previousOrder
previousOrder = order
profiles[i] = next
ProfileManager.updateProfile(next)
updated.add(next)
}
first.userOrder = previousOrder
profiles[to] = first
ProfileManager.updateProfile(first)
updated.add(first)
notifyItemMoved(from, to)
}
fun commitMove() {
updated.forEach { ProfileManager.updateProfile(it) }
updated.clear()
}
fun remove(pos: Int) {
profiles.removeAt(pos)
......@@ -341,6 +352,10 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
profilesAdapter.move(viewHolder.adapterPosition, target.adapterPosition)
return true
}
override fun clearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?) {
super.clearView(recyclerView, viewHolder)
profilesAdapter.commitMove()
}
}).attachToRecyclerView(profilesList)
}
......
......@@ -25,7 +25,6 @@ import android.content.Intent
import android.content.pm.ShortcutManager
import android.os.Build
import android.os.Bundle
import android.os.PersistableBundle
import android.support.v4.content.pm.ShortcutInfoCompat
import android.support.v4.content.pm.ShortcutManagerCompat
import android.support.v4.graphics.drawable.IconCompat
......@@ -34,8 +33,8 @@ import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.bg.BaseService
class QuickToggleShortcut : Activity(), ShadowsocksConnection.Interface {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (intent.action == Intent.ACTION_CREATE_SHORTCUT) {
setResult(Activity.RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(this,
ShortcutInfoCompat.Builder(this, "toggle")
......
......@@ -32,6 +32,7 @@ import android.support.v7.widget.Toolbar
import android.widget.Toast
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.utils.resolveResourceId
import com.google.zxing.Result
import me.dm7.barcodescanner.zxing.ZXingScannerView
......@@ -54,7 +55,7 @@ class ScannerActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
setContentView(R.layout.layout_scanner)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.title = title
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material)
toolbar.setNavigationIcon(theme.resolveResourceId(R.attr.homeAsUpIndicator))
toolbar.setNavigationOnClickListener { navigateUp() }
scannerView = findViewById(R.id.scanner)
if (Build.VERSION.SDK_INT >= 25) getSystemService(ShortcutManager::class.java).reportShortcutUsed("scan")
......
......@@ -41,6 +41,7 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection
val serviceCallback: IShadowsocksServiceCallback? get() = null
val connection: ShadowsocksConnection
get() = connections.getOrPut(this, { ShadowsocksConnection(this) })
val listenForDeath get() = false
fun onServiceConnected(service: IShadowsocksService) { }
/**
......@@ -66,7 +67,7 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection
override fun onServiceConnected(name: ComponentName?, binder: IBinder) {
this.binder = binder
binder.linkToDeath(instance, 0)
if (instance.listenForDeath) binder.linkToDeath(instance, 0)
val service = IShadowsocksService.Stub.asInterface(binder)!!
this.service = service
if (instance.serviceCallback != null && !callbackRegistered) try {
......@@ -106,7 +107,7 @@ class ShadowsocksConnection(private val instance: Interface) : ServiceConnection
(instance as Context).unbindService(this)
} catch (_: IllegalArgumentException) { } // ignore
connectionActive = false
binder?.unlinkToDeath(instance, 0)
if (instance.listenForDeath) binder?.unlinkToDeath(instance, 0)
binder = null
service = null
}
......
......@@ -20,6 +20,7 @@
package com.github.shadowsocks
import android.app.Activity
import android.app.KeyguardManager
import android.content.BroadcastReceiver
import android.content.Context
......@@ -27,15 +28,13 @@ import android.content.Intent
import android.content.IntentFilter
import android.net.VpnService
import android.os.Bundle
import android.os.PersistableBundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.broadcastReceiver
class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface {
class VpnRequestActivity : Activity(), ShadowsocksConnection.Interface {
companion object {
private const val TAG = "VpnRequestActivity"
private const val REQUEST_CONNECT = 1
......@@ -43,8 +42,8 @@ class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface
private var receiver: BroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!BaseService.usingVpnMode) {
finish()
return
......
......@@ -20,14 +20,15 @@
package com.github.shadowsocks.acl
import android.content.Context
import android.support.v7.util.SortedList
import android.util.Log
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Subnet
import com.github.shadowsocks.utils.asIterable
import com.j256.ormlite.field.DatabaseField
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.io.Reader
import java.net.URL
......@@ -41,21 +42,29 @@ class Acl {
const val GFWLIST = "gfwlist"
const val CHINALIST = "china-list"
const val CUSTOM_RULES = "custom-rules"
const val CUSTOM_RULES_FLATTENED = "custom-rules-flattened"
val networkAclParser = "^IMPORT_URL\\s*<(.+)>\\s*$".toRegex()
fun getFile(id: String) = File(app.filesDir, id + ".acl")
val customRules: Acl get() {
fun getFile(id: String, context: Context = app.deviceContext) = File(context.filesDir, id + ".acl")
var customRules: Acl
get() {
val acl = Acl()
try {
acl.fromId(CUSTOM_RULES)
} catch (_: FileNotFoundException) { }
val str = DataStore.publicStore.getString(CUSTOM_RULES)
if (str != null) {
acl.fromReader(str.reader())
if (!acl.bypass) {
acl.subnets.clear()
acl.hostnames.clear()
acl.bypass = true
acl.bypassHostnames.clear() // everything is bypassed
}
} else acl.bypass = true
return acl
}
fun save(id: String, acl: Acl): Unit = getFile(id).bufferedWriter().use { it.write(acl.toString()) }
set(value) = DataStore.publicStore.putString(CUSTOM_RULES, if ((!value.bypass ||
value.subnets.size() == 0 && value.hostnames.size() == 0) && value.urls.size() == 0)
null else value.toString())
fun save(id: String, acl: Acl) = getFile(id).writeText(acl.toString())
}
private abstract class BaseSorter<T> : SortedList.Callback<T>() {
......@@ -79,41 +88,39 @@ class Acl {
override fun compareNonNull(o1: URL, o2: URL): Int = ordering.compare(o1, o2)
}
@DatabaseField(generatedId = true)
var id = 0
val bypassHostnames = SortedList(String::class.java, StringSorter)
val proxyHostnames = SortedList(String::class.java, StringSorter)
val hostnames = SortedList(String::class.java, StringSorter)
val subnets = SortedList(Subnet::class.java, SubnetSorter)
val urls = SortedList(URL::class.java, URLSorter)
@DatabaseField
var bypass = false
fun fromAcl(other: Acl): Acl {
bypassHostnames.clear()
for (item in other.bypassHostnames.asIterable()) bypassHostnames.add(item)
proxyHostnames.clear()
for (item in other.proxyHostnames.asIterable()) proxyHostnames.add(item)
fun clear(): Acl {
hostnames.clear()
subnets.clear()
for (item in other.subnets.asIterable()) subnets.add(item)
urls.clear()
return this
}
fun fromAcl(other: Acl): Acl {
clear()
for (item in other.hostnames.asIterable()) hostnames.add(item)
for (item in other.subnets.asIterable()) subnets.add(item)
for (item in other.urls.asIterable()) urls.add(item)
bypass = other.bypass
return this
}
fun fromReader(reader: Reader, defaultBypass: Boolean = false): Acl {
bypassHostnames.clear()
proxyHostnames.clear()
subnets.clear()
urls.clear()
clear()
bypass = defaultBypass
val proxyHostnames by lazy { SortedList(String::class.java, StringSorter) }
val bypassHostnames by lazy { SortedList(String::class.java, StringSorter) }
val bypassSubnets by lazy { SortedList(Subnet::class.java, SubnetSorter) }
val proxySubnets by lazy { SortedList(Subnet::class.java, SubnetSorter) }
var hostnames: SortedList<String>? = if (defaultBypass) proxyHostnames else bypassHostnames
var subnets: SortedList<Subnet>? = if (defaultBypass) proxySubnets else bypassSubnets
reader.useLines {
for (line in it) {
val blocks = line.split('#', limit = 2)
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
val blocks = (line as java.lang.String).split("#", 2)
val url = networkAclParser.matchEntire(blocks.getOrElse(1, {""}))?.groupValues?.getOrNull(1)
if (url != null) urls.add(URL(url))
val input = blocks[0].trim()
......@@ -132,30 +139,39 @@ class Acl {
}
"[reject_all]", "[bypass_all]" -> bypass = true
"[accept_all]", "[proxy_all]" -> bypass = false
else -> if (subnets != null && input.isNotEmpty()) try {
subnets!!.add(Subnet.fromString(input))
} catch (_: IllegalArgumentException) {
hostnames!!.add(input)
else -> if (subnets != null && input.isNotEmpty()) {
val subnet = Subnet.fromString(input)
if (subnet == null) hostnames!!.add(input) else subnets!!.add(subnet)
}
}
}
}
for (item in (if (bypass) proxyHostnames else bypassHostnames).asIterable()) this.hostnames.add(item)
for (item in (if (bypass) proxySubnets else bypassSubnets).asIterable()) this.subnets.add(item)
return this
}
fun fromId(id: String): Acl = fromReader(Acl.getFile(id).bufferedReader())
fun fromId(id: String): Acl = try {
fromReader(Acl.getFile(id).bufferedReader())
} catch (_: IOException) { this }
fun flatten(depth: Int): Acl {
if (depth > 0) for (url in urls.asIterable()) {
val child = Acl().fromReader(url.openStream().bufferedReader(), bypass).flatten(depth - 1)
val child = Acl()
try {
child.fromReader(url.openStream().bufferedReader(), bypass).flatten(depth - 1)
} catch (_: IOException) {
continue
}
if (bypass != child.bypass) {
Log.w(TAG, "Imported network ACL has a conflicting mode set. " +
"This will probably not work as intended. URL: $url")
child.subnets.clear() // subnets for the different mode are discarded
// rules for the different mode are discarded
child.hostnames.clear()
child.subnets.clear()
child.bypass = bypass
}
for (item in child.bypassHostnames.asIterable()) bypassHostnames.add(item)
for (item in child.proxyHostnames.asIterable()) proxyHostnames.add(item)
for (item in child.hostnames.asIterable()) hostnames.add(item)
for (item in child.subnets.asIterable()) subnets.add(item)
}
urls.clear()
......@@ -164,21 +180,11 @@ class Acl {
override fun toString(): String {
val result = StringBuilder()
result.append(if (bypass) "[bypass_all]\n" else "[proxy_all]\n")
val bypassList = (if (bypass) bypassHostnames.asIterable().asSequence() else
subnets.asIterable().asSequence().map(Subnet::toString) + proxyHostnames.asIterable().asSequence()).toList()
val proxyList = (if (bypass) subnets.asIterable().asSequence().map(Subnet::toString) +
proxyHostnames.asIterable().asSequence() else bypassHostnames.asIterable().asSequence()).toList()
if (bypassList.isNotEmpty()) {
result.append("[bypass_list]\n")
result.append(bypassList.joinToString("\n"))
result.append(if (bypass) "[bypass_all]\n[proxy_list]\n" else "[proxy_all]\n[bypass_list]\n")
result.append(subnets.asIterable().joinToString("\n"))
result.append('\n')
}
if (proxyList.isNotEmpty()) {
result.append("[proxy_list]\n")
result.append(proxyList.joinToString("\n"))
result.append(hostnames.asIterable().joinToString("\n"))
result.append('\n')
}
result.append(urls.asIterable().joinToString("") { "#IMPORT_URL <$it>\n" })
return result.toString()
}
......
......@@ -48,7 +48,6 @@ import com.github.shadowsocks.ToolbarFragment
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.Subnet
import com.github.shadowsocks.utils.asIterable
import com.github.shadowsocks.utils.dp
import com.github.shadowsocks.widget.UndoSnackbarManager
import java.net.IDN
import java.net.URL
......@@ -62,7 +61,8 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private const val SELECTED_HOSTNAMES = "com.github.shadowsocks.acl.CustomRulesFragment.SELECTED_HOSTNAMES"
private const val SELECTED_URLS = "com.github.shadowsocks.acl.CustomRulesFragment.SELECTED_URLS"
private val PATTERN_DOMAIN = """(?<=^\(\^\|\\\.\)).*(?=\$$)""".toRegex()
// unescaped: (?<=^(\(\^\|\\\.\)|\^\(\.\*\\\.\)\?)).*(?=\$$)
private val PATTERN_DOMAIN = "(?<=^(\\(\\^\\|\\\\\\.\\)|\\^\\(\\.\\*\\\\\\.\\)\\?)).*(?=\\\$\$)".toRegex()
}
private enum class Template {
......@@ -78,7 +78,8 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
init {
view.setPaddingRelative(view.paddingStart, view.paddingTop,
Math.max(view.paddingEnd, 20f.dp().toInt()), view.paddingBottom)
Math.max(view.paddingEnd, resources.getDimensionPixelSize(R.dimen.fastscroll__bubble_corner)),
view.paddingBottom)
view.setOnClickListener(this)
view.setOnLongClickListener(this)
view.setBackgroundResource(R.drawable.background_selectable)
......@@ -132,20 +133,20 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
override fun onBindViewHolder(holder: AclRuleViewHolder, i: Int) {
val j = i - acl.subnets.size()
if (j < 0) holder.bind(acl.subnets[i]) else {
val k = j - acl.proxyHostnames.size()
if (k < 0) holder.bind(acl.proxyHostnames[j]) else holder.bind(acl.urls[k])
val k = j - acl.hostnames.size()
if (k < 0) holder.bind(acl.hostnames[j]) else holder.bind(acl.urls[k])
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = AclRuleViewHolder(LayoutInflater
.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false))
override fun getItemCount(): Int = acl.subnets.size() + acl.proxyHostnames.size() + acl.urls.size()
override fun getItemCount(): Int = acl.subnets.size() + acl.hostnames.size() + acl.urls.size()
override fun getSectionTitle(i: Int): String {
val j = i - acl.subnets.size()
return try {
(if (j < 0) acl.subnets[i].address.hostAddress.substring(0, 1) else {
val k = j - acl.proxyHostnames.size()
val k = j - acl.hostnames.size()
if (k < 0) {
val hostname = acl.proxyHostnames[j]
val hostname = acl.hostnames[j]
// don't convert IDN yet
PATTERN_DOMAIN.find(hostname)?.value?.replace("\\.", ".") ?: hostname
} else acl.urls[k].host
......@@ -157,7 +158,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
if (!savePending) {
savePending = true
list.post {
Acl.save(Acl.CUSTOM_RULES, acl)
Acl.customRules = acl
savePending = false
}
}
......@@ -179,9 +180,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
return index
}
fun addHostname(hostname: String): Int {
val old = acl.proxyHostnames.size()
val index = acl.subnets.size() + acl.proxyHostnames.add(hostname)
if (old != acl.proxyHostnames.size()) {
val old = acl.hostnames.size()
val index = acl.subnets.size() + acl.hostnames.add(hostname)
if (old != acl.hostnames.size()) {
notifyItemInserted(index)
apply()
}
......@@ -189,7 +190,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
}
fun addURL(url: URL): Int {
val old = acl.urls.size()
val index = acl.subnets.size() + acl.proxyHostnames.size() + acl.urls.add(url)
val index = acl.subnets.size() + acl.hostnames.size() + acl.urls.add(url)
if (old != acl.urls.size()) {
notifyItemInserted(index)
apply()
......@@ -201,7 +202,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
var result: Int? = null
if (acl.bypass) acl.subnets.asIterable().asSequence().map { addSubnet(it) }
.forEach { if (result == null) result = it }
(acl.proxyHostnames.asIterable().asSequence().map { addHostname(it) } +
(acl.hostnames.asIterable().asSequence().map { addHostname(it) } +
acl.urls.asIterable().asSequence().map { addURL(it) })
.forEach { if (result == null) result = it }
return result
......@@ -227,10 +228,10 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
undoManager.remove(Pair(i, acl.subnets[i]))
acl.subnets.removeItemAt(i)
} else {
val k = j - acl.proxyHostnames.size()
val k = j - acl.hostnames.size()
if (k < 0) {
undoManager.remove(Pair(j, acl.proxyHostnames[j]))
acl.proxyHostnames.removeItemAt(j)
undoManager.remove(Pair(j, acl.hostnames[j]))
acl.hostnames.removeItemAt(j)
} else {
undoManager.remove(Pair(k, acl.urls[k]))
acl.urls.removeItemAt(k)
......@@ -247,12 +248,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
apply()
}
is String -> {
notifyItemRemoved(acl.subnets.size() + acl.proxyHostnames.indexOf(item))
acl.proxyHostnames.remove(item)
notifyItemRemoved(acl.subnets.size() + acl.hostnames.indexOf(item))
acl.hostnames.remove(item)
apply()
}
is URL -> {
notifyItemRemoved(acl.subnets.size() + acl.proxyHostnames.size() + acl.urls.indexOf(item))
notifyItemRemoved(acl.subnets.size() + acl.hostnames.size() + acl.urls.indexOf(item))
acl.urls.remove(item)
apply()
}
......@@ -271,7 +272,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
fun selectAll() {
selectedItems.clear()
selectedItems.addAll(acl.subnets.asIterable())
selectedItems.addAll(acl.proxyHostnames.asIterable())
selectedItems.addAll(acl.hostnames.asIterable())
selectedItems.addAll(acl.urls.asIterable())
onSelectedItemsUpdated()
notifyDataSetChanged()
......@@ -333,8 +334,8 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (savedInstanceState != null) {
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_SUBNETS)?.map(Subnet.Companion::fromString)
?: listOf())
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_SUBNETS)
?.mapNotNull(Subnet.Companion::fromString) ?: listOf())
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_HOSTNAMES)
?: arrayOf())
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_URLS)?.map { URL(it) }
......@@ -355,7 +356,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
undoManager = UndoSnackbarManager(activity!!.findViewById(R.id.snackbar), adapter::undo)
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START or ItemTouchHelper.END) {
override fun getSwipeDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int =
if (isEnabled) super.getSwipeDirs(recyclerView, viewHolder) else 0
if (isEnabled && selectedItems.isEmpty()) super.getSwipeDirs(recyclerView, viewHolder) else 0
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) =
adapter.remove(viewHolder.adapterPosition)
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
......@@ -386,7 +387,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
selectedItems.forEach {
when (it) {
is Subnet -> acl.subnets.add(it)
is String -> acl.proxyHostnames.add(it)
is String -> acl.hostnames.add(it)
is URL -> acl.urls.add(it)
}
}
......@@ -432,10 +433,15 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
R.id.action_import_gfwlist -> {
val acl = Acl().fromId(Acl.GFWLIST)
if (!acl.bypass) acl.subnets.asIterable().forEach { adapter.addSubnet(it) }
acl.proxyHostnames.asIterable().forEach { adapter.addHostname(it) }
acl.hostnames.asIterable().forEach { adapter.addHostname(it) }
acl.urls.asIterable().forEach { adapter.addURL(it) }
true
}
else -> false
}
override fun onDetach() {
undoManager.flush()
super.onDetach()
}
}
......@@ -20,12 +20,15 @@
package com.github.shadowsocks.bg
import android.annotation.TargetApi
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.*
import android.text.TextUtils
import android.os.Build
import android.os.IBinder
import android.os.RemoteCallbackList
import android.support.v4.os.UserManagerCompat
import android.util.Base64
import android.util.Log
import android.widget.Toast
......@@ -66,6 +69,8 @@ object BaseService {
const val STOPPING = 3
const val STOPPED = 4
const val CONFIG_FILE = "shadowsocks.conf"
class Data internal constructor(private val service: Interface) {
@Volatile var profile: Profile? = null
@Volatile var state = STOPPED
......@@ -91,10 +96,8 @@ object BaseService {
}
var closeReceiverRegistered = false
private fun state() = state
val binder = object : IShadowsocksService.Stub() {
override fun getState(): Int = state()
override fun getState(): Int = this@Data.state
override fun getProfileName(): String = profile?.formattedName ?: "Idle"
override fun registerCallback(cb: IShadowsocksServiceCallback) {
......@@ -165,7 +168,8 @@ object BaseService {
}
}
internal fun buildShadowsocksConfig() {
internal var shadowsocksConfigFile: File? = null
internal fun buildShadowsocksConfig(): File {
val profile = profile!!
val config = JSONObject()
.put("server", profile.host)
......@@ -180,7 +184,30 @@ object BaseService {
.put("plugin", Commandline.toString(service.buildAdditionalArguments(pluginCmd)))
.put("plugin_opts", plugin.toString())
}
File(app.filesDir, "shadowsocks.json").bufferedWriter().use { it.write(config.toString()) }
// sensitive Shadowsocks config is stored in
val file = File((if (UserManagerCompat.isUserUnlocked(app)) app.filesDir else @TargetApi(24) {
app.deviceContext.noBackupFilesDir // only API 24+ will be in locked state
}), CONFIG_FILE)
shadowsocksConfigFile = file
file.writeText(config.toString())
return file
}
val aclFile: File? get() {
val route = profile!!.route
return if (route == Acl.ALL) null else Acl.getFile(route)
}
fun changeState(s: Int, msg: String? = null) {
if (state == s && msg == null) return
if (callbacks.registeredCallbackCount > 0) app.handler.post {
val n = callbacks.beginBroadcast()
for (i in 0 until n) try {
callbacks.getBroadcastItem(i).stateChanged(s, binder.profileName, msg)
} catch (_: Exception) { } // ignore
callbacks.finishBroadcast()
}
state = s
}
}
interface Interface {
......@@ -189,7 +216,7 @@ object BaseService {
fun onBind(intent: Intent): IBinder? = if (intent.action == Action.SERVICE) data.binder else null
fun checkProfile(profile: Profile): Boolean =
if (TextUtils.isEmpty(profile.host) || TextUtils.isEmpty(profile.password)) {
if (profile.host.isEmpty() || profile.password.isEmpty()) {
stopRunner(true, (this as Context).getString(R.string.proxy_empty))
false
} else true
......@@ -212,19 +239,18 @@ object BaseService {
fun startNativeProcesses() {
val data = data
data.buildShadowsocksConfig()
val cmd = buildAdditionalArguments(arrayListOf(
File((this as Context).applicationInfo.nativeLibraryDir, Executable.SS_LOCAL).absolutePath,
"-u",
"-b", "127.0.0.1",
"-l", DataStore.portProxy.toString(),
"-t", "600",
"-c", "shadowsocks.json"))
"-c", data.buildShadowsocksConfig().absolutePath))
val route = data.profile!!.route
if (route != Acl.ALL) {
val acl = data.aclFile
if (acl != null) {
cmd += "--acl"
cmd += Acl.getFile(if (route == Acl.CUSTOM_RULES) Acl.CUSTOM_RULES_FLATTENED else route).absolutePath
cmd += acl.absolutePath
}
if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
......@@ -232,7 +258,7 @@ object BaseService {
data.sslocalProcess = GuardedProcess(cmd).start()
}
fun createNotification(): ServiceNotification
fun createNotification(profileName: String): ServiceNotification
fun startRunner() {
this as Context
......@@ -248,20 +274,23 @@ object BaseService {
fun stopRunner(stopService: Boolean, msg: String? = null) {
// channge the state
changeState(STOPPING)
val data = data
data.changeState(STOPPING)
app.track(tag, "stop")
killProcesses()
// clean up recevier
val data = data
this as Service
if (data.closeReceiverRegistered) {
unregisterReceiver(data.closeReceiver)
data.closeReceiverRegistered = false
}
data.shadowsocksConfigFile?.delete() // remove old config possibly in device storage
data.shadowsocksConfigFile = null
data.notification?.destroy()
data.notification = null
......@@ -273,7 +302,7 @@ object BaseService {
data.trafficMonitorThread = null
// change the state
changeState(STOPPED, msg)
data.changeState(STOPPED, msg)
// stop the service if nothing has bound to it
if (stopService) stopSelf()
......@@ -287,12 +316,13 @@ object BaseService {
val data = data
if (data.state != STOPPED) return Service.START_NOT_STICKY
val profile = app.currentProfile
this as Context
if (profile == null) {
stopRunner(true)
data.notification = createNotification("") // gracefully shutdown: https://stackoverflow.com/questions/47337857/context-startforegroundservice-did-not-then-call-service-startforeground-eve
stopRunner(true, getString(R.string.profile_empty))
return Service.START_NOT_STICKY
}
data.profile = profile
profile.name = profile.formattedName
TrafficMonitor.reset()
val thread = TrafficMonitorThread()
......@@ -305,17 +335,16 @@ object BaseService {
filter.addAction(Action.RELOAD)
filter.addAction(Intent.ACTION_SHUTDOWN)
filter.addAction(Action.CLOSE)
(this as Context).registerReceiver(data.closeReceiver, filter)
registerReceiver(data.closeReceiver, filter)
data.closeReceiverRegistered = true
}
data.notification = createNotification()
data.notification = createNotification(profile.formattedName)
app.track(tag, "start")
changeState(CONNECTING)
data.changeState(CONNECTING)
thread {
this as Context
try {
if (profile.host == "198.199.101.152") {
val client = OkHttpClient.Builder()
......@@ -348,7 +377,7 @@ object BaseService {
}
if (profile.route == Acl.CUSTOM_RULES)
Acl.save(Acl.CUSTOM_RULES_FLATTENED, Acl.customRules.flatten(10))
Acl.save(Acl.CUSTOM_RULES, Acl.customRules.flatten(10))
data.plugin = PluginConfiguration(profile.plugin ?: "").selectedOptions
data.pluginPath = PluginManager.init(data.plugin)
......@@ -363,7 +392,7 @@ object BaseService {
if (profile.route !in arrayOf(Acl.ALL, Acl.CUSTOM_RULES)) AclSyncJob.schedule(profile.route)
changeState(CONNECTED)
data.changeState(CONNECTED)
} catch (_: UnknownHostException) {
stopRunner(true, getString(R.string.invalid_server))
} catch (_: VpnService.NullConnectionException) {
......@@ -375,19 +404,6 @@ object BaseService {
}
return Service.START_NOT_STICKY
}
fun changeState(s: Int, msg: String? = null) {
val data = instances[this]!!
if (data.state == s && msg == null) return
if (data.callbacks.registeredCallbackCount > 0) app.handler.post {
val n = data.callbacks.beginBroadcast()
for (i in 0 until n) try {
data.callbacks.getBroadcastItem(i).stateChanged(s, data.binder.profileName, msg)
} catch (_: Exception) { } // ignore
data.callbacks.finishBroadcast()
}
data.state = s
}
}
private val instances = WeakHashMap<Interface, Data>()
......
......@@ -20,49 +20,19 @@
package com.github.shadowsocks.bg
import android.content.Context
import android.net.ConnectivityManager
import android.net.LinkProperties
import android.os.Build
import android.util.Log
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.BuildConfig
import okhttp3.Dns as Okdns
import org.xbill.DNS.*
import java.net.Inet6Address
import java.net.InetAddress
import java.net.NetworkInterface
import java.net.UnknownHostException
import java.util.*
import okhttp3.Dns as Okdns
object Dns {
private const val TAG = "Dns"
@Throws(Exception::class)
fun getDnsResolver(context: Context): String {
val dnsResolvers = getDnsResolvers(context)
if (dnsResolvers.isEmpty()) throw Exception("Couldn't find an active DNS resolver")
val dnsResolver = dnsResolvers.iterator().next().toString()
if (dnsResolver.startsWith("/")) return dnsResolver.substring(1)
return dnsResolver
}
@Throws(Exception::class)
private fun getDnsResolvers(context: Context): Collection<InetAddress> {
val addresses = ArrayList<InetAddress>()
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val classLinkProperties = Class.forName("android.net.LinkProperties")
val getActiveLinkPropertiesMethod = ConnectivityManager::class.java.getMethod("getActiveLinkProperties")
val linkProperties = getActiveLinkPropertiesMethod.invoke(connectivityManager)
if (linkProperties != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
val dnses = classLinkProperties.getMethod("getDnses").invoke(linkProperties) as Collection<*>
dnses.mapTo(addresses) { it as InetAddress }
} else addresses.addAll((linkProperties as LinkProperties).dnsServers)
}
return addresses
}
private val hasIPv6Support get() = try {
val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() }
.count { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } > 0
......
......@@ -37,8 +37,7 @@ object Executable {
fun killAll() {
for (process in File("/proc").listFiles { _, name -> TextUtils.isDigitsOnly(name) }) {
val exe = File(File(process, "cmdline").bufferedReader().use { it.readText() }
.split(Character.MIN_VALUE, limit = 2).first())
val exe = File(File(process, "cmdline").readText().split(Character.MIN_VALUE, limit = 2).first())
if (exe.parent == app.applicationInfo.nativeLibraryDir && EXECUTABLES.contains(exe.name)) {
val errno = JniHelper.sigkill(process.name.toInt())
if (errno != 0) Log.w("kill", "SIGKILL ${exe.absolutePath} (${process.name}) failed with $errno")
......
......@@ -62,7 +62,7 @@ class GuardedProcess(private val cmd: List<String>) {
process = ProcessBuilder(cmd)
.redirectErrorStream(true)
.directory(app.filesDir)
.directory(app.deviceContext.filesDir)
.start()
streamLogger(process.inputStream, Log::i)
......
......@@ -44,6 +44,7 @@ object LocalDnsService {
override fun startNativeProcesses() {
super.startNativeProcesses()
val data = data
val profile = data.profile!!
fun makeDns(name: String, address: String, edns: Boolean = true): JSONObject {
......@@ -53,7 +54,7 @@ object LocalDnsService {
is Inet6Address -> "[$address]"
else -> address
}) + ":53")
.put("Timeout", 6)
.put("Timeout", 3)
.put("EDNSClientSubnet", JSONObject().put("Policy", "disable"))
if (edns) dns
.put("Protocol", "tcp")
......@@ -67,9 +68,9 @@ object LocalDnsService {
val config = JSONObject()
.put("BindAddress", "127.0.0.1:" + DataStore.portLocalDns)
.put("RedirectIPv6Record", true)
.put("DomainBase64Decode", true)
.put("DomainBase64Decode", false)
.put("HostsFile", "hosts")
.put("MinimumTTL", 3600)
.put("MinimumTTL", 120)
.put("CacheSize", 4096)
val remoteDns = JSONArray(profile.remoteDns.split(",")
.mapIndexed { i, dns -> makeDns("UserDef-" + i, dns.trim()) })
......@@ -78,18 +79,12 @@ object LocalDnsService {
makeDns("Primary-2", "114.114.114.114", false)
))
this as Context
try {
val localLinkDns = Dns.getDnsResolver(this)
localDns.put(makeDns("Primary-3", localLinkDns, false))
} catch (_: Exception) { } // ignore
when (profile.route) {
Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> config
.put("PrimaryDNS", localDns)
.put("AlternativeDNS", remoteDns)
.put("IPNetworkFile", "china_ip_list.txt")
.put("DomainFile", "gfwlist.txt")
.put("DomainFile", data.aclFile!!.absolutePath)
Acl.CHINALIST -> config
.put("PrimaryDNS", localDns)
.put("AlternativeDNS", remoteDns)
......@@ -98,7 +93,7 @@ object LocalDnsService {
// no need to setup AlternativeDNS in Acl.ALL/BYPASS_LAN mode
.put("OnlyPrimaryDNS", true)
}
File(filesDir, file).bufferedWriter().use { it.write(config.toString()) }
File(app.deviceContext.filesDir, file).writeText(config.toString())
return file
}
......
......@@ -41,7 +41,9 @@ abstract class LocalSocketListener(protected val tag: String) : Thread() {
* Inherited class do not need to close input/output streams as they will be closed automatically.
*/
protected abstract fun accept(socket: LocalSocket)
override final fun run() = LocalSocket().use { localSocket ->
override final fun run() {
socketFile.delete() // It's a must-have to close and reuse previous local socket.
LocalSocket().use { localSocket ->
val serverSocket = try {
localSocket.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
LocalServerSocket(localSocket.fileDescriptor)
......@@ -59,6 +61,7 @@ abstract class LocalSocketListener(protected val tag: String) : Thread() {
}?.use(this::accept)
}
}
}
fun stopThread() {
running = false
......
......@@ -23,6 +23,7 @@ package com.github.shadowsocks.bg
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.github.shadowsocks.database.Profile
/**
* Shadowsocks service at its minimum.
......@@ -33,8 +34,8 @@ class ProxyService : Service(), BaseService.Interface {
}
override val tag: String get() = "ShadowsocksProxyService"
override fun createNotification(): ServiceNotification =
ServiceNotification(this, data.profile!!.formattedName, "service-proxy", true)
override fun createNotification(profileName: String): ServiceNotification =
ServiceNotification(this, profileName, "service-proxy", true)
override fun onBind(intent: Intent): IBinder? = super.onBind(intent)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int =
......
......@@ -38,6 +38,12 @@ import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.broadcastReceiver
import java.util.*
/**
* Android < 8 VPN: always invisible because of VPN notification/icon
* Android < 8 other: only invisible in (possibly unsecure) lockscreen
* Android 8+: always visible due to system limitations
* (user can choose to hide the notification in secure lockscreen or anywhere)
*/
class ServiceNotification(private val service: BaseService.Interface, profileName: String,
channel: String, private val visible: Boolean = false) {
private val keyGuard = (service as Context).getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
......@@ -69,7 +75,7 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
.setContentTitle(profileName)
.setContentIntent(PendingIntent.getActivity(service, 0, Intent(service, MainActivity::class.java)
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), 0))
.setSmallIcon(R.drawable.ic_start_connected)
.setSmallIcon(R.drawable.ic_service_active)
private val style = NotificationCompat.BigTextStyle(builder)
private var isVisible = true
......@@ -78,24 +84,22 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close,
service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0))
val power = service.getSystemService(Context.POWER_SERVICE) as PowerManager
update(if (if (Build.VERSION.SDK_INT >= 20) power.isInteractive else @Suppress("DEPRECATION") power.isScreenOn)
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
update(if (power.isInteractive) Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
val screenFilter = IntentFilter()
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
if (visible && Build.VERSION.SDK_INT in 21 until 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
if (visible && Build.VERSION.SDK_INT < 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
service.registerReceiver(lockReceiver, screenFilter)
}
private fun update(action: String, forceShow: Boolean = false) {
if (forceShow || service.data.state == BaseService.CONNECTED) when (action) {
Intent.ACTION_SCREEN_OFF -> {
setVisible(visible && Build.VERSION.SDK_INT < 21, forceShow)
setVisible(false, forceShow)
unregisterCallback() // unregister callback to save battery
}
Intent.ACTION_SCREEN_ON -> {
setVisible(visible && (Build.VERSION.SDK_INT < 21 || !keyGuard.inKeyguardRestrictedInputMode()),
forceShow)
setVisible(visible && !keyGuard.inKeyguardRestrictedInputMode(), forceShow)
service.data.binder.registerCallback(callback)
service.data.binder.startListeningForBandwidth(callback)
callbackRegistered = true
......
......@@ -20,8 +20,9 @@
package com.github.shadowsocks.bg
import android.app.KeyguardManager
import android.content.Context
import android.graphics.drawable.Icon
import android.os.Build
import android.service.quicksettings.Tile
import android.support.annotation.RequiresApi
import com.github.shadowsocks.App.Companion.app
......@@ -31,34 +32,35 @@ import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import android.service.quicksettings.TileService as BaseTileService
@RequiresApi(Build.VERSION_CODES.N)
@RequiresApi(24)
class TileService : BaseTileService(), ShadowsocksConnection.Interface {
private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_start_idle).setTint(0x79ffffff) }
private val iconBusy by lazy { Icon.createWithResource(this, R.drawable.ic_start_busy) }
private val iconConnected by lazy { Icon.createWithResource(this, R.drawable.ic_start_connected) }
private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_service_idle).setTint(0x79ffffff) }
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 keyguard by lazy { getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager }
override val serviceCallback: IShadowsocksServiceCallback.Stub by lazy {
@RequiresApi(Build.VERSION_CODES.N)
@RequiresApi(24)
object : IShadowsocksServiceCallback.Stub() {
override fun stateChanged(state: Int, profileName: String?, msg: String?) {
val tile = qsTile ?: return
var label: String? = null
when (state) {
BaseService.STOPPED -> {
tile.icon = iconIdle
tile.label = getString(R.string.app_name)
tile.state = Tile.STATE_INACTIVE
}
BaseService.CONNECTED -> {
tile.icon = iconConnected
tile.label = profileName ?: getString(R.string.app_name)
if (!keyguard.isDeviceLocked) label = profileName
tile.state = Tile.STATE_ACTIVE
}
else -> {
tile.icon = iconBusy
tile.label = getString(R.string.app_name)
tile.state = Tile.STATE_UNAVAILABLE
}
}
tile.label = label ?: getString(R.string.app_name)
tile.updateTile()
}
override fun trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) { }
......
......@@ -29,7 +29,7 @@ import java.nio.ByteBuffer
import java.nio.ByteOrder
class TrafficMonitorThread : LocalSocketListener("TrafficMonitorThread") {
override val socketFile = File(app.filesDir, "/stat_path")
override val socketFile = File(app.deviceContext.filesDir, "stat_path")
override fun accept(socket: LocalSocket) {
try {
......
......@@ -23,6 +23,7 @@ package com.github.shadowsocks.bg
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.preference.DataStore
import java.io.File
......@@ -32,8 +33,8 @@ class TransproxyService : Service(), LocalDnsService.Interface {
}
override val tag: String get() = "ShadowsocksTransproxyService"
override fun createNotification(): ServiceNotification =
ServiceNotification(this, data.profile!!.formattedName, "service-transproxy", true)
override fun createNotification(profileName: String): ServiceNotification =
ServiceNotification(this, profileName, "service-transproxy", true)
override fun onBind(intent: Intent): IBinder? = super.onBind(intent)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int =
......@@ -49,12 +50,12 @@ class TransproxyService : Service(), LocalDnsService.Interface {
"-u",
"-l", DataStore.portLocalDns.toString(), // ss-tunnel listens on the same port as overture
"-L", data.profile!!.remoteDns.split(",").first().trim() + ":53",
"-c", "shadowsocks.json") // config is already built by BaseService.Interface
"-c", data.shadowsocksConfigFile!!.absolutePath) // config is already built by BaseService.Interface
sstunnelProcess = GuardedProcess(cmd).start()
}
private fun startRedsocksDaemon() {
val config = """base {
File(app.deviceContext.filesDir, "redsocks.conf").writeText("""base {
log_debug = off;
log_info = off;
log = stderr;
......@@ -68,8 +69,7 @@ redsocks {
port = ${DataStore.portProxy};
type = socks5;
}
"""
File(filesDir, "redsocks.conf").bufferedWriter().use { it.write(config) }
""")
redsocksProcess = GuardedProcess(arrayListOf(
File(applicationInfo.nativeLibraryDir, Executable.REDSOCKS).absolutePath,
"-c", "redsocks.conf")
......
......@@ -24,7 +24,6 @@ import android.app.Service
import android.content.Intent
import android.content.pm.PackageManager
import android.net.LocalSocket
import android.os.Build
import android.os.IBinder
import android.os.ParcelFileDescriptor
import android.util.Log
......@@ -52,7 +51,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
}
private inner class ProtectWorker : LocalSocketListener("ShadowsocksVpnThread") {
override val socketFile: File = File(filesDir, "protect_path")
override val socketFile: File = File(app.deviceContext.filesDir, "protect_path")
override fun accept(socket: LocalSocket) {
try {
......@@ -76,8 +75,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
}
override val tag: String get() = "ShadowsocksVpnService"
override fun createNotification(): ServiceNotification =
ServiceNotification(this, data.profile!!.formattedName, "service-vpn")
override fun createNotification(profileName: String): ServiceNotification =
ServiceNotification(this, profileName, "service-vpn")
private var conn: ParcelFileDescriptor? = null
private var worker: ProtectWorker? = null
......@@ -140,22 +139,29 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
builder.addRoute("::", 0)
}
if (Build.VERSION.SDK_INT >= 21 && profile.proxyApps) {
for (pkg in profile.individual.split('\n')) try {
if (profile.bypass) builder.addDisallowedApplication(pkg) else builder.addAllowedApplication(pkg)
if (profile.proxyApps) {
val me = packageName
profile.individual.split('\n')
.filter { it != me }
.forEach {
try {
if (profile.bypass) builder.addDisallowedApplication(it)
else builder.addAllowedApplication(it)
} catch (ex: PackageManager.NameNotFoundException) {
Log.e(tag, "Invalid package name", ex)
}
}
if (!profile.bypass) builder.addAllowedApplication(me)
}
when (profile.route) {
Acl.ALL, Acl.BYPASS_CHN, Acl.CUSTOM_RULES -> builder.addRoute("0.0.0.0", 0)
else -> {
resources.getStringArray(R.array.bypass_private_route).forEach {
val subnet = Subnet.fromString(it)
val subnet = Subnet.fromString(it)!!
builder.addRoute(subnet.address.hostAddress, subnet.prefixSize)
}
profile.remoteDns.split(",").map { it.trim().parseNumericAddress() }
profile.remoteDns.split(",").mapNotNull { it.trim().parseNumericAddress() }
.forEach { builder.addRoute(it, it.address.size shl 3) }
}
}
......@@ -187,10 +193,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private fun sendFd(fd: Int): Boolean {
if (fd != -1) {
var tries = 1
while (tries < 5) {
Thread.sleep(1000L * tries)
if (JniHelper.sendFd(fd, File(filesDir, "sock_path").absolutePath) != -1) return true
var tries = 0
while (tries < 10) {
Thread.sleep(30L shl tries)
if (JniHelper.sendFd(fd, File(app.deviceContext.filesDir, "sock_path").absolutePath) != -1) return true
tries += 1
}
}
......
......@@ -53,7 +53,7 @@ class KeyValuePair() {
get() = if (valueType == TYPE_LONG) ByteBuffer.wrap(value).long else null
val string: String?
get() = if (valueType == TYPE_STRING) String(value) else null
val stringSet: MutableSet<String>?
val stringSet: Set<String>?
get() = if (valueType == TYPE_STRING_SET) {
val buffer = ByteBuffer.wrap(value)
val result = HashSet<String>()
......@@ -95,7 +95,7 @@ class KeyValuePair() {
this.value = value.toByteArray()
return this
}
fun put(value: MutableSet<String>): KeyValuePair {
fun put(value: Set<String>): KeyValuePair {
valueType = TYPE_STRING_SET
val stream = ByteArrayOutputStream()
for (v in value) {
......
......@@ -31,7 +31,7 @@ import com.j256.ormlite.dao.Dao
import com.j256.ormlite.support.ConnectionSource
import com.j256.ormlite.table.TableUtils
object DBHelper : OrmLiteSqliteOpenHelper(app, Key.PROFILE, null, 24) {
object PrivateDatabase : OrmLiteSqliteOpenHelper(app, Key.DB_PROFILE, null, 25) {
@Suppress("UNCHECKED_CAST")
val profileDao: Dao<Profile, Int> by lazy { getDao(Profile::class.java) as Dao<Profile, Int> }
@Suppress("UNCHECKED_CAST")
......@@ -134,8 +134,12 @@ object DBHelper : OrmLiteSqliteOpenHelper(app, Key.PROFILE, null, 24) {
TableUtils.createTable(connectionSource, KeyValuePair::class.java)
profileDao.executeRawNoArgs("COMMIT;")
val old = PreferenceManager.getDefaultSharedPreferences(app)
kvPairDao.createOrUpdate(KeyValuePair(Key.id).put(old.getInt(Key.id, 0)))
kvPairDao.createOrUpdate(KeyValuePair(Key.tfo).put(old.getBoolean(Key.tfo, false)))
PublicDatabase.kvPairDao.createOrUpdate(KeyValuePair(Key.id).put(old.getInt(Key.id, 0)))
PublicDatabase.kvPairDao.createOrUpdate(KeyValuePair(Key.tfo).put(old.getBoolean(Key.tfo, false)))
}
if (oldVersion < 25) {
PublicDatabase.onUpgrade(database, 0, -1)
}
} catch (ex: Exception) {
app.track(ex)
......
......@@ -29,10 +29,11 @@ import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.parsePort
import com.j256.ormlite.field.DataType
import com.j256.ormlite.field.DatabaseField
import java.io.Serializable
import java.net.URI
import java.util.*
class Profile {
class Profile : Serializable {
companion object {
private const val TAG = "ShadowParser"
private val pattern = """(?i)ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;\[\]]*[-a-zA-Z0-9+&@#/%=~_|\[\]]""".toRegex()
......@@ -153,34 +154,34 @@ class Profile {
override fun toString() = toUri().toString()
fun serialize() {
DataStore.putString(Key.name, name)
DataStore.putString(Key.host, host)
DataStore.putString(Key.remotePort, remotePort.toString())
DataStore.putString(Key.password, password)
DataStore.putString(Key.route, route)
DataStore.putString(Key.remoteDns, remoteDns)
DataStore.putString(Key.method, method)
DataStore.privateStore.putString(Key.name, name)
DataStore.privateStore.putString(Key.host, host)
DataStore.privateStore.putString(Key.remotePort, remotePort.toString())
DataStore.privateStore.putString(Key.password, password)
DataStore.privateStore.putString(Key.route, route)
DataStore.privateStore.putString(Key.remoteDns, remoteDns)
DataStore.privateStore.putString(Key.method, method)
DataStore.proxyApps = proxyApps
DataStore.bypass = bypass
DataStore.putBoolean(Key.udpdns, udpdns)
DataStore.putBoolean(Key.ipv6, ipv6)
DataStore.privateStore.putBoolean(Key.udpdns, udpdns)
DataStore.privateStore.putBoolean(Key.ipv6, ipv6)
DataStore.individual = individual
DataStore.plugin = plugin ?: ""
DataStore.remove(Key.dirty)
DataStore.privateStore.remove(Key.dirty)
}
fun deserialize() {
// It's assumed that default values are never used, so 0/false/null is always used even if that isn't the case
name = DataStore.getString(Key.name) ?: ""
host = DataStore.getString(Key.host) ?: ""
remotePort = parsePort(DataStore.getString(Key.remotePort), 8388, 1)
password = DataStore.getString(Key.password) ?: ""
method = DataStore.getString(Key.method) ?: ""
route = DataStore.getString(Key.route) ?: ""
remoteDns = DataStore.getString(Key.remoteDns) ?: ""
name = DataStore.privateStore.getString(Key.name) ?: ""
host = DataStore.privateStore.getString(Key.host) ?: ""
remotePort = parsePort(DataStore.privateStore.getString(Key.remotePort), 8388, 1)
password = DataStore.privateStore.getString(Key.password) ?: ""
method = DataStore.privateStore.getString(Key.method) ?: ""
route = DataStore.privateStore.getString(Key.route) ?: ""
remoteDns = DataStore.privateStore.getString(Key.remoteDns) ?: ""
proxyApps = DataStore.proxyApps
bypass = DataStore.bypass
udpdns = DataStore.getBoolean(Key.udpdns, false)
ipv6 = DataStore.getBoolean(Key.ipv6, false)
udpdns = DataStore.privateStore.getBoolean(Key.udpdns, false)
ipv6 = DataStore.privateStore.getBoolean(Key.ipv6, false)
individual = DataStore.individual
plugin = DataStore.plugin
}
......
......@@ -23,6 +23,8 @@ package com.github.shadowsocks.database
import android.util.Log
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.ProfilesFragment
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot
object ProfileManager {
private const val TAG = "ProfileManager"
......@@ -41,10 +43,10 @@ object ProfileManager {
profile.individual = oldProfile.individual
profile.udpdns = oldProfile.udpdns
}
val last = DBHelper.profileDao.queryRaw(DBHelper.profileDao.queryBuilder().selectRaw("MAX(userOrder)")
.prepareStatementString()).firstResult
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
DBHelper.profileDao.createOrUpdate(profile)
PrivateDatabase.profileDao.createOrUpdate(profile)
ProfilesFragment.instance?.profilesAdapter?.add(profile)
} catch (ex: Exception) {
Log.e(TAG, "addProfile", ex)
......@@ -53,8 +55,11 @@ object ProfileManager {
return profile
}
/**
* Note: It's caller's responsibility to update DirectBoot profile if necessary.
*/
fun updateProfile(profile: Profile): Boolean = try {
DBHelper.profileDao.update(profile)
PrivateDatabase.profileDao.update(profile)
true
} catch (ex: Exception) {
Log.e(TAG, "updateProfile", ex)
......@@ -63,7 +68,7 @@ object ProfileManager {
}
fun getProfile(id: Int): Profile? = try {
DBHelper.profileDao.queryForId(id)
PrivateDatabase.profileDao.queryForId(id)
} catch (ex: Exception) {
Log.e(TAG, "getProfile", ex)
app.track(ex)
......@@ -71,8 +76,9 @@ object ProfileManager {
}
fun delProfile(id: Int): Boolean = try {
DBHelper.profileDao.deleteById(id)
PrivateDatabase.profileDao.deleteById(id)
ProfilesFragment.instance?.profilesAdapter?.removeId(id)
if (id == DataStore.profileId && DataStore.directBootAware) DirectBoot.clean()
true
} catch (ex: Exception) {
Log.e(TAG, "delProfile", ex)
......@@ -81,7 +87,7 @@ object ProfileManager {
}
fun getFirstProfile(): Profile? = try {
val result = DBHelper.profileDao.query(DBHelper.profileDao.queryBuilder().limit(1L).prepare())
val result = PrivateDatabase.profileDao.query(PrivateDatabase.profileDao.queryBuilder().limit(1L).prepare())
if (result.size == 1) result[0] else null
} catch (ex: Exception) {
Log.e(TAG, "getAllProfiles", ex)
......@@ -90,7 +96,7 @@ object ProfileManager {
}
fun getAllProfiles(): List<Profile>? = try {
DBHelper.profileDao.query(DBHelper.profileDao.queryBuilder().orderBy("userOrder", true).prepare())
PrivateDatabase.profileDao.query(PrivateDatabase.profileDao.queryBuilder().orderBy("userOrder", true).prepare())
} catch (ex: Exception) {
Log.e(TAG, "getAllProfiles", ex)
app.track(ex)
......
/*******************************************************************************
* *
* 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.SQLiteDatabase
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.utils.Key
import com.j256.ormlite.android.AndroidDatabaseConnection
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper
import com.j256.ormlite.dao.Dao
import com.j256.ormlite.support.ConnectionSource
import com.j256.ormlite.table.TableUtils
object PublicDatabase : OrmLiteSqliteOpenHelper(app.deviceContext, Key.DB_PUBLIC, null, 2) {
@Suppress("UNCHECKED_CAST")
val kvPairDao: Dao<KeyValuePair, String?> by lazy { getDao(KeyValuePair::class.java) as Dao<KeyValuePair, String?> }
override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) {
TableUtils.createTable(connectionSource, KeyValuePair::class.java)
}
override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?,
oldVersion: Int, newVersion: Int) {
if (oldVersion < 1) {
PrivateDatabase.kvPairDao.queryBuilder().where().`in`("key",
Key.id, Key.tfo, Key.serviceMode, Key.portProxy, Key.portLocalDns, Key.portTransproxy).query()
.forEach { kvPairDao.createOrUpdate(it) }
}
if (oldVersion < 2) {
kvPairDao.createOrUpdate(KeyValuePair(Acl.CUSTOM_RULES).put(Acl().fromId(Acl.CUSTOM_RULES).toString()))
}
}
override fun onDowngrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
val connection = AndroidDatabaseConnection(db, true)
connectionSource.saveSpecialConnection(connection)
TableUtils.dropTable<KeyValuePair, String?>(connectionSource, KeyValuePair::class.java, true)
onCreate(db, connectionSource)
connectionSource.clearSpecialConnection(connection)
}
}
......@@ -50,7 +50,7 @@ class PluginConfiguration(val pluginsOptions: Map<String, PluginOptions>, val se
})
fun getOptions(id: String): PluginOptions = if (id.isEmpty()) PluginOptions() else
pluginsOptions.get(id) ?: PluginOptions(id, PluginManager.fetchPlugins()[id]?.defaultConfig)
pluginsOptions[id] ?: PluginOptions(id, PluginManager.fetchPlugins()[id]?.defaultConfig)
val selectedOptions: PluginOptions get() = getOptions(selected)
override fun toString(): String {
......
......@@ -157,7 +157,7 @@ object PluginManager {
var initialized = false
fun entryNotFound(): Nothing = throw IndexOutOfBoundsException("Plugin entry binary not found")
val list = ArrayList<String>()
val pluginDir = File(app.filesDir, "plugin")
val pluginDir = File(app.deviceContext.filesDir, "plugin")
(cr.query(uri, arrayOf(PluginContract.COLUMN_PATH, PluginContract.COLUMN_MODE), null, null, null)
?: return null).use { cursor ->
if (!cursor.moveToFirst()) entryNotFound()
......
......@@ -29,6 +29,7 @@ import android.os.Bundle
import android.provider.Settings
import android.support.design.widget.BottomSheetDialog
import android.support.v7.preference.PreferenceDialogFragmentCompat
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
......@@ -103,12 +104,16 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
val activity = activity
val dialog = BottomSheetDialog(activity!!, theme)
val recycler = RecyclerView(activity)
val padding = resources.getDimensionPixelOffset(R.dimen.bottom_sheet_padding)
recycler.setPadding(0, padding, 0, padding)
recycler.setHasFixedSize(true)
recycler.layoutManager = LinearLayoutManager(activity)
recycler.itemAnimator = DefaultItemAnimator()
recycler.adapter = IconListAdapter(dialog)
recycler.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
dialog.setContentView(recycler)
dialog.findViewById<View>(R.id.touch_outside)!!.isFocusable = false
return dialog
}
......
......@@ -21,115 +21,72 @@
package com.github.shadowsocks.preference
import android.os.Binder
import android.support.v7.preference.PreferenceDataStore
import com.github.shadowsocks.database.DBHelper
import com.github.shadowsocks.database.KeyValuePair
import com.github.shadowsocks.BootReceiver
import com.github.shadowsocks.database.PrivateDatabase
import com.github.shadowsocks.database.PublicDatabase
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.parsePort
import java.util.*
@Suppress("MemberVisibilityCanPrivate", "unused")
object DataStore : PreferenceDataStore() {
fun getBoolean(key: String?) = DBHelper.kvPairDao.queryForId(key)?.boolean
fun getFloat(key: String?) = DBHelper.kvPairDao.queryForId(key)?.float
fun getInt(key: String?) = DBHelper.kvPairDao.queryForId(key)?.int
fun getLong(key: String?) = DBHelper.kvPairDao.queryForId(key)?.long
fun getString(key: String?) = DBHelper.kvPairDao.queryForId(key)?.string
fun getStringSet(key: String?) = DBHelper.kvPairDao.queryForId(key)?.stringSet
override fun getBoolean(key: String?, defValue: Boolean) = getBoolean(key) ?: defValue
override fun getFloat(key: String?, defValue: Float) = getFloat(key) ?: defValue
override fun getInt(key: String?, defValue: Int) = getInt(key) ?: defValue
override fun getLong(key: String?, defValue: Long) = getLong(key) ?: defValue
override fun getString(key: String?, defValue: String?) = getString(key) ?: defValue
override fun getStringSet(key: String?, defValue: MutableSet<String>?) = getStringSet(key) ?: defValue
fun putBoolean(key: String?, value: Boolean?) = if (value == null) remove(key) else putBoolean(key, value)
fun putFloat(key: String?, value: Float?) = if (value == null) remove(key) else putFloat(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)
override fun putBoolean(key: String?, value: Boolean) {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putFloat(key: String?, value: Float) {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putInt(key: String?, value: Int) {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putLong(key: String?, value: Long) {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putString(key: String?, value: String?) = if (value == null) remove(key) else {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putStringSet(key: String?, values: MutableSet<String>?) = if (values == null) remove(key) else {
DBHelper.kvPairDao.createOrUpdate(KeyValuePair(key).put(values))
fireChangeListener(key)
}
fun remove(key: String?) {
DBHelper.kvPairDao.deleteById(key)
fireChangeListener(key)
}
private val listeners = HashSet<OnPreferenceDataStoreChangeListener>()
private fun fireChangeListener(key: String?) = listeners.forEach { it.onPreferenceDataStoreChanged(this, key) }
fun registerChangeListener(listener: OnPreferenceDataStoreChangeListener) = listeners.add(listener)
fun unregisterChangeListener(listener: OnPreferenceDataStoreChangeListener) = listeners.remove(listener)
object DataStore {
val publicStore = OrmLitePreferenceDataStore(PublicDatabase.kvPairDao)
// privateStore will only be used as temp storage for ProfileConfigFragment
val privateStore = OrmLitePreferenceDataStore(PrivateDatabase.kvPairDao)
// hopefully hashCode = mHandle doesn't change, currently this is true from KitKat to Nougat
private val userIndex by lazy { Binder.getCallingUserHandle().hashCode() }
private fun getLocalPort(key: String, default: Int): Int {
val value = getInt(key)
val value = publicStore.getInt(key)
return if (value != null) {
putString(key, value.toString())
publicStore.putString(key, value.toString())
value
} else parsePort(getString(key), default + userIndex)
} else parsePort(publicStore.getString(key), default + userIndex)
}
var profileId: Int
get() = getInt(Key.id) ?: 0
set(value) = putInt(Key.id, value)
get() = publicStore.getInt(Key.id) ?: 0
set(value) {
publicStore.putInt(Key.id, value)
if (DataStore.directBootAware) DirectBoot.update()
}
/**
* Setter is defined in MainActivity.onPreferenceDataStoreChanged.
*/
val directBootAware: Boolean get() = BootReceiver.enabled && (publicStore.getBoolean(Key.directBootAware) ?: false)
var serviceMode: String
get() = getString(Key.serviceMode) ?: Key.modeVpn
set(value) = putString(Key.serviceMode, value)
get() = publicStore.getString(Key.serviceMode) ?: Key.modeVpn
set(value) = publicStore.putString(Key.serviceMode, value)
var portProxy: Int
get() = getLocalPort(Key.portProxy, 1080)
set(value) = putString(Key.portProxy, value.toString())
set(value) = publicStore.putString(Key.portProxy, value.toString())
var portLocalDns: Int
get() = getLocalPort(Key.portLocalDns, 5450)
set(value) = putString(Key.portLocalDns, value.toString())
set(value) = publicStore.putString(Key.portLocalDns, value.toString())
var portTransproxy: Int
get() = getLocalPort(Key.portTransproxy, 8200)
set(value) = putString(Key.portTransproxy, value.toString())
set(value) = publicStore.putString(Key.portTransproxy, value.toString())
fun initGlobal() {
// temporary workaround for support lib bug
if (publicStore.getString(Key.serviceMode) == null) serviceMode = serviceMode
if (publicStore.getString(Key.portProxy) == null) portProxy = portProxy
if (publicStore.getString(Key.portLocalDns) == null) portLocalDns = portLocalDns
if (publicStore.getString(Key.portTransproxy) == null) portTransproxy = portTransproxy
}
var proxyApps: Boolean
get() = getBoolean(Key.proxyApps) ?: false
set(value) = putBoolean(Key.proxyApps, value)
get() = privateStore.getBoolean(Key.proxyApps) ?: false
set(value) = privateStore.putBoolean(Key.proxyApps, value)
var bypass: Boolean
get() = getBoolean(Key.bypass) ?: false
set(value) = putBoolean(Key.bypass, value)
get() = privateStore.getBoolean(Key.bypass) ?: false
set(value) = privateStore.putBoolean(Key.bypass, value)
var individual: String
get() = getString(Key.individual) ?: ""
set(value) = putString(Key.individual, value)
get() = privateStore.getString(Key.individual) ?: ""
set(value) = privateStore.putString(Key.individual, value)
var plugin: String
get() = getString(Key.plugin) ?: ""
set(value) = putString(Key.plugin, value)
get() = privateStore.getString(Key.plugin) ?: ""
set(value) = privateStore.putString(Key.plugin, value)
var dirty: Boolean
get() = getBoolean(Key.dirty) ?: false
set(value) = putBoolean(Key.dirty, value)
fun initGlobal() {
// temporary workaround for support lib bug
if (getString(Key.serviceMode) == null) serviceMode = serviceMode
if (getString(Key.portProxy) == null) portProxy = portProxy
if (getString(Key.portLocalDns) == null) portLocalDns = portLocalDns
if (getString(Key.portTransproxy) == null) portTransproxy = portTransproxy
}
get() = privateStore.getBoolean(Key.dirty) ?: false
set(value) = privateStore.putBoolean(Key.dirty, value)
}
/*******************************************************************************
* *
* 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.preference
import android.support.v7.preference.PreferenceDataStore
import com.github.shadowsocks.database.KeyValuePair
import com.j256.ormlite.dao.Dao
import java.util.HashSet
@Suppress("MemberVisibilityCanPrivate", "unused")
open class OrmLitePreferenceDataStore(private val kvPairDao: Dao<KeyValuePair, String?>) : PreferenceDataStore() {
fun getBoolean(key: String?) = kvPairDao.queryForId(key)?.boolean
fun getFloat(key: String?) = kvPairDao.queryForId(key)?.float
fun getInt(key: String?) = kvPairDao.queryForId(key)?.int
fun getLong(key: String?) = kvPairDao.queryForId(key)?.long
fun getString(key: String?) = kvPairDao.queryForId(key)?.string
fun getStringSet(key: String?) = kvPairDao.queryForId(key)?.stringSet
override fun getBoolean(key: String?, defValue: Boolean) = getBoolean(key) ?: defValue
override fun getFloat(key: String?, defValue: Float) = getFloat(key) ?: defValue
override fun getInt(key: String?, defValue: Int) = getInt(key) ?: defValue
override fun getLong(key: String?, defValue: Long) = getLong(key) ?: defValue
override fun getString(key: String?, defValue: String?) = getString(key) ?: defValue
override fun getStringSet(key: String?, defValue: MutableSet<String>?) = getStringSet(key) ?: defValue
fun putBoolean(key: String?, value: Boolean?) = if (value == null) remove(key) else putBoolean(key, value)
fun putFloat(key: String?, value: Float?) = if (value == null) remove(key) else putFloat(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)
override fun putBoolean(key: String?, value: Boolean) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putFloat(key: String?, value: Float) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putInt(key: String?, value: Int) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putLong(key: String?, value: Long) {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putString(key: String?, value: String?) = if (value == null) remove(key) else {
kvPairDao.createOrUpdate(KeyValuePair(key).put(value))
fireChangeListener(key)
}
override fun putStringSet(key: String?, values: MutableSet<String>?) = if (values == null) remove(key) else {
kvPairDao.createOrUpdate(KeyValuePair(key).put(values))
fireChangeListener(key)
}
fun remove(key: String?) {
kvPairDao.deleteById(key)
fireChangeListener(key)
}
private val listeners = HashSet<OnPreferenceDataStoreChangeListener>()
private fun fireChangeListener(key: String?) = listeners.forEach { it.onPreferenceDataStoreChanged(this, key) }
fun registerChangeListener(listener: OnPreferenceDataStoreChangeListener) = listeners.add(listener)
fun unregisterChangeListener(listener: OnPreferenceDataStoreChangeListener) = listeners.remove(listener)
}
......@@ -22,7 +22,6 @@ package com.github.shadowsocks.tasker
import android.app.Activity
import android.content.res.Resources
import android.os.Build
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator
......@@ -37,6 +36,7 @@ import android.widget.Switch
import com.github.shadowsocks.R
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.utils.resolveResourceId
class ConfigActivity : AppCompatActivity() {
inner class ProfileViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
......@@ -44,9 +44,7 @@ class ConfigActivity : AppCompatActivity() {
private val text = itemView.findViewById<CheckedTextView>(android.R.id.text1)
init {
val typedArray = obtainStyledAttributes(intArrayOf(android.R.attr.selectableItemBackground))
view.setBackgroundResource(typedArray.getResourceId(0, 0))
typedArray.recycle()
view.setBackgroundResource(theme.resolveResourceId(android.R.attr.selectableItemBackground))
itemView.setOnClickListener(this)
}
......@@ -72,13 +70,12 @@ class ConfigActivity : AppCompatActivity() {
inner class ProfilesAdapter : RecyclerView.Adapter<ProfileViewHolder>() {
internal val profiles = ProfileManager.getAllProfiles()?.toMutableList() ?: mutableListOf()
private val name = "select_dialog_singlechoice_" + (if (Build.VERSION.SDK_INT >= 21) "material" else "holo")
override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) =
if (position == 0) holder.bindDefault() else holder.bind(profiles[position - 1])
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder(
LayoutInflater.from(parent.context).inflate(Resources.getSystem()
.getIdentifier(name, "layout", "android"), parent, false))
.getIdentifier("select_dialog_singlechoice_material", "layout", "android"), parent, false))
override fun getItemCount(): Int = 1 + profiles.size
}
......
......@@ -27,7 +27,7 @@ import com.github.shadowsocks.R
import com.github.shadowsocks.database.ProfileManager
import com.twofortyfouram.locale.api.Intent as ApiIntent
class Settings(bundle: Bundle) {
class Settings(bundle: Bundle?) {
companion object {
private val KEY_SWITCH_ON = "switch_on"
private val KEY_PROFILE_ID = "profile_id"
......@@ -35,8 +35,8 @@ class Settings(bundle: Bundle) {
fun fromIntent(intent: Intent) = Settings(intent.getBundleExtra(ApiIntent.EXTRA_BUNDLE))
}
var switchOn: Boolean = bundle.getBoolean(KEY_SWITCH_ON, true)
var profileId: Int = bundle.getInt(KEY_PROFILE_ID, -1)
var switchOn: Boolean = bundle?.getBoolean(KEY_SWITCH_ON, true) ?: true
var profileId: Int = bundle?.getInt(KEY_PROFILE_ID, -1) ?: -1
fun toIntent(context: Context): Intent {
val bundle = Bundle()
......
......@@ -21,7 +21,11 @@
package com.github.shadowsocks.utils
object Key {
const val PROFILE = "profile.db"
/**
* Public config that doesn't need to be kept secret.
*/
const val DB_PUBLIC = "config.db"
const val DB_PROFILE = "profile.db"
const val id = "profileId"
const val name = "profileName"
......@@ -39,6 +43,7 @@ object Key {
const val route = "route"
const val isAutoConnect = "isAutoConnect"
const val directBootAware = "directBootAware"
const val proxyApps = "isProxyApps"
const val bypass = "isBypassApps"
......
/*******************************************************************************
* *
* 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.utils
import android.annotation.TargetApi
import android.content.Context
import android.content.ContextWrapper
@TargetApi(24)
class DeviceContext(context: Context) : ContextWrapper(context.createDeviceProtectedStorageContext()) {
/**
* Thou shalt not get the REAL underlying application context which would no longer be operating under device
* protected storage.
*/
override fun getApplicationContext(): Context = this
}
package com.github.shadowsocks.utils
import android.annotation.TargetApi
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore
import java.io.File
import java.io.FileNotFoundException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
@TargetApi(24)
object DirectBoot {
private val file = File(app.deviceContext.noBackupFilesDir, "directBootProfile")
fun getDeviceProfile(): Profile? = try {
ObjectInputStream(file.inputStream()).use { it.readObject() as Profile }
} catch (_: FileNotFoundException) { null }
fun clean() {
file.delete()
File(app.deviceContext.noBackupFilesDir, BaseService.CONFIG_FILE).delete()
}
fun update() {
val profile = ProfileManager.getProfile(DataStore.profileId) // app.currentProfile will call this
if (profile == null) clean() else ObjectOutputStream(file.outputStream()).use { it.writeObject(profile) }
}
}
......@@ -25,15 +25,16 @@ import java.util.*
class Subnet(val address: InetAddress, val prefixSize: Int) : Comparable<Subnet> {
companion object {
@Throws(IllegalArgumentException::class)
fun fromString(value: String): Subnet {
val parts = value.split('/')
val addr = parts[0].parseNumericAddress()
return when (parts.size) {
1 -> Subnet(addr, addr.address.size shl 3)
2 -> Subnet(addr, parts[1].toInt())
else -> throw IllegalArgumentException()
}
fun fromString(value: String): Subnet? {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
val parts = (value as java.lang.String).split("/", 2)
val addr = parts[0].parseNumericAddress() ?: return null
return if (parts.size == 2) try {
val prefixSize = parts[1].toInt()
if (prefixSize < 0 || prefixSize > addr.address.size shl 3) null else Subnet(addr, prefixSize)
} catch (_: NumberFormatException) {
null
} else Subnet(addr, addr.address.size shl 3)
}
}
......
......@@ -42,6 +42,7 @@ object TcpFastOpen {
val sendEnabled: Boolean get() {
val file = File("/proc/sys/net/ipv4/tcp_fastopen")
// File.readText doesn't work since this special file will return length 0
return file.canRead() && file.bufferedReader().use { it.readText() }.trim().toInt() and 1 > 0
}
......
......@@ -3,31 +3,28 @@ package com.github.shadowsocks.utils
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.os.Build
import android.support.annotation.AttrRes
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v7.util.SortedList
import android.util.TypedValue
import com.github.shadowsocks.App.Companion.app
import java.lang.reflect.InvocationTargetException
import com.github.shadowsocks.JniHelper
import java.net.InetAddress
import java.net.URLConnection
private val isNumericMethod by lazy { InetAddress::class.java.getMethod("isNumeric", String::class.java) }
private val parseNumericAddressMethod by lazy {
InetAddress::class.java.getMethod("parseNumericAddress", String::class.java)
}
private val fieldChildFragmentManager by lazy {
val field = Fragment::class.java.getDeclaredField("mChildFragmentManager")
field.isAccessible = true
field
}
fun String.isNumericAddress(): Boolean = isNumericMethod.invoke(null, this) as Boolean
fun String.parseNumericAddress(): InetAddress = try {
parseNumericAddressMethod.invoke(null, this) as InetAddress
} catch (exc: InvocationTargetException) {
throw exc.cause ?: exc
fun String.isNumericAddress() = JniHelper.parseNumericAddress(this) != null
fun String.parseNumericAddress(): InetAddress? {
val addr = JniHelper.parseNumericAddress(this)
return if (addr == null) null else InetAddress.getByAddress(this, addr)
}
fun parsePort(str: String?, default: Int, min: Int = 1025): Int {
......@@ -53,8 +50,6 @@ fun thread(start: Boolean = true, isDaemon: Boolean = false, contextClassLoader:
val URLConnection.responseLength: Long
get() = if (Build.VERSION.SDK_INT >= 24) contentLengthLong else contentLength.toLong()
fun Float.dp(): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, app.resources.displayMetrics)
/**
* Based on: https://stackoverflow.com/a/15656428/2245107
*/
......@@ -62,6 +57,15 @@ var Fragment.childFragManager: FragmentManager?
get() = childFragmentManager
set(value) = fieldChildFragmentManager.set(this, value)
/**
* Based on: https://stackoverflow.com/a/26348729/2245107
*/
fun Resources.Theme.resolveResourceId(@AttrRes resId: Int): Int {
val typedValue = TypedValue()
if (!resolveAttribute(resId, typedValue, true)) throw Resources.NotFoundException()
return typedValue.resourceId
}
private class SortedListIterable<out T>(private val list: SortedList<T>) : Iterable<T> {
override fun iterator(): Iterator<T> = SortedListIterator(list)
}
......
......@@ -28,12 +28,13 @@ import com.github.shadowsocks.R
/**
* Based on: http://stackoverflow.com/a/6212120/2245107
*/
class BoundedGridLayout(context: Context, attrs: AttributeSet) : GridLayout(context, attrs) {
class BoundedGridLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0,
defStyleRes: Int = 0) : GridLayout(context, attrs, defStyleAttr) {
private val boundedWidth: Int
private val boundedHeight: Int
init {
val arr = context.obtainStyledAttributes(attrs, R.styleable.BoundedGridLayout)
val arr = context.obtainStyledAttributes(attrs, R.styleable.BoundedGridLayout, defStyleAttr, defStyleRes)
boundedWidth = arr.getDimensionPixelSize(R.styleable.BoundedGridLayout_bounded_width, 0)
boundedHeight = arr.getDimensionPixelSize(R.styleable.BoundedGridLayout_bounded_height, 0)
arr.recycle()
......
/*******************************************************************************
* *
* 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.widget
import android.content.Context
import android.graphics.drawable.Drawable
import android.support.annotation.DrawableRes
import android.support.design.widget.FloatingActionButton
import android.support.graphics.drawable.Animatable2Compat
import android.support.graphics.drawable.AnimatedVectorDrawableCompat
import android.support.v7.widget.TooltipCompat
import android.util.AttributeSet
import android.view.View
import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.R
import com.github.shadowsocks.bg.BaseService
import java.util.*
class ServiceButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
FloatingActionButton(context, attrs, defStyleAttr) {
private val callback = object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable) {
super.onAnimationEnd(drawable)
var next = animationQueue.peek() ?: return
if (next.current == drawable) {
animationQueue.pop()
next = animationQueue.peek() ?: return
}
setImageDrawable(next)
next.start()
}
}
private fun createIcon(@DrawableRes resId: Int): AnimatedVectorDrawableCompat {
val result = AnimatedVectorDrawableCompat.create(context, resId)!!
result.registerAnimationCallback(callback)
return result
}
private val iconStopped by lazy { createIcon(R.drawable.ic_service_stopped) }
private val iconConnecting by lazy { createIcon(R.drawable.ic_service_connecting) }
private val iconConnected by lazy { createIcon(R.drawable.ic_service_connected) }
private val iconStopping by lazy { createIcon(R.drawable.ic_service_stopping) }
private val animationQueue = ArrayDeque<AnimatedVectorDrawableCompat>()
private var checked = false
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val drawableState = super.onCreateDrawableState(extraSpace + 1)
if (checked) View.mergeDrawableStates(drawableState, intArrayOf(android.R.attr.state_checked))
return drawableState
}
fun changeState(state: Int, animate: Boolean) {
when (state) {
BaseService.CONNECTING -> changeState(iconConnecting, animate)
BaseService.CONNECTED -> changeState(iconConnected, animate)
BaseService.STOPPING -> changeState(iconStopping, animate)
else -> changeState(iconStopped, animate)
}
if (state == BaseService.CONNECTED) {
checked = true
TooltipCompat.setTooltipText(this, context.getString(R.string.stop))
} else {
checked = false
TooltipCompat.setTooltipText(this, context.getString(R.string.connect))
}
refreshDrawableState()
isEnabled = false
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 =
a == iconStopped && b == iconConnecting ||
a == iconConnecting && b == iconStopped ||
a == iconConnected && b == iconStopping ||
a == iconStopping && b == iconConnected
private fun changeState(icon: AnimatedVectorDrawableCompat, animate: Boolean) {
if (animate) {
if (animationQueue.size < 2 || !counters(animationQueue.last, icon)) {
animationQueue.add(icon)
if (animationQueue.size == 1) {
setImageDrawable(icon)
icon.start()
}
} else animationQueue.removeLast()
} else {
animationQueue.peekFirst()?.stop()
animationQueue.clear()
setImageDrawable(icon)
icon.start() // force ensureAnimatorSet to be called so that stop() will work
icon.stop()
}
}
}
/*******************************************************************************
* *
* 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.widget
import android.animation.ValueAnimator
import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.support.design.widget.Snackbar
import android.support.design.widget.SnackbarAnimation
import android.util.AttributeSet
import android.view.View
import android.view.accessibility.AccessibilityManager
/**
* Full credits go to: https://stackoverflow.com/a/35904421/2245107
*/
class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<View>(context, attrs) {
private val accessibility = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean =
dependency is Snackbar.SnackbarLayout
override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
child.layoutParams.height = dependency.y.toInt()
child.requestLayout()
return true
}
/**
* Based on BaseTransientBottomBar.animateViewOut (support lib 27.0.2).
*/
override fun onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) {
if (accessibility.isEnabled) child.layoutParams.height = parent.height else {
val animator = ValueAnimator()
val start = child.height
animator.setIntValues(start, parent.height)
animator.interpolator = SnackbarAnimation.FAST_OUT_SLOW_IN_INTERPOLATOR
animator.duration = SnackbarAnimation.ANIMATION_DURATION
@Suppress("NAME_SHADOWING")
animator.addUpdateListener { animator ->
child.layoutParams.height = animator.animatedValue as Int
child.requestLayout()
}
animator.start()
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/material_green_700" android:state_checked="true"/>
<item android:color="@color/material_primary_500"/>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/material_primary_300" />
</shape>
</item>
<item>
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/material_green_700" />
</shape>
</item>
</selector>
</item>
<!-- android:start not available until API 23 -->
<item android:left="8dp">
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
</shape>
</item>
<item android:drawable="?android:attr/selectableItemBackground"/>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
<item>
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_selected="true">
<color android:color="@color/material_primary_100"/>
</item>
</selector>
</item>
</ripple>
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
<item>
<color android:color="@color/material_primary_300"/>
</item>
</ripple>
......@@ -15,18 +15,11 @@
</item>
</selector>
</item>
<!-- android:start not available until API 23 -->
<item android:left="8dp">
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
</shape>
</item>
<item>
<selector>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#12000000" />
</shape>
</item>
</selector>
</item>
<item android:drawable="?android:attr/selectableItemBackground"/>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_selected="true">
<color android:color="@color/material_primary_100"/>
</item>
</selector>
</selector>
</item>
<item android:drawable="?android:attr/selectableItemBackground"/>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/material_primary_300" />
</shape>
</item>
<item>
<selector>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#12000000" />
</shape>
</item>
</selector>
<color android:color="@color/material_primary_300"/>
</item>
<item android:drawable="?android:attr/selectableItemBackground"/>
</layer-list>
......@@ -5,9 +5,7 @@
android:viewportHeight="24">
<path
android:name="path"
android:fillColor="#fff"
android:pathData="M 21.25 2.28 L 17.55 18.55 L 9.26 15.89 L 16.58 7.16 L 6.83 15.37 L 0 12.8 L 21.25 2.28 Z" />
<path
android:fillColor="#fff"
android:pathData="M 9.45 17.56 L 12.09 18.41 L 9.46 22 L 9.45 17.56 Z" />
android:pathData="M 21.25 2.28 L 17.55 18.55 L 9.26 15.89 L 16.58 7.16 L 6.83 15.37 L 0 12.8 L 21.25 2.28 ZM 9.45 17.56 L 12.09 18.41 L 9.46 22 L 9.45 17.56 Z" />
</vector>
......@@ -5,9 +5,7 @@
android:viewportHeight="24">
<path
android:name="path"
android:fillColor="#fff"
android:pathData="M17.68,9l-1.59,7L12.7,14.89l5-5.93M10,10.08l-3.57,3L5,12.55l5-2.47M21.25,2.28L0,12.8l6.83,2.57,9.76-8.21L9.26,15.89l8.29,2.67,3.7-16.27h0Z" />
<path
android:fillColor="#fff"
android:pathData="M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
android:pathData="M17.68,9l-1.59,7L12.7,14.89l5-5.93M10,10.08l-3.57,3L5,12.55l5-2.47M21.25,2.28L0,12.8l6.83,2.57,9.76-8.21L9.26,15.89l8.29,2.67,3.7-16.27h0ZM 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/ic_service_busy"
tools:ignore="NewApi">
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 17.68 9 L 16.09 16 L 12.7 14.89 L 17.7 8.96 M 10 10.08 L 6.43 13.08 L 5 12.55 L 10 10.08 M 21.25 2.28 L 0 12.8 L 6.83 15.37 L 16.59 7.16 L 9.26 15.89 L 17.55 18.56 L 21.25 2.29 L 21.25 2.29 Z M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z"
android:valueTo="M 15.5 13.28 L 15.5 13.28 L 15.5 13.28 L 15.5 13.28 M 7.14 11.9 L 7.14 11.9 L 7.14 11.9 L 7.14 11.9 M 21.25 2.28 L 0 12.8 L 6.83 15.37 L 16.59 7.16 L 9.26 15.89 L 17.55 18.56 L 21.25 2.29 L 21.25 2.29 Z M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/ic_service_idle"
tools:ignore="NewApi">
<target android:name="strike_thru_path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 19.73 22 L 21 20.73 L 3.27 3 L 2 4.27 Z"
android:valueTo="M 2 4.27 L 3.27 3 L 3.27 3 L 2 4.27 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="strike_thru_mask">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 0 0 L 24 0 L 24 24 L 0 24 L 0 0 Z M 4.54 1.73 L 3.27 3 L 21 20.73 L 22.27 19.46 Z"
android:valueTo="M 0 0 L 24 0 L 24 24 L 0 24 L 0 0 Z M 4.54 1.73 L 3.27 3 L 3.27 3 L 4.54 1.73 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="strike_thru_path"
android:pathData="M 19.73 22 L 21 20.73 L 3.27 3 L 2 4.27 Z"
android:fillColor="#fff"
android:strokeWidth="1"/>
<clip-path
android:name="strike_thru_mask"
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 L 0 0 Z M 4.54 1.73 L 3.27 3 L 21 20.73 L 22.27 19.46 Z"/>
<path
android:name="holey_icon"
android:pathData="M17.68,9l-1.59,7L12.7,14.89l5-5.93M10,10.08l-3.57,3L5,12.55l5-2.47M21.25,2.28L0,12.8l6.83,2.57,9.76-8.21L9.26,15.89l8.29,2.67,3.7-16.27h0ZM 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z"
android:fillColor="#fff"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/ic_service_idle"
tools:ignore="NewApi">
<target android:name="strike_thru_path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 2 4.27 L 3.27 3 L 3.27 3 L 2 4.27 Z"
android:valueTo="M 19.73 22 L 21 20.73 L 3.27 3 L 2 4.27 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="strike_thru_mask">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 0 0 L 24 0 L 24 24 L 0 24 L 0 0 Z M 4.54 1.73 L 3.27 3 L 3.27 3 L 4.54 1.73 Z"
android:valueTo="M 0 0 L 24 0 L 24 24 L 0 24 L 0 0 Z M 4.54 1.73 L 3.27 3 L 21 20.73 L 22.27 19.46 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/ic_service_busy"
tools:ignore="NewApi">
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="@android:integer/config_mediumAnimTime"
android:valueFrom="M 15.5 13.28 L 15.5 13.28 L 15.5 13.28 L 15.5 13.28 M 7.14 11.9 L 7.14 11.9 L 7.14 11.9 L 7.14 11.9 M 21.25 2.28 L 0 12.8 L 6.83 15.37 L 16.59 7.16 L 9.26 15.89 L 17.55 18.56 L 21.25 2.29 L 21.25 2.29 Z M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z"
android:valueTo="M 17.68 9 L 16.09 16 L 12.7 14.89 L 17.7 8.96 M 10 10.08 L 6.43 13.08 L 5 12.55 L 10 10.08 M 21.25 2.28 L 0 12.8 L 6.83 15.37 L 16.59 7.16 L 9.26 15.89 L 17.55 18.56 L 21.25 2.29 L 21.25 2.29 Z M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
<path
android:strokeColor="#fff"
android:strokeWidth="2"
android:strokeMiterLimit="10"
android:pathData="M0.71,2.12L21.88,23.29Z" />
<path
android:fillColor="#fff"
android:pathData="M 13 10.17 L 16.58 7.16 L 13.57 10.75 L 14.99 12.16 L 17.68 8.96 L 16.59 13.76 L 18.26 15.43 L 21.25 2.28 L 10.45 7.62 L 13 10.17 Z" />
<path
android:fillColor="#fff"
android:pathData="M 15.93 15.93 L 12.71 14.89 L 13.7 13.7 L 12.28 12.28 L 9.26 15.89 L 17.55 18.55 L 17.74 17.74 L 15.93 15.93 Z" />
<path
android:fillColor="#fff"
android:pathData="M8.56,8.56L0,12.8l6.83,2.57,4.64-3.9ZM6.44,13.08L5,12.55l5-2.47Z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="Iceland"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>
......@@ -6,6 +6,7 @@
<Spinner android:id="@+id/template_selector"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@+id/content"
android:entries="@array/acl_rule_templates"/>
<EditText android:id="@+id/content"
android:layout_width="match_parent"
......
......@@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:checked="true"
android:paddingBottom="12dp"
android:paddingEnd="20dp"
android:paddingEnd="@dimen/fastscroll__bubble_corner"
android:paddingStart="60dp"
android:paddingTop="12dp"
android:text="@string/on"
......@@ -34,7 +34,7 @@
android:layout_height="wrap_content"
android:checked="true"
android:paddingBottom="12dp"
android:paddingEnd="20dp"
android:paddingEnd="@dimen/fastscroll__bubble_corner"
android:paddingStart="60dp"
android:paddingTop="12dp"
android:text="@string/bypass_apps"
......
......@@ -20,7 +20,7 @@
android:id="@+id/itemcheck"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_marginEnd="20dp"
android:layout_marginEnd="@dimen/fastscroll__bubble_corner"
android:layout_weight="1"
android:clickable="false"
android:ellipsize="end"
......
......@@ -10,8 +10,7 @@
android:scaleType="centerCrop"
android:src="@drawable/background_header"/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_title"
<TextView android:id="@+id/drawer_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
......
......@@ -6,7 +6,7 @@
android:orientation="vertical">
<include layout="@layout/toolbar_light_dark"/>
<android.support.v7.widget.RecyclerView android:id="@+id/list"
tools:listitem="@android:layout/simple_list_item_1"
tools:listitem="@layout/layout_profile"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent"
tools:ignore="UnknownIdInLayout" android:clipChildren="false">
<FrameLayout android:id="@+id/fragment_holder"
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/snackbar"
android:background="@color/material_primary_700"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/stat"/>
<LinearLayout android:id="@+id/stat"
app:layout_behavior="com.github.shadowsocks.widget.ShrinkUpwardBehavior">
<FrameLayout
android:id="@+id/fragment_holder"
android:background="?android:attr/windowBackground"
android:layout_above="@+id/stat"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/stat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_stat"
android:elevation="4dp"
android:paddingStart="16dip"
android:paddingEnd="16dip"
android:paddingTop="16dip"
android:paddingBottom="16dip"
android:focusable="true"
android:background="@drawable/background_stat"
android:orientation="vertical"
android:nextFocusRight="@+id/fab"
android:layout_above="@+id/snackbar">
<TextView android:id="@+id/status"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:orientation="vertical"
android:paddingBottom="16dip"
android:paddingEnd="16dip"
android:paddingStart="16dip"
android:paddingTop="16dip"
android:layout_alignParentBottom="true">
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingEnd="72dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.github.shadowsocks.widget.BoundedGridLayout android:layout_width="match_parent"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
tools:ignore="RtlSymmetry"/>
<com.github.shadowsocks.widget.BoundedGridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:bounded_width="288dp"
app:columnCount="4">
<TextView app:layout_column="0" style="@style/TextAppearance.AppCompat.Body2"
android:ellipsize="marquee" android:text="@string/sent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
<TextView
style="@style/TextAppearance.AppCompat.Body2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:gravity="end"/>
<TextView app:layout_column="1" android:id="@+id/tx" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="0dp" android:layout_height="wrap_content"
app:layout_columnWeight="1" android:layout_gravity="fill_horizontal"/>
<TextView app:layout_column="2" android:textSize="14sp"
android:ellipsize="marquee"
android:gravity="end"
android:text="@string/sent"
app:layout_column="0"/>
<TextView
android:id="@+id/tx"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:ellipsize="marquee"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_column="1"
app:layout_columnWeight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:text="▲"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_column="2"/>
<TextView
android:id="@+id/txRate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:ellipsize="marquee"
android:gravity="end"
android:textColor="?android:attr/textColorSecondary"
android:ellipsize="marquee" android:text="▲"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView app:layout_column="3" android:id="@+id/txRate" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="0dp" android:layout_height="wrap_content" app:layout_columnWeight="1"
android:layout_gravity="fill_horizontal" android:gravity="end"/>
<TextView app:layout_row="1" app:layout_column="0" style="@style/TextAppearance.AppCompat.Body2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp"
app:layout_column="3"
app:layout_columnWeight="1"/>
<TextView
style="@style/TextAppearance.AppCompat.Body2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:ellipsize="marquee"
android:gravity="end"
android:text="@string/received"
app:layout_column="0"
app:layout_row="1"/>
<TextView
android:id="@+id/rx"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:ellipsize="marquee"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_row="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:text="▼"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_column="2"
app:layout_row="1"/>
<TextView
android:id="@+id/rxRate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:ellipsize="marquee"
android:gravity="end"
android:ellipsize="marquee" android:text="@string/received"/>
<TextView app:layout_row="1" app:layout_column="1" android:id="@+id/rx" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="0dp" android:layout_height="wrap_content" app:layout_columnWeight="1"
android:layout_gravity="fill_horizontal" />
<TextView app:layout_row="1" app:layout_column="2" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="▼"/>
<TextView app:layout_row="1" app:layout_column="3" android:id="@+id/rxRate" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="0dp" android:layout_height="wrap_content" app:layout_columnWeight="1"
android:layout_gravity="fill_horizontal" android:gravity="end"/>
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_column="3"
app:layout_columnWeight="1"
app:layout_row="1"/>
</com.github.shadowsocks.widget.BoundedGridLayout>
</LinearLayout>
<com.github.jorgecastilloprz.FABProgressCircle android:id="@+id/fabProgressCircle"
app:reusable="true"
</RelativeLayout>
<!-- workaround for 0 elevation in disabled state -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="6dp"
android:layout_alignTop="@+id/stat"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:layout_marginTop="@dimen/fab_margin_top">
<android.support.design.widget.FloatingActionButton android:id="@+id/fab"
android:layout_marginTop="-28dp"
android:elevation="6dp"
app:layout_anchor="@id/stat"
app:layout_anchorGravity="top|end">
<com.github.shadowsocks.widget.ServiceButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:backgroundTint="@color/material_primary_500"
app:srcCompat="@drawable/ic_start_idle"
app:backgroundTint="@color/background_service"
app:fabSize="normal"
app:pressedTranslationZ="6dp"
app:borderWidth="0dp"/>
</com.github.jorgecastilloprz.FABProgressCircle>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/snackbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
app:srcCompat="@drawable/ic_service_idle"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
......@@ -12,10 +12,6 @@
android:nextFocusRight="@+id/edit"
android:orientation="vertical">
<Space
android:layout_width="match_parent"
android:layout_height="8dp"/>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
......@@ -46,7 +42,7 @@
android:contentDescription="@string/share"
android:focusable="true"
android:nextFocusLeft="@+id/container"
android:padding="8dp"
android:padding="12dp"
app:srcCompat="@drawable/ic_social_share"/>
<android.support.v7.widget.AppCompatImageView
......@@ -57,7 +53,7 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/edit"
android:focusable="true"
android:padding="8dp"
android:padding="12dp"
app:srcCompat="@drawable/ic_image_edit"/>
</LinearLayout>
......@@ -72,13 +68,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginEnd="8dp"
android:layout_marginBottom="@dimen/profile_padding"
android:layout_marginEnd="12dp"
android:layout_toStartOf="@+id/traffic"
android:ellipsize="end"
android:maxLines="2"
tools:text="@string/profile_plugin"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
android:textColor="?android:attr/textColorSecondary"
tools:text="@string/profile_plugin"/>
<TextView
android:id="@+id/traffic"
......@@ -86,13 +83,11 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="bottom"
android:layout_marginEnd="8dp"
android:layout_marginBottom="@dimen/profile_padding"
android:layout_marginEnd="12dp"
android:ellipsize="end"
tools:text="@string/traffic"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
android:textColor="?android:attr/textColorSecondary"
tools:text="@string/traffic"/>
</RelativeLayout>
<Space
android:layout_width="match_parent"
android:layout_height="8dp"/>
</LinearLayout>
<?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/selection"
android:title="@string/action_selection"
android:icon="@drawable/abc_ic_menu_selectall_mtrl_alpha"
<item
android:id="@+id/selection"
android:alphabeticShortcut="s"
android:icon="?attr/actionModeSelectAllDrawable"
android:numericShortcut="0"
android:title="@string/action_selection"
android:visible="false"
app:showAsAction="always">
<menu>
<item android:id="@+id/action_select_all"
android:title="@android:string/selectAll"
<item
android:id="@+id/action_select_all"
android:alphabeticShortcut="a"
android:numericShortcut="1"
android:title="@android:string/selectAll"
app:showAsAction="always"/>
<item android:id="@+id/action_cut"
android:title="@android:string/cut"
<item
android:id="@+id/action_cut"
android:alphabeticShortcut="t"
android:numericShortcut="2"
android:title="@android:string/cut"
app:showAsAction="always"/>
<item android:id="@+id/action_copy"
android:title="@android:string/copy"
<item
android:id="@+id/action_copy"
android:alphabeticShortcut="c"
android:numericShortcut="3"
android:title="@android:string/copy"
app:showAsAction="always"/>
<item android:id="@+id/action_delete"
android:title="@string/delete"
<item
android:id="@+id/action_delete"
android:alphabeticShortcut="d"
android:numericShortcut="4"
android:title="@string/delete"
app:showAsAction="always"/>
</menu>
</item>
......
......@@ -4,7 +4,7 @@
<!-- misc -->
<string name="profile">"پروفایل"</string>
<string name="connection_test_testing">"در حال آزمایش..."</string>
<string name="connection_test_testing">"در حال آزمایش"</string>
<!-- proxy category -->
<string name="profile_name">"نام پروفایل"</string>
......@@ -20,7 +20,7 @@
<string name="invalid_server">"آدرس سرور نامعتبر است"</string>
<string name="service_failed">"اتصال به سرور ناموفق بود!"</string>
<string name="stop">"غیرفعال‌کردن"</string>
<string name="stopping">"در حال قطع‌کردن اتصال..."</string>
<string name="stopping">"در حال قطع‌کردن اتصال"</string>
<string name="profile_invalid_input">"هیچ پروفایل معتبری یافت نشد!"</string>
<!-- alert category -->
......@@ -33,7 +33,6 @@
<string name="profiles">"پروفایل‌ها"</string>
<string name="settings">"تنظیمات"</string>
<string name="faq">"سوالات مداول"</string>
<string name="recovery">"ریست"</string>
<string name="about">"درباره ما"</string>
<string name="edit">"ویرایش"</string>
<string name="share">"به اشتراک گذاری"</string>
......@@ -52,9 +51,8 @@
<!-- status -->
<string name="sent">"فرستاده‌شده:"</string>
<string name="received">"دریافت‌شده:"</string>
<string name="connecting">"در حال اتصال..."</string>
<string name="connecting">"در حال اتصال"</string>
<string name="vpn_connected">"وصل شد. برای بررسی اتصال ضربه (Tap) بزنید."</string>
<string name="nat_connected">"اتصال برقرار است."</string>
<string name="not_connected">"اتصال برقرار نیست!"</string>
<string name="route_entry_all">"همه"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- misc -->
<string name="profile">"Profil"</string>
<string name="connection_test_error">"Impossible de détecter la connexion Internet :%s"</string>
<string name="connection_test_fail">"Internet Indisponible"</string>
<string name="connection_test_error_status_code">"Code de l'Erreur : #%d"</string>
<string name="proxy">"Serveur"</string>
<string name="sitekey">"Mot de passe"</string>
<string name="service_failed">"Échec de la connexion au serveur distant"</string>
<!-- alert category -->
<string name="close">"Fermer"</string>
<string name="profile_empty">"Veuillez sélectionner un profil"</string>
<!-- menu category -->
<string name="profiles">"Profils"</string>
<string name="settings">"Paramètres"</string>
<string name="about">"À propos"</string>
<string name="share">"Partager"</string>
<string name="add_profile">"Ajouter un Profil"</string>
<string name="action_apply_all">"Appliquer les Paramètres à tous les Profils"</string>
<string name="action_export">"Exporter vers le presse-papiers"</string>
<string name="action_import">"Importer depuis le presse-papiers"</string>
<string name="delete">"Supprimer"</string>
<string name="delete_confirm_prompt">"Êtes-vous sûr de vouloir supprimer ce profil?"</string>
<string name="share_qr_nfc">"QR Code/NFC"</string>
<string name="add_profile_methods_scan_qr_code">"Scanner le QR Code"</string>
<plurals name="removed">
<item quantity="one">"Supprimé"</item>
<item quantity="other">"%d éléments supprimés"</item>
</plurals>
<string name="undo">"Annuler"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">"Shadowsocks"</string>
<string name="quick_toggle">"ON/OFF"</string>
<!-- misc -->
......@@ -9,7 +8,6 @@
<string name="remote_dns">"リモートDNS"</string>
<string name="stat_summary">"送信済み: \t%3$s\t↑\t%1$s/s
受信済み: \t%4$s\t↓\t%2$s/s"</string>
<string name="connection_test_pending">"接続状況確認"</string>
<string name="connection_test_testing">"テスト中…"</string>
<string name="connection_test_available">"成功: %dmsの遅延"</string>
......@@ -35,10 +33,8 @@
<string name="ipv6_summary">"リモートサーバーに IPv6 パケットを転送"</string>
<string name="route_list">"プロキシ方式"</string>
<string name="route_entry_gfwlist">"中国本土からアクセス不可なアドレス以外を迂回する"</string>
<string name="proxied_apps">"アプリ別のプロキシを使用"</string>
<string name="proxied_apps_summary">"アプリ別でプロキシを指定、Android 4.x では必ずNATモードを使用して下さい"</string>
<string name="proxied_apps">"アプリ別のVPNモードを使用"</string>
<string name="proxied_apps_summary">"アプリ別のVPNモードを設定"</string>
<string name="on">"ON"</string>
<string name="bypass_apps">"バイパスモード(迂回モード)"</string>
<string name="bypass_apps_summary">"このモードを選択した場合、指定したアプリのパケットはプロキシを経由しない"</string>
......@@ -74,9 +70,7 @@
<string name="profiles">"プロファイル"</string>
<string name="settings">"オプション設定"</string>
<string name="faq">"よくある質問"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
<string name="about">"本アプリについて"</string>
<string name="about_title">"Shadowsocks %s"</string>
<string name="edit">"編集"</string>
<string name="share">"共有"</string>
<string name="add_profile">"プロファイルを追加"</string>
......@@ -127,10 +121,7 @@
<string name="route_entry_bypass_chn">"中国本土のアドレスを迂回する"</string>
<string name="route_entry_bypass_lan_chn">"LAN 及び中国本土のアドレスを迂回する"</string>
<string name="route_entry_chinalist">"中国本土のアドレス以外を迂回する"</string>
<string name="proxied_apps_summary_v21">"選択したアプリにプロキシを設定する"</string>
<string name="acl_rule_templates_generic">"URL/サブネット/ホスト名 PCRE パターン"</string>
<string name="acl_rule_templates_generic">"サブネットまたはホスト名のPCREパターン"</string>
<string name="acl_rule_templates_domain">"ドメイン及び全てのサブドメイン"</string>
<!-- plugin -->
......@@ -148,7 +139,6 @@
<string name="advanced">"アドバンス"</string>
<string name="service_mode">"サービスモード"</string>
<string name="service_mode_proxy">"プロキシのみ"</string>
<string name="service_mode_vpn">"VPN"</string>
<string name="service_mode_transproxy">"トランスプロキシ"</string>
<string name="port_proxy">"SOCKS5プロキシポート"</string>
<string name="port_local_dns">"ローカルDNSポート"</string>
......@@ -157,4 +147,7 @@
<string name="service_transproxy">"トランスプロキシサービス"</string>
<string name="vpn_permission_denied">"VPNサービス作成のアクセス許可が拒否されました"</string>
<string name="auto_connect_summary_v24">"起動時にShadowsockを有効。 VPN常時接続の使用をお勧めします"</string>
<string name="direct_boot_aware">"ダイレクトブート"</string>
<string name="direct_boot_aware_summary">"デバイスがロック解除される前にShadowsocksの自動起動を許可(選択されたプロファイル情報はより少ない保護を受けることになります)"</string>
<string name="acl_rule_online_config">"オンライン設定のURL"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">"Shadowsocks"</string>
<string name="quick_toggle">"켜기/끄기"</string>
<!-- misc -->
......@@ -9,7 +8,9 @@
<string name="remote_dns">"원격 DNS"</string>
<string name="stat_summary">"송신: \t%3$s\t↑\t%1$s/s
수신: \t%4$s\t↓\t%2$s/s"</string>
<plurals name="bytes">
<item quantity="other">"바이트"</item>
</plurals>
<string name="connection_test_pending">"인터넷 연결 상태 검사하기"</string>
<string name="connection_test_testing">"검사 중…"</string>
<string name="connection_test_available">"성공: 지연시간 %dms"</string>
......@@ -34,11 +35,10 @@
<string name="ipv6">"IPv6 라우팅"</string>
<string name="ipv6_summary">"IPv6 트래픽도 원격으로 리다이렉트 합니다"</string>
<string name="route_list">"라우팅 대상"</string>
<string name="route_entry_gfwlist">"GFW List"</string>
<!-- Fuzzy -->
<string name="proxied_apps">"원하는 앱만 프락시 적용하기"</string>
<string name="proxied_apps_summary">"선택한 앱에만 프락시를 적용합니다. Android 4.x 이하에서는 NAT 모드를 써야 합니다."</string>
<string name="proxied_apps_summary">"선택한 앱에만 프락시를 적용합니다"</string>
<string name="on">"활성화"</string>
<string name="bypass_apps">"선택된 앱들만 프록시 적용 제외하기"</string>
<string name="bypass_apps_summary">"이 옵션을 활성화하면 선택된 앱들은 프락시를 사용하지 않습니다"</string>
......@@ -55,7 +55,6 @@
<string name="service_failed">"원격 서버에 접속하는 데 실패했습니다"</string>
<string name="stop">"중지"</string>
<string name="stopping">"종료 중…"</string>
<string name="vpn_error">"%s"</string>
<string name="reboot_required">"VPN 서비스를 시작하는 데 실패했습니다. 장치를 재시작해 보세요."</string>
<string name="profile_invalid_input">"올바른 프로필 데이터를 찾을 수 없습니다"</string>
......@@ -74,13 +73,10 @@
<string name="profiles">"프로필"</string>
<string name="settings">"설정"</string>
<string name="faq">"자주 묻는 질문"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
<string name="about">"이 앱에 대하여"</string>
<string name="about_title">"Shadowsocks %s"</string>
<string name="edit">"수정"</string>
<string name="share">"공유"</string>
<string name="add_profile">"프로필 추가"</string>
<string name="action_apply_all">"Apply Settings to All Profiles"</string>
<string name="action_export">"클립보드로 내보내기"</string>
<string name="action_import">"클립보드에서 불러오기"</string>
<string name="action_export_msg">"성공적으로 내보냈습니다"</string>
......@@ -102,34 +98,15 @@
</plurals>
<string name="undo">"실행 취소"</string>
<!-- tasker -->
<string name="toggle_service_state">"Start the service"</string>
<string name="start_service_default">"Connect to the current server"</string>
<string name="start_service">"Connect to %s"</string>
<string name="stop_service">"Switch to %s"</string>
<string name="profile_default">"Use the current profile"</string>
<!-- status -->
<string name="sent">"송신:"</string>
<string name="received">"수신:"</string>
<string name="connecting">"연결 중…"</string>
<string name="vpn_connected">"연결 완료. 탭 하면 연결 상태를 검사합니다."</string>
<string name="not_connected">"Not connected"</string>
<!-- acl -->
<string name="custom_rules">"사용자 정의 규칙"</string>
<string name="action_selection">"Selection…"</string>
<string name="action_add_rule">"Add rule(s)…"</string>
<string name="edit_rule">"Edit rule"</string>
<string name="route_entry_all">"All"</string>
<string name="route_entry_bypass_lan">"Bypass LAN"</string>
<string name="route_entry_bypass_chn">"Bypass mainland China"</string>
<string name="route_entry_bypass_lan_chn">"Bypass LAN &amp; mainland China"</string>
<string name="route_entry_chinalist">"China List"</string>
<string name="proxied_apps_summary_v21">"Configure VPN mode for selected apps"</string>
<string name="acl_rule_templates_generic">"URL, 서브넷 혹은 호스트 이름 PCRE 패턴"</string>
<string name="acl_rule_templates_domain">"Domain name and all its subdomain names"</string>
<string name="acl_rule_templates_generic">"서브넷 혹은 호스트 이름 PCRE 패턴"</string>
<!-- plugin -->
<string name="plugin">"플러그인"</string>
......@@ -139,21 +116,4 @@
<string name="plugin_untrusted">"경고: 이 플러그인은 신뢰할 수 있는 출처에서 온 것이 아닌 것 같습니다"</string>
<string name="profile_plugin">"플러그인: %s"</string>
<string name="add_profile_scanner_permission_required">"QR 코드를 읽어 들이려면 카메라 권한이 필요합니다"</string>
<!-- notification category -->
<string name="service_vpn">"VPN Service"</string>
<string name="add_profile_methods_manual_settings">"Manual Settings"</string>
<string name="advanced">"Advanced"</string>
<string name="service_mode">"Service mode"</string>
<string name="service_mode_proxy">"Proxy only"</string>
<string name="service_mode_vpn">"VPN"</string>
<string name="service_mode_transproxy">"Transproxy"</string>
<string name="port_proxy">"SOCKS5 proxy port"</string>
<string name="port_local_dns">"Local DNS port"</string>
<string name="port_transproxy">"Transproxy port"</string>
<string name="service_proxy">"Proxy Service"</string>
<string name="service_transproxy">"Transproxy Service"</string>
<string name="vpn_permission_denied">"Permission denied to create a VPN service"</string>
<string name="auto_connect_summary_v24">"Enable Shadowsocks on startup. Recommended to use always-on VPN
instead"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">"Shadowsocks"</string>
<string name="quick_toggle">"Подключение"</string>
<!-- misc -->
<string name="profile">"Профиль"</string>
<string name="profile_summary">"Переключить на другой профиль или добавить новые"</string>
<string name="remote_dns">"Удалённый DNS"</string>
<string name="stat_summary">"Отправлено: \t%3$s\t↑\t%1$s/s
Получено: \t%4$s\t↓\t%2$s/s"</string>
<string name="stat_summary">"Отправлено: \t%3$s\t↑\t%1$s
Получено: \t\t\t%4$s\t↓\t%2$s"</string>
<plurals name="bytes">
<item quantity="one">"байт"</item>
<item quantity="few">"байта"</item>
......@@ -27,11 +25,11 @@
<string name="proxy_cat">"Настройки Сервера"</string>
<!-- proxy category -->
<string name="profile_name">"Имя Профиля"</string>
<string name="profile_name">"Имя профиля"</string>
<string name="proxy">"Сервер"</string>
<string name="remote_port">"Удалённый порт"</string>
<string name="sitekey">"Пароль"</string>
<string name="enc_method">"Метод Шифрования"</string>
<string name="enc_method">"Метод шифрования"</string>
<!-- feature category -->
<string name="feature_cat">"Дополнительные Настройки"</string>
......@@ -41,14 +39,12 @@
<string name="ipv6_summary">"Перенаправлять трафик IPv6 на удалённый сервер"</string>
<string name="route_list">"Маршрут"</string>
<string name="route_entry_gfwlist">"Список GFW"</string>
<string name="proxied_apps">"Прокси для выбранных приложений"</string>
<string name="proxied_apps_summary">"Установить прокси для выбранных приложений, требует режим NAT под Android 4.x"</string>
<string name="proxied_apps">"Режим VPN для выбранных приложений"</string>
<string name="proxied_apps_summary">"Выбрать приложения, для которых нужно использовать режим VPN"</string>
<string name="on">"Вкл"</string>
<string name="bypass_apps">"В обход прокси"</string>
<string name="bypass_apps_summary">"Включите эту опцию для работы выбранных приложений в обход прокси"</string>
<string name="auto_connect">"Авто Подключение"</string>
<string name="auto_connect">"Авто-подключение"</string>
<string name="auto_connect_summary">"Запускать Shadowsocks при включении"</string>
<string name="tcp_fastopen_summary">"Переключение требует наличия ROOT прав"</string>
<string name="tcp_fastopen_summary_unsupported">"Неподдерживаемая версия ядра: %s &lt; 3.7.1"</string>
......@@ -61,9 +57,8 @@
<string name="service_failed">"Ошибка при подключении к удалённому серверу"</string>
<string name="stop">"Остановить"</string>
<string name="stopping">"Останавливается…"</string>
<string name="vpn_error">"%s"</string>
<string name="reboot_required">"Не удалось запустить службу VPN. Возможно, требуется перезагрузить ваше устройство."</string>
<string name="profile_invalid_input">"No valid profile data found."</string>
<string name="profile_invalid_input">"Не найдено действительных данных профиля."</string>
<!-- alert category -->
<string name="yes">"Да"</string>
......@@ -79,13 +74,13 @@
<!-- menu category -->
<string name="profiles">"Профили"</string>
<string name="settings">"Настройки"</string>
<string name="faq">"FAQ"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
<string name="faq">"ЧаВо"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.ru.md"</string>
<string name="about">"О приложении"</string>
<string name="about_title">"Shadowsocks %s"</string>
<string name="edit">"Изменить"</string>
<string name="share">"Поделиться"</string>
<string name="add_profile">"Добавить Профиль"</string>
<string name="add_profile">"Добавить профиль"</string>
<string name="action_apply_all">"Применить настройки для всех профилей"</string>
<string name="action_export">"Экспортировать в буфер обмена"</string>
<string name="action_import">"Импортировать из буфера обмена"</string>
......@@ -101,7 +96,7 @@
<string name="delete">"Удалить"</string>
<string name="delete_confirm_prompt">"Вы уверены, что хотите удалить этот профиль?"</string>
<string name="share_qr_nfc">"QR-код/NFC"</string>
<string name="add_profile_dialog">"Добавить этот Профиль Shadowsocks?"</string>
<string name="add_profile_dialog">"Добавить этот профиль Shadowsocks?"</string>
<string name="add_profile_methods_scan_qr_code">"Сканировать QR-код"</string>
<plurals name="removed">
<item quantity="one">"Удалено %d элементов"</item>
......@@ -135,10 +130,7 @@
<string name="route_entry_bypass_chn">"Все, кроме Китая"</string>
<string name="route_entry_bypass_lan_chn">"Все, кроме LAN и Китая"</string>
<string name="route_entry_chinalist">"Список Китай"</string>
<string name="proxied_apps_summary_v21">"Установить прокси для выбранных приложений"</string>
<string name="acl_rule_templates_generic">"URL/Подсеть/Регулярное выражение (PCRE) имени хоста"</string>
<string name="acl_rule_templates_generic">"Подсеть или имя хоста, записанное регулярным выражением (PCRE)"</string>
<string name="acl_rule_templates_domain">"Доменное имя и все его поддомены"</string>
<!-- plugin -->
......@@ -151,19 +143,21 @@
<string name="add_profile_scanner_permission_required">"Разрешение камеры требуется для сканирования QR код."</string>
<!-- notification category -->
<string name="service_vpn">"VPN Service"</string>
<string name="add_profile_methods_manual_settings">"Manual Settings"</string>
<string name="advanced">"Advanced"</string>
<string name="service_mode">"Service mode"</string>
<string name="service_mode_proxy">"Proxy only"</string>
<string name="service_mode_vpn">"VPN"</string>
<string name="service_mode_transproxy">"Transproxy"</string>
<string name="port_proxy">"SOCKS5 proxy port"</string>
<string name="port_local_dns">"Local DNS port"</string>
<string name="port_transproxy">"Transproxy port"</string>
<string name="service_proxy">"Proxy Service"</string>
<string name="service_transproxy">"Transproxy Service"</string>
<string name="vpn_permission_denied">"Permission denied to create a VPN service"</string>
<string name="auto_connect_summary_v24">"Enable Shadowsocks on startup. Recommended to use always-on VPN
instead"</string>
<string name="service_vpn">"Служба VPN"</string>
<string name="add_profile_methods_manual_settings">"Ручные настройки"</string>
<string name="advanced">"Дополнительно"</string>
<string name="service_mode">"Режим"</string>
<string name="service_mode_proxy">"Только прокси"</string>
<string name="service_mode_transproxy">"Прозрачный прокси"</string>
<string name="port_proxy">"Порт SOCKS5 прокси"</string>
<string name="port_local_dns">"Локальный порт DNS"</string>
<string name="port_transproxy">"Порт прозрачного прокси"</string>
<string name="service_proxy">"Служба прокси"</string>
<string name="service_transproxy">"Служба прозрачный прокси"</string>
<string name="vpn_permission_denied">"Нет разрешения на создание VPN соединения"</string>
<string name="auto_connect_summary_v24">"Включить Shadowsocks во время запуска. Лучше использовать режим постоянной VPN."</string>
<string name="speed">"%s/с"</string>
<string name="direct_boot_aware">"Непосредственная загрузка"</string>
<string name="direct_boot_aware_summary">"Позволить Shadowsocks запускаться до того, как устройство будет разблокировано (данные выбранного профиля будут хуже защищены)"</string>
<string name="acl_rule_online_config">"URL конфигурации"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">"影梭"</string>
<string name="quick_toggle">"开关"</string>
<!-- misc -->
<string name="profile">"配置文件"</string>
<string name="profile_summary">"新建或切换到其他配置文件"</string>
<string name="remote_dns">"远程 DNS"</string>
<string name="stat_summary">"上传: \t%3$s\t↑\t%1$s/s
下载: \t%4$s\t↓\t%2$s/s"</string>
<string name="stat_summary">"上传: \t%3$s\t↑\t%1$s
下载: \t%4$s\t↓\t%2$s"</string>
<string name="connection_test_pending">"检查网络连接"</string>
<string name="connection_test_testing">"测试中…"</string>
<string name="connection_test_available">"连接成功:延时 %d 毫秒"</string>
<string name="connection_test_error">"失败:%s"</string>
<string name="connection_test_fail">"无互联网连接"</string>
<string name="connection_test_error_status_code">"状态码无效(#%d)"</string>
<!-- proxy category -->
......@@ -29,7 +21,6 @@
<!-- proxy category -->
<string name="profile_name">"配置名称"</string>
<string name="proxy">"服务器"</string>
<string name="remote_port">"远程端口"</string>
<string name="sitekey">"密码"</string>
......@@ -44,7 +35,6 @@
<string name="route_list">"路由"</string>
<string name="route_entry_gfwlist">"GFW 列表"</string>
<string name="proxied_apps">"分应用 VPN"</string>
<string name="proxied_apps_summary">"允许部分应用绕过 VPN"</string>
<string name="on">"启用"</string>
<string name="bypass_apps">"绕行模式"</string>
......@@ -81,7 +71,6 @@
<string name="profiles">"配置文件"</string>
<string name="settings">"设置选项"</string>
<string name="faq">"常见问题"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
<string name="about">"关于"</string>
<string name="about_title">"影梭 (Shadowsocks) %s"</string>
<string name="edit">"编辑"</string>
......@@ -133,10 +122,7 @@
<string name="route_entry_bypass_chn">"绕过中国大陆地址"</string>
<string name="route_entry_bypass_lan_chn">"绕过局域网及中国大陆地址"</string>
<string name="route_entry_chinalist">"仅代理中国大陆地址"</string>
<string name="proxied_apps_summary_v21">"为应用程序分别设置代理"</string>
<string name="acl_rule_templates_generic">"URL/子网/域名 PCRE 正则表达式"</string>
<string name="acl_rule_templates_generic">"子网/域名 PCRE 正则表达式"</string>
<string name="acl_rule_templates_domain">"域名及其子域名"</string>
<!-- plugin -->
......@@ -154,7 +140,6 @@
<string name="advanced">"高级选项"</string>
<string name="service_mode">"服务模式"</string>
<string name="service_mode_proxy">"仅代理"</string>
<string name="service_mode_vpn">"VPN"</string>
<string name="service_mode_transproxy">"透明代理"</string>
<string name="port_proxy">"SOCKS5 代理端口"</string>
<string name="port_local_dns">"本地 DNS 端口"</string>
......@@ -163,4 +148,7 @@
<string name="service_transproxy">"透明代理模式"</string>
<string name="vpn_permission_denied">"创建 VPN 服务权限不足"</string>
<string name="auto_connect_summary_v24">"允许 Shadowsocks 随系统启动,建议使用始终开启的 VPN"</string>
<string name="direct_boot_aware">"直接启动"</string>
<string name="direct_boot_aware_summary">"允许在设备解锁前启动服务(选中的配置信息会不那么安全)"</string>
<string name="acl_rule_online_config">"在线规则文件 URL"</string>
</resources>
\ No newline at end of file
......@@ -37,10 +37,8 @@
<string name="ipv6_summary">"向遠端重新導向 IPv6 流量"</string>
<string name="route_list">"路由"</string>
<string name="route_entry_gfwlist">"GFW List"</string>
<string name="proxied_apps">"個別應用程式的 Proxy"</string>
<string name="proxied_apps_summary">"為已選擇的應用程式設定 Proxy,在 Android 4.X 以下需要開啟 NAT 模式"</string>
<string name="proxied_apps">"個別應用程式的 VPN"</string>
<string name="proxied_apps_summary">"為已選擇的應用程式設定 VPN"</string>
<string name="on">"開"</string>
<string name="bypass_apps">"略過模式"</string>
<string name="bypass_apps_summary">"啟用此選項,會略過已選擇的應用程式"</string>
......@@ -57,7 +55,6 @@
<string name="service_failed">"連線至遠端伺服器失敗"</string>
<string name="stop">"停止"</string>
<string name="stopping">"關閉中…"</string>
<string name="vpn_error">"%s"</string>
<string name="reboot_required">"VPN 服務啟動失敗。您或許需要重新啟動您的裝置。"</string>
<string name="profile_invalid_input">"未找到有效的設定檔資料。"</string>
......@@ -76,7 +73,6 @@
<string name="profiles">"設定檔"</string>
<string name="settings">"設定"</string>
<string name="faq">"常見問題"</string>
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
<string name="about">"關於"</string>
<string name="about_title">"Shadowsocks %s"</string>
<string name="edit">"編輯"</string>
......@@ -128,10 +124,7 @@
<string name="route_entry_bypass_chn">"略過中國大陸"</string>
<string name="route_entry_bypass_lan_chn">"略過區域網路及中國大陸"</string>
<string name="route_entry_chinalist">"China List"</string>
<string name="proxied_apps_summary_v21">"為已選擇的應用程式設定 Proxy"</string>
<string name="acl_rule_templates_generic">"URL/子網路/主機名稱 PCRE 模式"</string>
<string name="acl_rule_templates_generic">"子網路/主機名稱 PCRE 模式"</string>
<string name="acl_rule_templates_domain">"網域及其所有子網域"</string>
<!-- plugin -->
......@@ -149,7 +142,6 @@
<string name="advanced">"高級"</string>
<string name="service_mode">"服務模式"</string>
<string name="service_mode_proxy">"仅代理"</string>
<string name="service_mode_vpn">"VPN"</string>
<string name="service_mode_transproxy">"透明代理"</string>
<string name="port_proxy">"SOCKS5 代理連接埠"</string>
<string name="port_local_dns">"本地 DNS 連接埠"</string>
......
......@@ -224,7 +224,7 @@
<string-array name="acl_rule_templates" translatable="false">
<item>@string/acl_rule_templates_generic</item>
<item>@string/acl_rule_templates_domain</item>
<item>URL</item>
<item>@string/acl_rule_online_config</item>
</string-array>
<string-array name="service_modes">
......
......@@ -2,7 +2,6 @@
<resources>
<dimen name="profile_item_max_width">480dp</dimen>
<dimen name="qr_code_size">250dp</dimen>
<dimen name="margin_small">8dp</dimen>
<!-- TODO: Remove when this issue is fixed: https://github.com/JorgeCastilloPrz/FABProgressCircle/issues/19 -->
<dimen name="fab_margin_top">-44dp</dimen>
<dimen name="profile_padding">8dp</dimen>
<dimen name="bottom_sheet_padding">8dp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="com_google_android_gms_fonts_certs">
<item>@array/com_google_android_gms_fonts_certs_dev</item>
<item>@array/com_google_android_gms_fonts_certs_prod</item>
</array>
<string-array name="com_google_android_gms_fonts_certs_dev" translatable="false">
<item>
MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
</item>
</string-array>
<string-array name="com_google_android_gms_fonts_certs_prod" translatable="false">
<item>
MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
</item>
</string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="preloaded_fonts" translatable="false">
<item>@font/iceland</item>
</array>
</resources>
......@@ -17,8 +17,8 @@
<string name="port_transproxy">Transproxy port</string>
<string name="remote_dns">Remote DNS</string>
<string name="traffic" translatable="false">%s↑\t%s↓</string>
<string name="stat_summary">Sent: \t\t\t\t\t%3$s\t↑\t%1$s/s\nReceived: \t%4$s\t↓\t%2$s/s</string>
<string name="traffic">%s↑\t%s↓</string>
<string name="stat_summary">Sent: \t\t\t\t\t%3$s\t↑\t%1$s\nReceived: \t%4$s\t↓\t%2$s</string>
<string name="speed">%s/s</string>
<plurals name="bytes">
<item quantity="one">Byte</item>
......@@ -57,6 +57,9 @@
<string name="auto_connect_summary">Enable Shadowsocks on startup</string>
<string name="auto_connect_summary_v24">Enable Shadowsocks on startup. Recommended to use always-on VPN
instead</string>
<string name="direct_boot_aware">Direct Boot Aware</string>
<string name="direct_boot_aware_summary">Allow Shadowsocks to start before your device is unlocked (your selected
profile information will be less protected)</string>
<string name="tcp_fastopen_summary">Toggling requires ROOT permission</string>
<string name="tcp_fastopen_summary_unsupported">Unsupported kernel version: %s &lt; 3.7.1</string>
<string name="udp_dns">DNS Forwarding</string>
......@@ -136,6 +139,7 @@
<string name="action_add_rule">Add rule(s)…</string>
<string name="acl_rule_templates_generic">Subnet or Hostname PCRE pattern</string>
<string name="acl_rule_templates_domain">Domain name and all its subdomain names</string>
<string name="acl_rule_online_config">URL to online config</string>
<string name="edit_rule">Edit rule</string>
<!-- plugin -->
......
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content xmlns:tools="http://schemas.android.com/tools"
tools:ignore="FullBackupContent">
<include domain="database" path="profile.db"/>
<!-- No device storage yet in Android 6.0 -->
<include domain="database" path="config.db"/>
<include domain="device_database" path="config.db"/>
</full-backup-content>
......@@ -5,6 +5,11 @@
android:persistent="false"
android:summary="@string/auto_connect_summary"
android:title="@string/auto_connect"/>
<!-- Direct Boot Aware alone doesn't do anything without auto connect -->
<SwitchPreference android:key="directBootAware"
android:dependency="isAutoConnect"
android:summary="@string/direct_boot_aware_summary"
android:title="@string/direct_boot_aware"/>
<SwitchPreference android:key="tcp_fastopen"
android:summary="@string/tcp_fastopen_summary"
android:title="TCP Fast Open"/>
......
......@@ -13,6 +13,7 @@
<AutoSummaryEditTextPreference
android:key="proxy"
app:pref_summaryHasText="%s"
android:singleLine="true"
android:title="@string/proxy"/>
<AutoSummaryEditTextPreference
android:key="remotePortNum"
......@@ -25,6 +26,7 @@
app:pref_summaryPasswordSubstituteLength="0"
android:key="sitekey"
app:pref_summaryHasText="%s"
android:singleLine="true"
android:title="@string/sitekey"/>
<SimpleMenuPreference
android:key="encMethod"
......
package com.github.shadowsocks
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see [Testing documentation](http://d.android.com/tools/testing)
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, (2 + 2).toLong())
}
}
\ No newline at end of file
/*******************************************************************************
* *
* 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 org.junit.Assert
import org.junit.Test
class KeyValuePairTest {
@Test
fun putAndGet() {
val kvp = KeyValuePair()
Assert.assertEquals(true, kvp.put(true).boolean)
Assert.assertEquals(3f, kvp.put(3f).float)
Assert.assertEquals(3, kvp.put(3).int)
Assert.assertEquals(3L, kvp.put(3L).long)
Assert.assertEquals("3", kvp.put("3").string)
val set = (0 until 3).map(Int::toString).toSet()
Assert.assertEquals(set, kvp.put(set).stringSet)
Assert.assertEquals(null, kvp.boolean)
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply from: 'gradle-mvn-push.gradle'
android {
buildToolsVersion rootProject.buildToolsVersion
compileSdkVersion rootProject.sdkVersion
defaultConfig {
......@@ -21,7 +24,6 @@ android {
}
dependencies {
api "com.android.support:preference-v7:$supportLibraryVersion"
api "com.android.support:preference-v14:$supportLibraryVersion"
api "com.takisoft.fix:preference-v7:$takisoftFixVersion"
api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
......
/*
* Copyright 2013 Chris Banes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
apply plugin: 'maven'
apply plugin: 'signing'
@SuppressWarnings(["GroovyUnusedDeclaration", "GrMethodMayBeStatic"])
def isReleaseBuild() {
return !android.defaultConfig.versionName.contains("SNAPSHOT")
}
@SuppressWarnings("GroovyUnusedDeclaration")
def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}
@SuppressWarnings("GroovyUnusedDeclaration")
def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}
@SuppressWarnings("GroovyUnusedDeclaration")
def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}
@SuppressWarnings("GroovyUnusedDeclaration")
def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
pom.groupId = 'com.github.shadowsocks'
pom.artifactId = 'plugin'
pom.version = android.defaultConfig.versionName
repository(url: getReleaseRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
snapshotRepository(url: getSnapshotRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
pom.project {
name 'Shadowsocks Plugin'
packaging 'aar'
description 'Shadowsocks Plugin'
url 'https://github.com/shadowsocks/shadowsocks-android'
scm {
url 'https://github.com/shadowsocks/shadowsocks-android.git'
connection 'scm:git:git://github.com/shadowsocks/shadowsocks-android.git'
developerConnection 'scm:git:git@github.com:shadowsocks/shadowsocks-android.git'
}
licenses {
license {
name 'GPLv3'
url 'https://www.gnu.org/licenses/gpl-3.0.html'
distribution 'repo'
}
}
developers {
developer {
id 'madeye'
name 'Max Lv'
url 'https://github.com/madeye'
}
developer {
id 'Mygod'
name 'Mygod Studio'
url 'https://github.com/Mygod'
}
}
}
}
}
}
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
android.libraryVariants.all { variant ->
def javadocTask = task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
description "Generates Javadoc for $variant.name."
source = variant.javaCompiler.source
ext.androidJar = project.files(android.getBootClasspath().join(File.pathSeparator))
classpath = files(variant.javaCompiler.classpath.files) + files(ext.androidJar)
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
javadocTask.dependsOn variant.javaCompiler
def jarJavadocTask = task("jar${variant.name.capitalize()}Javadoc", type: Jar) {
description "Generate Javadoc Jar for $variant.name"
classifier = 'javadoc'
from javadocTask.destinationDir
}
jarJavadocTask.dependsOn javadocTask
artifacts.add('archives', jarJavadocTask)
def jarSourceTask = task("jar${variant.name.capitalize()}Sources", type: Jar) {
description "Generates Java Sources for $variant.name."
classifier = 'sources'
from variant.javaCompiler.source
}
jarSourceTask.dependsOn variant.javaCompiler
artifacts.add('archives', jarSourceTask)
}
}
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="ImpliedQuantity" severity="warning" />
<issue id="ExtraTranslation" severity="warning" />
<issue id="MissingTranslation" severity="informational" />
</lint>
......@@ -18,35 +18,33 @@
* *
*******************************************************************************/
package com.github.shadowsocks.plugin;
package com.github.shadowsocks.plugin
/**
* The contract between the plugin provider and host. Contains definitions for the supported actions, extras, etc.
*
* This class is written in Java to keep Java interoperability.
*/
public final class PluginContract {
private PluginContract() { }
object PluginContract {
/**
* ContentProvider Action: Used for NativePluginProvider.
*
* Constant Value: "com.github.shadowsocks.plugin.ACTION_NATIVE_PLUGIN"
*/
public static final String ACTION_NATIVE_PLUGIN = "com.github.shadowsocks.plugin.ACTION_NATIVE_PLUGIN";
const val ACTION_NATIVE_PLUGIN = "com.github.shadowsocks.plugin.ACTION_NATIVE_PLUGIN"
/**
* Activity Action: Used for ConfigurationActivity.
*
* Constant Value: "com.github.shadowsocks.plugin.ACTION_CONFIGURE"
*/
public static final String ACTION_CONFIGURE = "com.github.shadowsocks.plugin.ACTION_CONFIGURE";
const val ACTION_CONFIGURE = "com.github.shadowsocks.plugin.ACTION_CONFIGURE"
/**
* Activity Action: Used for HelpActivity or HelpCallback.
*
* Constant Value: "com.github.shadowsocks.plugin.ACTION_HELP"
*/
public static final String ACTION_HELP = "com.github.shadowsocks.plugin.ACTION_HELP";
const val ACTION_HELP = "com.github.shadowsocks.plugin.ACTION_HELP"
/**
* The lookup key for a string that provides the plugin entry binary.
......@@ -55,7 +53,7 @@ public final class PluginContract {
*
* Constant Value: "com.github.shadowsocks.plugin.EXTRA_ENTRY"
*/
public static final String EXTRA_ENTRY = "com.github.shadowsocks.plugin.EXTRA_ENTRY";
const val EXTRA_ENTRY = "com.github.shadowsocks.plugin.EXTRA_ENTRY"
/**
* The lookup key for a string that provides the options as a string.
*
......@@ -63,34 +61,34 @@ public final class PluginContract {
*
* Constant Value: "com.github.shadowsocks.plugin.EXTRA_OPTIONS"
*/
public static final String EXTRA_OPTIONS = "com.github.shadowsocks.plugin.EXTRA_OPTIONS";
const val EXTRA_OPTIONS = "com.github.shadowsocks.plugin.EXTRA_OPTIONS"
/**
* The lookup key for a CharSequence that provides user relevant help message.
*
* Example: "obfs=<http|tls> Enable obfuscating: HTTP or TLS (Experimental).
* Example: "obfs=<http></http>|tls> Enable obfuscating: HTTP or TLS (Experimental).
* obfs-host=<host_name> Hostname for obfuscating (Experimental)."
*
* Constant Value: "com.github.shadowsocks.plugin.EXTRA_HELP_MESSAGE"
*/
public static final String EXTRA_HELP_MESSAGE = "com.github.shadowsocks.plugin.EXTRA_HELP_MESSAGE";
</host_name> */
const val EXTRA_HELP_MESSAGE = "com.github.shadowsocks.plugin.EXTRA_HELP_MESSAGE"
/**
* The metadata key to retrieve plugin id. Required for plugins.
*
* Constant Value: "com.github.shadowsocks.plugin.id"
*/
public static final String METADATA_KEY_ID = "com.github.shadowsocks.plugin.id";
const val METADATA_KEY_ID = "com.github.shadowsocks.plugin.id"
/**
* The metadata key to retrieve default configuration. Default value is empty.
*
* Constant Value: "com.github.shadowsocks.plugin.default_config"
*/
public static final String METADATA_KEY_DEFAULT_CONFIG = "com.github.shadowsocks.plugin.default_config";
const val METADATA_KEY_DEFAULT_CONFIG = "com.github.shadowsocks.plugin.default_config"
public static final String METHOD_GET_EXECUTABLE = "shadowsocks:getExecutable";
const val METHOD_GET_EXECUTABLE = "shadowsocks:getExecutable"
/** ConfigurationActivity result: fallback to manual edit mode. */
public static final int RESULT_FALLBACK = 1;
const val RESULT_FALLBACK = 1
/**
* Relative to the file to be copied. This column is required.
......@@ -99,7 +97,7 @@ public final class PluginContract {
*
* Type: String
*/
public static final String COLUMN_PATH = "path";
const val COLUMN_PATH = "path"
/**
* File mode bits. Default value is "644".
*
......@@ -107,14 +105,14 @@ public final class PluginContract {
*
* Type: String
*/
public static final String COLUMN_MODE = "mode";
const val COLUMN_MODE = "mode"
/**
* The scheme for general plugin actions.
*/
public static final String SCHEME = "plugin";
const val SCHEME = "plugin"
/**
* The authority for general plugin actions.
*/
public static final String AUTHORITY = "com.github.shadowsocks";
const val AUTHORITY = "com.github.shadowsocks"
}
......@@ -18,110 +18,87 @@
* *
*******************************************************************************/
package com.github.shadowsocks.plugin;
package com.github.shadowsocks.plugin
import android.text.TextUtils;
import java.util.HashMap;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.*
/**
* Helper class for processing plugin options.
*
* Based on: https://github.com/apache/ant/blob/588ce1f/src/main/org/apache/tools/ant/types/Commandline.java
*/
public final class PluginOptions extends HashMap<String, String> {
public PluginOptions() {
super();
}
public PluginOptions(int initialCapacity) {
super(initialCapacity);
}
public PluginOptions(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
class PluginOptions : HashMap<String, String?> {
var id = ""
// TODO: this method is not needed since API 24
public String getOrDefault(Object key, String defaultValue) {
String v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
constructor() : super()
constructor(initialCapacity: Int) : super(initialCapacity)
constructor(initialCapacity: Int, loadFactor: Float) : super(initialCapacity, loadFactor)
private PluginOptions(String options, boolean parseId) {
this();
if (TextUtils.isEmpty(options)) return;
final StringTokenizer tokenizer = new StringTokenizer(options + ';', "\\=;", true);
final StringBuilder current = new StringBuilder();
String key = null;
private constructor(options: String?, parseId: Boolean) : this() {
@Suppress("NAME_SHADOWING")
var parseId = parseId
if (options.isNullOrEmpty()) return
val tokenizer = StringTokenizer(options + ';', "\\=;", true)
val current = StringBuilder()
var key: String? = null
while (tokenizer.hasMoreTokens()) {
String nextToken = tokenizer.nextToken();
if ("\\".equals(nextToken)) current.append(tokenizer.nextToken());
else if ("=".equals(nextToken) && key == null) {
key = current.toString();
current.setLength(0);
} else if (";".equals(nextToken)) {
val nextToken = tokenizer.nextToken()
when (nextToken) {
"\\" -> current.append(tokenizer.nextToken())
"=" -> if (key == null) {
key = current.toString()
current.setLength(0)
} else current.append(nextToken)
";" -> {
if (key != null) {
put(key, current.toString());
key = null;
} else if (current.length() > 0)
if (parseId) id = current.toString(); else put(current.toString(), null);
current.setLength(0);
parseId = false;
} else current.append(nextToken);
put(key, current.toString())
key = null
} else if (current.isNotEmpty())
if (parseId) id = current.toString() else put(current.toString(), null)
current.setLength(0)
parseId = false
}
else -> current.append(nextToken)
}
public PluginOptions(String options) {
this(options, true);
}
public PluginOptions(String id, String options) {
this(options, false);
this.id = id;
}
public String id = "";
constructor(options: String?) : this(options, true)
constructor(id: String, options: String?) : this(options, false) {
this.id = id
}
private static void append(StringBuilder result, String str) {
for (int i = 0; i < str.length(); ++i) {
char ch = str.charAt(i);
switch (ch) {
case '\\': case '=': case ';': result.append('\\'); // intentionally no break
default: result.append(ch);
private fun append(result: StringBuilder, str: String) = (0 until str.length)
.map { str[it] }
.forEach {
when (it) {
'\\', '=', ';' -> {
result.append('\\') // intentionally no break
result.append(it)
}
else -> result.append(it)
}
}
public String toString(boolean trimId) {
final StringBuilder result = new StringBuilder();
if (!trimId) if (TextUtils.isEmpty(id)) return ""; else append(result, id);
for (Entry<String, String> entry : entrySet()) {
if (result.length() > 0) result.append(';');
append(result, entry.getKey());
String value = entry.getValue();
fun toString(trimId: Boolean): String {
val result = StringBuilder()
if (!trimId) if (id.isEmpty()) return "" else append(result, id)
for ((key, value) in entries) {
if (result.isNotEmpty()) result.append(';')
append(result, key)
if (value != null) {
result.append('=');
append(result, value);
result.append('=')
append(result, value)
}
}
return result.toString();
}
@Override
public String toString() {
return toString(true);
return result.toString()
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
PluginOptions that = (PluginOptions) o;
return Objects.equals(id, that.id) && super.equals(that);
}
override fun toString(): String = toString(true)
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id);
override fun equals(other: Any?): Boolean {
if (this === other) return true
return javaClass == other?.javaClass && super.equals(other) && id == (other as PluginOptions).id
}
override fun hashCode(): Int = Objects.hash(super.hashCode(), id)
}
......@@ -6,6 +6,7 @@
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:touchscreenBlocksFocus="false"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:id="@+id/toolbar" />
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="fab_margin_top">-28dp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- proxy category -->
<string name="proxy_cat">"サーバー設定"</string>
<!-- feature category -->
<string name="feature_cat">"ファンクション設定"</string>
<!-- alert category -->
<string name="feature_cat">"機能設定"</string>
<string name="unsaved_changes_prompt">"変更は保存されておりません、保存しますか?"</string>
<string name="yes">"はい"</string>
<string name="no">"いいえ"</string>
<string name="unsaved_changes_prompt">"変更は適応されておりません、保存しますか?"</string>
<string name="apply">"適用"</string>
<string name="apply">"適応"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- proxy category -->
<string name="proxy_cat">"Настройки Сервера"</string>
<!-- feature category -->
<string name="feature_cat">"Дополнительные Настройки"</string>
<!-- alert category -->
<string name="proxy_cat">"Настройки сервера"</string>
<string name="feature_cat">"Настройки опций"</string>
<string name="unsaved_changes_prompt">"Сохранить изменения?"</string>
<string name="yes">"Да"</string>
<string name="no">"Нет"</string>
<string name="unsaved_changes_prompt">"Изменения не сохранены. Сохранить?"</string>
<string name="apply">"Применить"</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- proxy category -->
<string name="proxy_cat">"服务器设置"</string>
<!-- feature category -->
<string name="feature_cat">"功能设置"</string>
<!-- alert category -->
<string name="unsaved_changes_prompt">"是否要保存修改?"</string>
<string name="yes">"是"</string>
<string name="no">"否"</string>
<string name="unsaved_changes_prompt">"保存修改吗?"</string>
<string name="apply">"应用"</string>
</resources>
\ No newline at end of file
package com.github.shadowsocks.plugin;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
/*******************************************************************************
* *
* 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.plugin
import org.junit.Assert
import org.junit.Test
class PluginOptionsTest {
@Test
fun equal() {
val o1 = PluginOptions("obfs-local;obfs=http;obfs-host=localhost")
val o2 = PluginOptions("obfs-local", "obfs-host=localhost;obfs=http")
Assert.assertEquals(o1.hashCode(), o2.hashCode())
Assert.assertEquals(true, o1 == o2)
val o3 = PluginOptions(o1.toString(false))
Assert.assertEquals(true, o2 == o3)
val o4 = PluginOptions(o2.id, o2.toString())
Assert.assertEquals(true, o3 == o4)
}
}
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