mirror of https://github.com/NekoX-Dev/NekoX.git
proxy: remove all ss, ssr and v2ray stuff. fix proxy selection saving
This commit is contained in:
parent
34b440b867
commit
a66f24ccef
|
@ -146,103 +146,11 @@ jobs:
|
|||
run: |
|
||||
export NATIVE_TARGET="${{ matrix.flavor }}"
|
||||
./run libs native
|
||||
v2ray:
|
||||
name: Native Build (V2ray)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status v2ray > v2ray_status
|
||||
- name: V2ray Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/libv2ray.aar
|
||||
key: ${{ hashFiles('bin/libs/v2ray/*', 'v2ray_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Install Golang
|
||||
uses: actions/setup-go@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
go-version: 1.16
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs v2ray
|
||||
shadowsocks:
|
||||
name: Native Build (Shadowsocks)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status ss-rust/src/main/rust/shadowsocks-rust > shadowsocks_status
|
||||
- name: Shadowsocks Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ss-rust-release.aar
|
||||
key: ${{ hashFiles('shadowsocks_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Install Rust
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run init action shadowsocks
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs shadowsocks
|
||||
shadowsocksr:
|
||||
name: Native Build (ShadowsocksR)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status 'ssr-libev/*' > shadowsocksr_status
|
||||
- name: ShadowsocksR Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ssr-libev-release.aar
|
||||
key: ${{ hashFiles('shadowsocksr_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs ssr
|
||||
build:
|
||||
name: Gradle Build
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- native
|
||||
- v2ray
|
||||
- shadowsocks
|
||||
- shadowsocksr
|
||||
strategy:
|
||||
matrix:
|
||||
flavor:
|
||||
|
@ -360,7 +268,6 @@ jobs:
|
|||
if: ${{ github.event_name != 'pull_request' && success() }}
|
||||
needs:
|
||||
- native
|
||||
- v2ray
|
||||
- telegram-bot-api
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -376,9 +283,6 @@ jobs:
|
|||
run: |
|
||||
git submodule status TMessagesProj/jni/ffmpeg > ffmpeg_status
|
||||
git submodule status TMessagesProj/jni/boringssl > boringssl_status
|
||||
git submodule status ss-rust/src/main/rust/shadowsocks-rust > shadowsocks_status
|
||||
git submodule status 'ssr-libev/*' > shadowsocksr_status
|
||||
git submodule status v2ray > v2ray_status
|
||||
- name: Native Cache (armeabi-v7a)
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
@ -403,20 +307,12 @@ jobs:
|
|||
path: |
|
||||
TMessagesProj/src/main/libs
|
||||
key: ${{ hashFiles('TMessagesProj/jni/**', 'ffmpeg_status', 'boringssl_status') }}-x86_64
|
||||
- name: V2ray Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/libv2ray.aar
|
||||
key: ${{ hashFiles('bin/libs/v2ray/*', 'v2ray_status') }}
|
||||
- name: Build Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/build
|
||||
TMessagesProj/.cxx
|
||||
ss-rust/build
|
||||
ssr-rust/build
|
||||
openpgp-api/build
|
||||
key: build-cache
|
||||
- name: Configure Gradle
|
||||
|
|
|
@ -155,106 +155,11 @@ jobs:
|
|||
run: |
|
||||
export NATIVE_TARGET="${{ matrix.flavor }}"
|
||||
./run libs native
|
||||
v2ray:
|
||||
name: Native Build (V2ray)
|
||||
runs-on: ubuntu-latest
|
||||
needs: check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status v2ray > v2ray_status
|
||||
- name: V2ray Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/libv2ray.aar
|
||||
key: ${{ hashFiles('bin/libs/v2ray/*', 'v2ray_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Install Golang
|
||||
uses: actions/setup-go@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
go-version: 1.16
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs v2ray
|
||||
shadowsocks:
|
||||
name: Native Build (Shadowsocks)
|
||||
runs-on: ubuntu-latest
|
||||
needs: check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status ss-rust/src/main/rust/shadowsocks-rust > shadowsocks_status
|
||||
- name: Shadowsocks Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ss-rust-release.aar
|
||||
key: ${{ hashFiles('shadowsocks_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Install Rust
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run init action shadowsocks
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs shadowsocks
|
||||
shadowsocksr:
|
||||
name: Native Build (ShadowsocksR)
|
||||
runs-on: ubuntu-latest
|
||||
needs: check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch Status
|
||||
run: git submodule status 'ssr-libev/*' > shadowsocksr_status
|
||||
- name: ShadowsocksR Cache
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ssr-libev-release.aar
|
||||
key: ${{ hashFiles('shadowsocksr_status') }}
|
||||
- name: Setup Android SDK Tools
|
||||
uses: android-actions/setup-android@v2
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install NDK
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.4.7075529" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
||||
echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
|
||||
- name: Native Build
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./run libs ssr
|
||||
build:
|
||||
name: Gradle Build
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- native
|
||||
- v2ray
|
||||
- shadowsocks
|
||||
- shadowsocksr
|
||||
strategy:
|
||||
matrix:
|
||||
flavor:
|
||||
|
@ -276,9 +181,6 @@ jobs:
|
|||
run: |
|
||||
git submodule status TMessagesProj/jni/ffmpeg > ffmpeg_status
|
||||
git submodule status TMessagesProj/jni/boringssl > boringssl_status
|
||||
git submodule status ss-rust/src/main/rust/shadowsocks-rust > shadowsocks_status
|
||||
git submodule status 'ssr-libev/*' > shadowsocksr_status
|
||||
git submodule status v2ray > v2ray_status
|
||||
- name: Native Cache (armeabi-v7a)
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
@ -303,24 +205,6 @@ jobs:
|
|||
path: |
|
||||
TMessagesProj/src/main/libs
|
||||
key: ${{ hashFiles('TMessagesProj/jni/**', 'ffmpeg_status', 'boringssl_status') }}-x86_64
|
||||
- name: V2ray Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/libv2ray.aar
|
||||
key: ${{ hashFiles('bin/libs/v2ray/*', 'v2ray_status') }}
|
||||
- name: Shadowsocks Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ss-rust-release.aar
|
||||
key: ${{ hashFiles('shadowsocks_status') }}
|
||||
- name: ShadowsocksR Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
TMessagesProj/libs/ssr-libev-release.aar
|
||||
key: ${{ hashFiles('shadowsocksr_status') }}
|
||||
- name: Fix Gradle Memoery
|
||||
run: |
|
||||
sed -i -e "s/16384/6144/g" gradle.properties
|
||||
|
|
|
@ -14,29 +14,3 @@
|
|||
url = https://github.com/webmproject/libvpx
|
||||
ignore = dirty
|
||||
|
||||
[submodule "ss-rust/src/main/rust/shadowsocks-rust"]
|
||||
path = ss-rust/src/main/rust/shadowsocks-rust
|
||||
url = https://github.com/shadowsocks/shadowsocks-rust.git
|
||||
|
||||
[submodule "shadowsocksr-libev"]
|
||||
path = ssr-libev/src/main/jni/shadowsocks-libev
|
||||
url = https://github.com/shadowsocksRb/shadowsocksr-libev.git
|
||||
[submodule "ssr-libev/src/main/jni/libancillary"]
|
||||
path = ssr-libev/src/main/jni/libancillary
|
||||
url = https://github.com/shadowsocks/libancillary.git
|
||||
[submodule "ssr-libev/src/main/jni/mbedtls"]
|
||||
path = ssr-libev/src/main/jni/mbedtls
|
||||
url = https://github.com/ARMmbed/mbedtls
|
||||
[submodule "ssr-libev/src/main/jni/pcre"]
|
||||
path = ssr-libev/src/main/jni/pcre
|
||||
url = https://android.googlesource.com/platform/external/pcre
|
||||
[submodule "ssr-libev/src/main/jni/libsodium"]
|
||||
path = ssr-libev/src/main/jni/libsodium
|
||||
url = https://github.com/jedisct1/libsodium.git
|
||||
branch = stable
|
||||
[submodule "ssr-libev/src/main/jni/re2"]
|
||||
path = ssr-libev/src/main/jni/re2
|
||||
url = https://github.com/google/re2.git
|
||||
[submodule "v2ray"]
|
||||
path = v2ray
|
||||
url = https://github.com/nekohasekai/AndroidLibV2rayLite
|
||||
|
|
|
@ -169,6 +169,7 @@ import java.io.RandomAccessFile;
|
|||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.IDN;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -198,7 +199,6 @@ import tw.nekomimi.nekogram.NekoXConfig;
|
|||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.EnvUtil;
|
||||
import tw.nekomimi.nekogram.utils.FileUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
import static com.v2ray.ang.V2RayConfig.SSR_PROTOCOL;
|
||||
|
@ -3636,27 +3636,68 @@ public class AndroidUtilities {
|
|||
if (intent == null) {
|
||||
return false;
|
||||
}
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
|
||||
return false;
|
||||
}
|
||||
Uri data = intent.getData();
|
||||
if (data == null) return false;
|
||||
String link = data.toString();
|
||||
if (link.startsWith("tg://proxy") ||
|
||||
link.startsWith("tg://socks") ||
|
||||
link.startsWith("http://t.me/proxy?") ||
|
||||
link.startsWith("http://t.me/socks?") ||
|
||||
link.startsWith("https://t.me/proxy?") ||
|
||||
link.startsWith("https://t.me/socks?") ||
|
||||
link.startsWith(VMESS_PROTOCOL) ||
|
||||
link.startsWith(VMESS1_PROTOCOL) ||
|
||||
link.startsWith(SS_PROTOCOL) ||
|
||||
link.startsWith(SSR_PROTOCOL) ||
|
||||
link.startsWith(WS_PROTOCOL) ||
|
||||
link.startsWith(WSS_PROTOCOL) ||
|
||||
link.startsWith(TROJAN_PROTOCOL)/*||
|
||||
data.startsWith(RB_PROTOCOL)*/) {
|
||||
return ProxyUtil.importProxy(activity, link);
|
||||
try {
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
|
||||
return false;
|
||||
}
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
String user = null;
|
||||
String password = null;
|
||||
String port = null;
|
||||
String address = null;
|
||||
String secret = null;
|
||||
String scheme = data.getScheme();
|
||||
if (scheme != null) {
|
||||
if ((scheme.equals("http") || scheme.equals("https"))) {
|
||||
String host = data.getHost().toLowerCase();
|
||||
if (host.equals("telegram.me") || host.equals("t.me") || host.equals("telegram.dog")) {
|
||||
String path = data.getPath();
|
||||
if (path != null) {
|
||||
if (path.startsWith("/socks") || path.startsWith("/proxy")) {
|
||||
address = data.getQueryParameter("server");
|
||||
if (AndroidUtilities.checkHostForPunycode(address)) {
|
||||
address = IDN.toASCII(address, IDN.ALLOW_UNASSIGNED);
|
||||
}
|
||||
port = data.getQueryParameter("port");
|
||||
user = data.getQueryParameter("user");
|
||||
password = data.getQueryParameter("pass");
|
||||
secret = data.getQueryParameter("secret");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (scheme.equals("tg")) {
|
||||
String url = data.toString();
|
||||
if (url.startsWith("tg:proxy") || url.startsWith("tg://proxy") || url.startsWith("tg:socks") || url.startsWith("tg://socks")) {
|
||||
url = url.replace("tg:proxy", "tg://telegram.org").replace("tg://proxy", "tg://telegram.org").replace("tg://socks", "tg://telegram.org").replace("tg:socks", "tg://telegram.org");
|
||||
data = Uri.parse(url);
|
||||
address = data.getQueryParameter("server");
|
||||
if (AndroidUtilities.checkHostForPunycode(address)) {
|
||||
address = IDN.toASCII(address, IDN.ALLOW_UNASSIGNED);
|
||||
}
|
||||
port = data.getQueryParameter("port");
|
||||
user = data.getQueryParameter("user");
|
||||
password = data.getQueryParameter("pass");
|
||||
secret = data.getQueryParameter("secret");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(address) && !TextUtils.isEmpty(port)) {
|
||||
if (user == null) {
|
||||
user = "";
|
||||
}
|
||||
if (password == null) {
|
||||
password = "";
|
||||
}
|
||||
if (secret == null) {
|
||||
secret = "";
|
||||
}
|
||||
showProxyAlert(activity, address, port, user, password, secret, "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -3782,640 +3823,42 @@ public class AndroidUtilities {
|
|||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> dismissRunnable.run());
|
||||
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit();
|
||||
editor.putBoolean("proxy_enabled", true);
|
||||
editor.putString("proxy_ip", address);
|
||||
int p = Utilities.parseInt(port);
|
||||
editor.putInt("proxy_port", p);
|
||||
|
||||
SharedConfig.ProxyInfo info;
|
||||
|
||||
if (TextUtils.isEmpty(secret)) {
|
||||
|
||||
info = new SharedConfig.ProxyInfo(address, p, user, password, "");
|
||||
|
||||
} else {
|
||||
|
||||
info = new SharedConfig.ProxyInfo(address, p, "", "", secret);
|
||||
|
||||
}
|
||||
|
||||
info.setRemarks(remarks);
|
||||
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
int p = Utilities.parseInt(port);
|
||||
|
||||
SharedConfig.ProxyInfo info;
|
||||
|
||||
if (TextUtils.isEmpty(secret)) {
|
||||
|
||||
info = new SharedConfig.ProxyInfo(address, p, user, password, "");
|
||||
|
||||
} else {
|
||||
|
||||
info = new SharedConfig.ProxyInfo(address, p, "", "", secret);
|
||||
|
||||
}
|
||||
|
||||
info.setRemarks(remarks);
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
public static void showVmessAlert(Context activity, final SharedConfig.VmessProxy info) {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
|
||||
final Runnable dismissRunnable = builder.getDismissRunnable();
|
||||
|
||||
builder.setApplyTopPadding(false);
|
||||
builder.setApplyBottomPadding(false);
|
||||
LinearLayout linearLayout = new LinearLayout(activity);
|
||||
builder.setCustomView(linearLayout);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a = 0; a < 8; a++) {
|
||||
String text = null;
|
||||
String detail = null;
|
||||
if (a == 0) {
|
||||
text = info.bean.getAddress();
|
||||
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
|
||||
} else if (a == 1) {
|
||||
text = "" + info.bean.getPort();
|
||||
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
|
||||
} else if (a == 2) {
|
||||
text = info.bean.getId();
|
||||
detail = LocaleController.getString("VmessUserId", R.string.VmessUserId);
|
||||
} else if (a == 3) {
|
||||
text = info.bean.getSecurity();
|
||||
if ("none".equals(text)) continue;
|
||||
detail = LocaleController.getString("VmessSecurity", R.string.VmessSecurity);
|
||||
} else if (a == 4) {
|
||||
text = info.bean.getNetwork() + (StrUtil.isBlank(info.bean.getStreamSecurity()) ? "" : ", tls");
|
||||
detail = LocaleController.getString("VmessNetwork", R.string.VmessNetwork);
|
||||
} else if (a == 5) {
|
||||
text = info.bean.getHeaderType();
|
||||
if ("none".equals(text)) continue;
|
||||
detail = LocaleController.getString("VmessHeadType", R.string.VmessHeadType);
|
||||
} else if (a == 6) {
|
||||
text = info.bean.getRequestHost();
|
||||
detail = LocaleController.getString("VmessRequestHost", R.string.VmessRequestHost);
|
||||
} else {
|
||||
text = LocaleController.getString("Checking", R.string.Checking);
|
||||
detail = LocaleController.getString("Checking", R.string.Checking);
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
continue;
|
||||
}
|
||||
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
|
||||
cell.setTextAndValue(text, detail, true);
|
||||
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
|
||||
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
if (a == 7) {
|
||||
|
||||
RequestTimeDelegate callback = new RequestTimeDelegate() {
|
||||
@Override
|
||||
public void run(long time) {
|
||||
int c = count.getAndIncrement();
|
||||
String colorKey;
|
||||
if (time != -1) {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else if (c < 2) {
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteRedText4;
|
||||
}
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
info.start();
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
|
||||
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
|
||||
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
|
||||
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
|
||||
info.stop();
|
||||
dismissRunnable.run();
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
if (activity instanceof LaunchActivity) {
|
||||
INavigationLayout layout = ((LaunchActivity) activity).getActionBarLayout();
|
||||
BaseFragment fragment = layout.getLastFragment();
|
||||
if (fragment instanceof ChatActivity) {
|
||||
((ChatActivity) fragment).getUndoView().showWithAction(0, UndoView.ACTION_PROXY_ADDED, null);
|
||||
editor.remove("proxy_secret");
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
editor.remove("proxy_pass");
|
||||
} else {
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_SUCCESS, LocaleController.getString(R.string.ProxyAddedSuccess));
|
||||
editor.putString("proxy_pass", password);
|
||||
}
|
||||
} else {
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_SUCCESS, LocaleController.getString(R.string.ProxyAddedSuccess));
|
||||
}
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
public static void showTrojanAlert(Context activity, final SharedConfig.VmessProxy info) {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
|
||||
final Runnable dismissRunnable = builder.getDismissRunnable();
|
||||
|
||||
builder.setApplyTopPadding(false);
|
||||
builder.setApplyBottomPadding(false);
|
||||
LinearLayout linearLayout = new LinearLayout(activity);
|
||||
builder.setCustomView(linearLayout);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a = 0; a < 4; a++) {
|
||||
String text = null;
|
||||
String detail = null;
|
||||
if (a == 0) {
|
||||
text = info.bean.getAddress();
|
||||
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
|
||||
} else if (a == 1) {
|
||||
text = "" + info.bean.getPort();
|
||||
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
|
||||
} else if (a == 2) {
|
||||
text = info.bean.getId();
|
||||
detail = LocaleController.getString("SSPassword", R.string.SSPassword);
|
||||
} else {
|
||||
text = LocaleController.getString("Checking", R.string.Checking);
|
||||
detail = LocaleController.getString("Checking", R.string.Checking);
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
continue;
|
||||
}
|
||||
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
|
||||
cell.setTextAndValue(text, detail, true);
|
||||
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
|
||||
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
if (a == 3) {
|
||||
|
||||
RequestTimeDelegate callback = new RequestTimeDelegate() {
|
||||
@Override
|
||||
public void run(long time) {
|
||||
int c = count.getAndIncrement();
|
||||
String colorKey;
|
||||
if (time != -1) {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else if (c < 2) {
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteRedText4;
|
||||
}
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
info.start();
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
|
||||
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
|
||||
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
|
||||
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
|
||||
info.stop();
|
||||
dismissRunnable.run();
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
|
||||
public static void showShadowsocksAlert(Context activity, final SharedConfig.ShadowsocksProxy info) {
|
||||
try {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
|
||||
final Runnable dismissRunnable = builder.getDismissRunnable();
|
||||
|
||||
builder.setApplyTopPadding(false);
|
||||
builder.setApplyBottomPadding(false);
|
||||
LinearLayout linearLayout = new LinearLayout(activity);
|
||||
builder.setCustomView(linearLayout);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a = 0; a < 5; a++) {
|
||||
String text = null;
|
||||
String detail = null;
|
||||
if (a == 0) {
|
||||
text = info.bean.getHost();
|
||||
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
|
||||
} else if (a == 1) {
|
||||
text = "" + info.bean.getRemotePort();
|
||||
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
|
||||
} else if (a == 2) {
|
||||
text = info.bean.getPassword();
|
||||
detail = LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword);
|
||||
} else if (a == 3) {
|
||||
text = info.bean.getMethod();
|
||||
detail = LocaleController.getString("SSMethod", R.string.SSMethod);
|
||||
if (TextUtils.isEmpty(user)) {
|
||||
editor.remove("proxy_user");
|
||||
} else {
|
||||
text = LocaleController.getString("Checking", R.string.Checking);
|
||||
detail = LocaleController.getString("Checking", R.string.Checking);
|
||||
editor.putString("proxy_user", user);
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
continue;
|
||||
}
|
||||
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
|
||||
cell.setTextAndValue(text, detail, true);
|
||||
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
|
||||
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
if (a == 4) {
|
||||
|
||||
RequestTimeDelegate callback = new RequestTimeDelegate() {
|
||||
@Override
|
||||
public void run(long time) {
|
||||
int c = count.getAndIncrement();
|
||||
String colorKey;
|
||||
if (time != -1) {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else if (c < 2) {
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteRedText4;
|
||||
}
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
info.start();
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
|
||||
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
|
||||
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
|
||||
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
|
||||
info.stop();
|
||||
dismissRunnable.run();
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
builder.show();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showShadowsocksRAlert(Context activity, final SharedConfig.ShadowsocksRProxy info) {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
|
||||
final Runnable dismissRunnable = builder.getDismissRunnable();
|
||||
|
||||
builder.setApplyTopPadding(false);
|
||||
builder.setApplyBottomPadding(false);
|
||||
LinearLayout linearLayout = new LinearLayout(activity);
|
||||
builder.setCustomView(linearLayout);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a = 0; a < 7; a++) {
|
||||
String text = null;
|
||||
String detail = null;
|
||||
if (a == 0) {
|
||||
text = info.bean.getHost();
|
||||
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
|
||||
} else if (a == 1) {
|
||||
text = "" + info.bean.getRemotePort();
|
||||
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
|
||||
} else if (a == 2) {
|
||||
text = info.bean.getPassword();
|
||||
detail = LocaleController.getString("SSPassword", R.string.SSPassword);
|
||||
} else if (a == 3) {
|
||||
text = info.bean.getMethod();
|
||||
detail = LocaleController.getString("SSMethod", R.string.SSMethod);
|
||||
} else if (a == 4) {
|
||||
text = info.bean.getProtocol();
|
||||
if (!StrUtil.isBlank(info.bean.getProtocol_param())) {
|
||||
text += ", " + info.bean.getProtocol_param();
|
||||
}
|
||||
detail = LocaleController.getString("SSRProtocol", R.string.SSRProtocol);
|
||||
} else if (a == 5) {
|
||||
text = info.bean.getObfs();
|
||||
if (!StrUtil.isBlank(info.bean.getObfs_param())) {
|
||||
text += ", " + info.bean.getObfs_param();
|
||||
}
|
||||
detail = LocaleController.getString("SSRObfs", R.string.SSRObfs);
|
||||
info = new SharedConfig.ProxyInfo(address, p, user, password, "");
|
||||
} else {
|
||||
text = LocaleController.getString("Checking", R.string.Checking);
|
||||
detail = LocaleController.getString("Checking", R.string.Checking);
|
||||
editor.remove("proxy_pass");
|
||||
editor.remove("proxy_user");
|
||||
editor.putString("proxy_secret", secret);
|
||||
info = new SharedConfig.ProxyInfo(address, p, "", "", secret);
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
continue;
|
||||
}
|
||||
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
|
||||
cell.setTextAndValue(text, detail, true);
|
||||
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
|
||||
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
if (a == 6) {
|
||||
|
||||
RequestTimeDelegate callback = new RequestTimeDelegate() {
|
||||
@Override
|
||||
public void run(long time) {
|
||||
int c = count.getAndIncrement();
|
||||
String colorKey;
|
||||
if (time != -1) {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else if (c < 2) {
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteRedText4;
|
||||
}
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
info.start();
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
|
||||
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
|
||||
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
|
||||
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
|
||||
info.stop();
|
||||
dismissRunnable.run();
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
editor.apply();
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
public static void showWsAlert(Context activity, final SharedConfig.WsProxy info) {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
|
||||
final Runnable dismissRunnable = builder.getDismissRunnable();
|
||||
|
||||
builder.setApplyTopPadding(false);
|
||||
builder.setApplyBottomPadding(false);
|
||||
LinearLayout linearLayout = new LinearLayout(activity);
|
||||
builder.setCustomView(linearLayout);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a = 0; a < 4; a++) {
|
||||
String text = null;
|
||||
String detail = null;
|
||||
if (a == 0) {
|
||||
text = info.bean.getServer();
|
||||
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
|
||||
} else if (a == 1) {
|
||||
text = info.bean.getTls() ? "Y" : "N";
|
||||
detail = LocaleController.getString("VmessTls", R.string.VmessTls);
|
||||
} else {
|
||||
text = LocaleController.getString("Checking", R.string.Checking);
|
||||
detail = LocaleController.getString("Checking", R.string.Checking);
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
continue;
|
||||
}
|
||||
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
|
||||
cell.setTextAndValue(text, detail, true);
|
||||
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
|
||||
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
if (a == 3) {
|
||||
|
||||
RequestTimeDelegate callback = new RequestTimeDelegate() {
|
||||
@Override
|
||||
public void run(long time) {
|
||||
int c = count.getAndIncrement();
|
||||
String colorKey;
|
||||
if (time != -1) {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else if (c < 2) {
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGreenText;
|
||||
} else {
|
||||
info.stop();
|
||||
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
|
||||
colorKey = Theme.key_windowBackgroundWhiteRedText4;
|
||||
}
|
||||
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
info.start();
|
||||
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
AlertUtil.showToast(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
|
||||
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
|
||||
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
|
||||
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
|
||||
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
|
||||
info.stop();
|
||||
dismissRunnable.run();
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
|
||||
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
|
||||
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
|
||||
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
|
||||
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
|
||||
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
|
||||
SharedConfig.addProxy(info);
|
||||
|
||||
ConnectionsManager.setProxySettings(true, address, p, user, password, secret);
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
if (activity instanceof LaunchActivity) {
|
||||
INavigationLayout layout = ((LaunchActivity) activity).getActionBarLayout();
|
||||
|
@ -4435,17 +3878,6 @@ public class AndroidUtilities {
|
|||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_SUCCESS, LocaleController.getString(R.string.ProxyAddedSuccess));
|
||||
}
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
|
||||
pickerBottomLayout.doneButton.setOnClickListener(v -> {
|
||||
|
||||
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
dismissRunnable.run();
|
||||
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class ProxyRotationController implements NotificationCenter.NotificationC
|
|||
}
|
||||
editor.apply();
|
||||
|
||||
SharedConfig.currentProxy = info;
|
||||
SharedConfig.setCurrentProxy(info);
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyChangedByRotation);
|
||||
ConnectionsManager.setProxySettings(true, SharedConfig.currentProxy.address, SharedConfig.currentProxy.port, SharedConfig.currentProxy.username, SharedConfig.currentProxy.password, SharedConfig.currentProxy.secret);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,7 +57,6 @@ import javax.net.ssl.SSLException;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.parts.ProxySwitcher;
|
||||
import tw.nekomimi.nekogram.utils.DnsFactory;
|
||||
|
||||
public class ConnectionsManager extends BaseController {
|
||||
|
@ -472,9 +471,6 @@ SharedPreferences mainPreferences;
|
|||
SharedConfig.loadProxyList();
|
||||
|
||||
if (SharedConfig.proxyEnabled && SharedConfig.currentProxy != null) {
|
||||
if (SharedConfig.currentProxy instanceof SharedConfig.ExternalSocks5Proxy) {
|
||||
((SharedConfig.ExternalSocks5Proxy) SharedConfig.currentProxy).start();
|
||||
}
|
||||
native_setProxySettings(currentAccount, SharedConfig.currentProxy.address, SharedConfig.currentProxy.port, SharedConfig.currentProxy.username, SharedConfig.currentProxy.password, SharedConfig.currentProxy.secret);
|
||||
}
|
||||
checkConnection();
|
||||
|
@ -628,7 +624,6 @@ SharedPreferences mainPreferences;
|
|||
try {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getInstance(currentAccount).connectionState = state;
|
||||
ProxySwitcher.didReceivedNotification(state);
|
||||
AccountInstance.getInstance(currentAccount).getNotificationCenter().postNotificationName(NotificationCenter.didUpdateConnectionState);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -187,7 +187,7 @@ import tw.nekomimi.nekogram.NekoConfig;
|
|||
import tw.nekomimi.nekogram.parts.ArticleTransKt;
|
||||
import tw.nekomimi.nekogram.transtale.TranslateDb;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
public class ArticleViewer implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
@ -1267,7 +1267,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
if (which == 0 ) {
|
||||
Browser.openUrl(parentActivity, urlFinal);
|
||||
} else {
|
||||
ProxyUtil.showQrDialog(parentActivity, urlFinal);
|
||||
QrUtil.showQrDialog(parentActivity, urlFinal);
|
||||
}
|
||||
} else if (which == 1) {
|
||||
String url = urlFinal;
|
||||
|
|
|
@ -68,7 +68,7 @@ import tw.nekomimi.nekogram.NekoConfig;
|
|||
import tw.nekomimi.nekogram.transtale.TranslateDb;
|
||||
import tw.nekomimi.nekogram.transtale.Translator;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
import static com.google.zxing.common.detector.MathUtils.distance;
|
||||
import static org.telegram.ui.ActionBar.FloatingToolbar.STYLE_THEME;
|
||||
|
@ -1362,7 +1362,7 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
|
|||
return true;
|
||||
}
|
||||
String urlFinal = textS.toString();
|
||||
Activity activity = ProxyUtil.getOwnerActivity((((View) selectedView).getContext()));
|
||||
Activity activity = QrUtil.getOwnerActivity((((View) selectedView).getContext()));
|
||||
TranslateDb db = TranslateDb.currentTarget();
|
||||
if (db.contains(urlFinal)) {
|
||||
AlertUtil.showCopyAlert(activity, db.query(urlFinal));
|
||||
|
|
|
@ -137,7 +137,7 @@ import kotlin.Unit;
|
|||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
public class ChannelAdminLogActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
@ -2508,7 +2508,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
if (which == 0) {
|
||||
Browser.openUrl(getParentActivity(), urlFinal);
|
||||
} else {
|
||||
ProxyUtil.showQrDialog(getParentActivity(), urlFinal);
|
||||
QrUtil.showQrDialog(getParentActivity(), urlFinal);
|
||||
}
|
||||
} else if (which == 1) {
|
||||
String url1 = urlFinal;
|
||||
|
|
|
@ -343,7 +343,7 @@ import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
|||
import tw.nekomimi.nekogram.transtale.Translator;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.PGPUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
import tw.nekomimi.nekogram.utils.TelegramUtil;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -26260,18 +26260,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
showDialog(builder.create());
|
||||
}
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".nekox.json")) {
|
||||
//TODO wtf
|
||||
|
||||
File finalLocFile1 = locFile;
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
|
||||
R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import),
|
||||
false, () -> {
|
||||
String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile1);
|
||||
if (!StrUtil.isBlank(status)) {
|
||||
presentFragment(new ProxyListActivity(status));
|
||||
}
|
||||
});
|
||||
Toast.makeText(getContext(), "Not Supportred now", Toast.LENGTH_SHORT).show();
|
||||
// File finalLocFile1 = locFile;
|
||||
// AlertUtil.showConfirm(getParentActivity(),
|
||||
// LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
|
||||
// R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import),
|
||||
// false, () -> {
|
||||
// String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile1);
|
||||
// if (!StrUtil.isBlank(status)) {
|
||||
// presentFragment(new ProxyListActivity(status));
|
||||
// }
|
||||
// });
|
||||
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".nekox-stickers.json")) {
|
||||
|
||||
|
@ -26284,11 +26283,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
});
|
||||
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".nekox-settings.json")) {
|
||||
|
||||
File finalLocFile = locFile;
|
||||
|
||||
NekoSettingsActivity.importSettings(getParentActivity(), finalLocFile);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -28302,7 +28298,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}
|
||||
} else if (which == 2) {
|
||||
// QRCode
|
||||
ProxyUtil.showQrDialog(getParentActivity(), urlFinal);
|
||||
QrUtil.showQrDialog(getParentActivity(), urlFinal);
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
@ -30633,17 +30629,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
AlertUtil.showToast("FILE_NOT_FOUND");
|
||||
|
||||
} else if (message.getDocumentName().toLowerCase().endsWith(".nekox.json")) {
|
||||
AlertUtil.showToast("NOT_SUPPORTED_NOW");
|
||||
|
||||
File finalLocFile = locFile;
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
|
||||
R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import),
|
||||
false, () -> {
|
||||
String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile);
|
||||
if (!StrUtil.isBlank(status)) {
|
||||
presentFragment(new ProxyListActivity(status));
|
||||
}
|
||||
});
|
||||
// File finalLocFile = locFile;
|
||||
// AlertUtil.showConfirm(getParentActivity(),
|
||||
// LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
|
||||
// R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import),
|
||||
// false, () -> {
|
||||
// String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile);
|
||||
// if (!StrUtil.isBlank(status)) {
|
||||
// presentFragment(new ProxyListActivity(status));
|
||||
// }
|
||||
// });
|
||||
|
||||
} else if (message.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json")) {
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.graphics.PorterDuff;
|
|||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Vibrator;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
@ -82,7 +81,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.VibrateUtil;
|
||||
|
||||
public class ChatEditTypeActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
|
|
@ -121,7 +121,7 @@ import kotlin.Unit;
|
|||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SharedMediaLayout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
@ -4961,7 +4961,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
|
|||
if (which == 0) {
|
||||
openUrl(urlFinal);
|
||||
} else {
|
||||
ProxyUtil.showQrDialog(profileActivity.getParentActivity(), urlFinal);
|
||||
QrUtil.showQrDialog(profileActivity.getParentActivity(), urlFinal);
|
||||
}
|
||||
} else if (which == 1) {
|
||||
String url1 = urlFinal;
|
||||
|
|
|
@ -105,7 +105,7 @@ import java.util.List;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
@ -1052,11 +1052,11 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not
|
|||
if (child instanceof StickerEmojiCell) {
|
||||
Bitmap bitmap = ((StickerEmojiCell) child).getImageView().getBitmap();
|
||||
if (bitmap == null) continue;
|
||||
ProxyUtil.showQrDialog(getContext(), stickersUrl, imageSize -> Bitmap.createScaledBitmap(bitmap,imageSize,imageSize, true));
|
||||
QrUtil.showQrDialog(getContext(), stickersUrl, imageSize -> Bitmap.createScaledBitmap(bitmap,imageSize,imageSize, true));
|
||||
return;
|
||||
}
|
||||
}
|
||||
ProxyUtil.showQrDialog(getContext(), stickersUrl);
|
||||
QrUtil.showQrDialog(getContext(), stickersUrl);
|
||||
} else if (id == menu_archive) {
|
||||
dismiss();
|
||||
MediaDataController.getInstance(currentAccount).toggleStickerSet(parentActivity, stickerSet, 1, parentFragment, false, true);
|
||||
|
|
|
@ -215,7 +215,7 @@ import tw.nekomimi.nekogram.InternalUpdater;
|
|||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.utils.PrivacyUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
import tw.nekomimi.nekogram.utils.UpdateUtil;
|
||||
import tw.nekomimi.nekogram.utils.VibrateUtil;
|
||||
|
@ -5350,7 +5350,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
|
|||
|
||||
@Override
|
||||
public void didFindQr(String text) {
|
||||
ProxyUtil.showLinkAlert(getParentActivity(), text);
|
||||
QrUtil.showLinkAlert(getParentActivity(), text);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -81,7 +81,7 @@ import java.util.Locale;
|
|||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
public class FilteredSearchView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
@ -1103,7 +1103,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
|
|||
if (which == 0) {
|
||||
openUrl(urlFinal);
|
||||
} else {
|
||||
ProxyUtil.showQrDialog(parentActivity, urlFinal);
|
||||
QrUtil.showQrDialog(parentActivity, urlFinal);
|
||||
}
|
||||
} else if (which == 1) {
|
||||
String url1 = urlFinal;
|
||||
|
|
|
@ -42,7 +42,7 @@ import org.telegram.ui.Components.RecyclerListView;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
public class GroupInviteActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
@ -156,7 +156,7 @@ public class GroupInviteActivity extends BaseFragment implements NotificationCen
|
|||
if (invite == null) {
|
||||
return;
|
||||
}
|
||||
ProxyUtil.showQrDialog(getParentActivity(),invite.link);
|
||||
QrUtil.showQrDialog(getParentActivity(),invite.link);
|
||||
} else if (position == revokeLinkRow) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setMessage(LocaleController.getString("RevokeAlert", R.string.RevokeAlert));
|
||||
|
|
|
@ -205,12 +205,10 @@ import cn.hutool.core.util.StrUtil;
|
|||
import kotlin.Unit;
|
||||
import kotlin.text.StringsKt;
|
||||
import tw.nekomimi.nekogram.InternalUpdater;
|
||||
import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
||||
import tw.nekomimi.nekogram.proxy.SubInfo;
|
||||
import tw.nekomimi.nekogram.proxy.SubManager;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
|
@ -897,22 +895,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
|
|||
FileLog.e(e);
|
||||
}
|
||||
MediaController.getInstance().setBaseActivity(this, true);
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
// ExternalGcm.checkUpdate(this);
|
||||
if (NekoConfig.autoUpdateSubInfo.Bool())
|
||||
for (SubInfo subInfo : SubManager.getSubList().find()) {
|
||||
if (subInfo == null || !subInfo.enable) continue;
|
||||
try {
|
||||
subInfo.proxies = subInfo.reloadProxies();
|
||||
subInfo.lastFetch = System.currentTimeMillis();
|
||||
SubManager.getSubList().update(subInfo, true);
|
||||
SharedConfig.reloadProxyList();
|
||||
} catch (IOException allTriesFailed) {
|
||||
FileLog.e(allTriesFailed);
|
||||
}
|
||||
}
|
||||
}, 4000);
|
||||
SharedConfig.reloadProxyList();
|
||||
//FileLog.d("UI create time = " + (SystemClock.elapsedRealtime() - ApplicationLoader.startTime));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
|
|
@ -46,7 +46,6 @@ import android.telephony.PhoneNumberUtils;
|
|||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
|
@ -55,7 +54,6 @@ import android.text.TextWatcher;
|
|||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.ImageSpan;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.util.Base64;
|
||||
import android.util.TypedValue;
|
||||
|
@ -84,7 +82,6 @@ import android.widget.ViewSwitcher;
|
|||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
//import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
||||
|
@ -94,10 +91,7 @@ import androidx.core.graphics.ColorUtils;
|
|||
//import com.google.android.gms.common.api.ApiException;
|
||||
//import com.google.android.gms.safetynet.SafetyNet;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AccountInstance;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.AuthTokensHelper;
|
||||
|
@ -113,7 +107,6 @@ import org.telegram.messenger.MessageObject;
|
|||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.MessagesStorage;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.PushListenerController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SRPHelper;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
|
@ -125,7 +118,6 @@ import org.telegram.tgnet.SerializedData;
|
|||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
|
@ -147,7 +139,6 @@ import org.telegram.ui.Components.ImageUpdater;
|
|||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.LinkPath;
|
||||
import org.telegram.ui.Components.LoadingDrawable;
|
||||
import org.telegram.ui.Components.LoginOrView;
|
||||
import org.telegram.ui.Components.OutlineTextContainerView;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.RLottieImageView;
|
||||
|
@ -184,7 +175,7 @@ import tw.nekomimi.nekogram.NekoConfig;
|
|||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.ui.EditTextAutoFill;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
public class LoginActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
@ -8426,7 +8417,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
|
|||
} catch (Exception ignore) {
|
||||
}
|
||||
if (response instanceof TLRPC.TL_auth_loginToken) {
|
||||
exportLoginTokenDialog = ProxyUtil.showQrDialog(getParentActivity(), "tg://login?token=" + cn.hutool.core.codec.Base64.encodeUrlSafe(((TLRPC.TL_auth_loginToken) response).token));
|
||||
exportLoginTokenDialog = QrUtil.showQrDialog(getParentActivity(), "tg://login?token=" + cn.hutool.core.codec.Base64.encodeUrlSafe(((TLRPC.TL_auth_loginToken) response).token));
|
||||
int delay = (int) (((TLRPC.TL_auth_loginToken) response).expires - System.currentTimeMillis() / 1000);
|
||||
if (delay < 0 || delay > 20) delay = 20;
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
|
|
|
@ -267,7 +267,7 @@ import tw.nekomimi.nekogram.transtale.TranslateDb;
|
|||
import tw.nekomimi.nekogram.transtale.Translator;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -4350,7 +4350,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
|||
showDownloadAlert();
|
||||
return;
|
||||
}
|
||||
ProxyUtil.tryReadQR(parentActivity, bitmap);
|
||||
QrUtil.tryReadQR(parentActivity, bitmap);
|
||||
} catch (Exception ignored) {
|
||||
AlertUtil.showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound));
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ConfigurationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.DataSetObserver;
|
||||
|
@ -79,7 +78,6 @@ import androidx.annotation.Keep;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.math.MathUtils;
|
||||
import androidx.core.view.NestedScrollingParent3;
|
||||
|
@ -207,7 +205,6 @@ import org.telegram.ui.Components.SharedMediaLayout;
|
|||
import org.telegram.ui.Components.SizeNotifierFrameLayout;
|
||||
import org.telegram.ui.Components.StickerEmptyView;
|
||||
import org.telegram.ui.Components.TimerDrawable;
|
||||
import org.telegram.ui.Components.TranslateAlert2;
|
||||
import org.telegram.ui.Components.TypefaceSpan;
|
||||
import org.telegram.ui.Components.UndoView;
|
||||
import org.telegram.ui.Components.VectorAvatarThumbDrawable;
|
||||
|
@ -237,7 +234,6 @@ import cn.hutool.core.thread.ThreadUtil;
|
|||
import cn.hutool.core.util.RuntimeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import libv2ray.Libv2ray;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.parts.DialogTransKt;
|
||||
|
@ -245,10 +241,9 @@ import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
|||
import tw.nekomimi.nekogram.settings.NekoXSettingActivity;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.EnvUtil;
|
||||
import tw.nekomimi.nekogram.utils.FileUtil;
|
||||
import tw.nekomimi.nekogram.utils.LangsKt;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.QrUtil;
|
||||
import tw.nekomimi.nekogram.utils.ShareUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
|
@ -1697,7 +1692,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
final int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (error == null) {
|
||||
TLRPC.TL_chatInviteExported invite = (TLRPC.TL_chatInviteExported) response;
|
||||
ProxyUtil.showQrDialog(getParentActivity(), invite.link, imageSize -> Bitmap.createScaledBitmap(avatarImage.getImageReceiver().getBitmap(), imageSize, imageSize, true));
|
||||
QrUtil.showQrDialog(getParentActivity(), invite.link, imageSize -> Bitmap.createScaledBitmap(avatarImage.getImageReceiver().getBitmap(), imageSize, imageSize, true));
|
||||
} else {
|
||||
AlertUtil.showToast(error);
|
||||
}
|
||||
|
@ -2091,7 +2086,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
intent.putExtra(Intent.EXTRA_TEXT, text);
|
||||
startActivityForResult(Intent.createChooser(intent, LocaleController.getString("BotShare", R.string.BotShare)), 500);
|
||||
} else {
|
||||
ProxyUtil.showQrDialog(getParentActivity(), text, avatarImage.getImageReceiver().getBitmap() == null ? null : imageSize -> Bitmap.createScaledBitmap(avatarImage.getImageReceiver().getBitmap(), imageSize, imageSize, true));
|
||||
QrUtil.showQrDialog(getParentActivity(), text, avatarImage.getImageReceiver().getBitmap() == null ? null : imageSize -> Bitmap.createScaledBitmap(avatarImage.getImageReceiver().getBitmap(), imageSize, imageSize, true));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
|
@ -3538,14 +3533,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
|
||||
BottomBuilder builder = new BottomBuilder(getParentActivity());
|
||||
String message = cell.getTextView().getText().toString();
|
||||
try {
|
||||
if (!BuildVars.isMini) {
|
||||
message += "\n" + Libv2ray.checkVersionX()
|
||||
.replace("Lib", "AndroidLibV2rayLite")
|
||||
.replace("Core", "v2ray-core");
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
builder.addTitle(message);
|
||||
String finalMessage = message;
|
||||
builder.addItem(LocaleController.getString("Copy", R.string.Copy), R.drawable.baseline_content_copy_24, (it) -> {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,6 @@ import android.animation.ValueAnimator;
|
|||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -42,6 +41,8 @@ import android.widget.LinearLayout;
|
|||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
|
@ -56,6 +57,8 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
|||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.HeaderCell;
|
||||
import org.telegram.ui.Cells.RadioCell;
|
||||
import org.telegram.ui.Cells.ShadowSectionCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
|
@ -80,17 +83,18 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
private final static int FIELD_USER = 2;
|
||||
private final static int FIELD_PASSWORD = 3;
|
||||
private final static int FIELD_SECRET = 4;
|
||||
private final static int FIELD_REMARKS = 5;
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
private HeaderCell headerCell;
|
||||
private ShadowSectionCell[] sectionCell = new ShadowSectionCell[3];
|
||||
private TextInfoPrivacyCell[] bottomCells = new TextInfoPrivacyCell[2];
|
||||
private TextSettingsCell shareCell;
|
||||
private TextSettingsCell pasteCell;
|
||||
private ActionBarMenuItem doneItem;
|
||||
// private RadioCell[] typeCell = new RadioCell[2];
|
||||
private RadioCell[] typeCell = new RadioCell[2];
|
||||
private int currentType = -1;
|
||||
|
||||
private int pasteType = -1;
|
||||
|
@ -134,7 +138,7 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.MULTIPLY));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
}
|
||||
|
@ -157,16 +161,15 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ProxySettingsActivity(int type) {
|
||||
public ProxySettingsActivity() {
|
||||
super();
|
||||
currentProxyInfo = new SharedConfig.ProxyInfo("", 1080, "", "", "");
|
||||
addingNewProxy = true;
|
||||
currentType = type;
|
||||
}
|
||||
|
||||
public ProxySettingsActivity(SharedConfig.ProxyInfo proxyInfo) {
|
||||
|
@ -210,7 +213,6 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
}
|
||||
currentProxyInfo.address = inputFields[FIELD_IP].getText().toString();
|
||||
currentProxyInfo.port = Utilities.parseInt(inputFields[FIELD_PORT].getText().toString());
|
||||
currentProxyInfo.setRemarks(inputFields[FIELD_REMARKS].getText().toString());
|
||||
if (currentType == 0) {
|
||||
currentProxyInfo.secret = "";
|
||||
currentProxyInfo.username = inputFields[FIELD_USER].getText().toString();
|
||||
|
@ -223,11 +225,14 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
boolean enabled;
|
||||
if (addingNewProxy) {
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
SharedConfig.currentProxy = currentProxyInfo;
|
||||
editor.putBoolean("proxy_enabled", true);
|
||||
enabled = true;
|
||||
} else {
|
||||
SharedConfig.setProxyEnable(false);
|
||||
enabled = preferences.getBoolean("proxy_enabled", false);
|
||||
SharedConfig.saveProxyList();
|
||||
}
|
||||
if (addingNewProxy || SharedConfig.currentProxy == currentProxyInfo) {
|
||||
|
@ -236,21 +241,13 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
editor.putString("proxy_user", currentProxyInfo.username);
|
||||
editor.putInt("proxy_port", currentProxyInfo.port);
|
||||
editor.putString("proxy_secret", currentProxyInfo.secret);
|
||||
if (currentProxyInfo instanceof SharedConfig.VmessProxy) {
|
||||
editor.putString("vmess_link", ((SharedConfig.VmessProxy) currentProxyInfo).bean.toString());
|
||||
} else if (currentProxyInfo instanceof SharedConfig.ShadowsocksProxy) {
|
||||
editor.putString("vmess_link", ((SharedConfig.ShadowsocksProxy) currentProxyInfo).bean.toString());
|
||||
} else if (currentProxyInfo instanceof SharedConfig.ShadowsocksRProxy) {
|
||||
editor.putString("vmess_link", ((SharedConfig.ShadowsocksRProxy) currentProxyInfo).bean.toString());
|
||||
}
|
||||
ConnectionsManager.setProxySettings(SharedConfig.proxyEnabled, currentProxyInfo.address, currentProxyInfo.port, currentProxyInfo.username, currentProxyInfo.password, currentProxyInfo.secret);
|
||||
ConnectionsManager.setProxySettings(enabled, currentProxyInfo.address, currentProxyInfo.port, currentProxyInfo.username, currentProxyInfo.password, currentProxyInfo.secret);
|
||||
}
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -271,7 +268,23 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
final View.OnClickListener typeCellClickListener = view -> setProxyType((Integer) view.getTag(), true);
|
||||
|
||||
for (int a = 0; a < 2; a++) {
|
||||
typeCell[a] = new RadioCell(context);
|
||||
typeCell[a].setBackground(Theme.getSelectorDrawable(true));
|
||||
typeCell[a].setTag(a);
|
||||
if (a == 0) {
|
||||
typeCell[a].setText(LocaleController.getString("UseProxySocks5", R.string.UseProxySocks5), a == currentType, true);
|
||||
} else {
|
||||
typeCell[a].setText(LocaleController.getString("UseProxyTelegram", R.string.UseProxyTelegram), a == currentType, false);
|
||||
}
|
||||
linearLayout2.addView(typeCell[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50));
|
||||
typeCell[a].setOnClickListener(typeCellClickListener);
|
||||
}
|
||||
|
||||
sectionCell[0] = new ShadowSectionCell(context);
|
||||
linearLayout2.addView(sectionCell[0], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
|
@ -283,8 +296,8 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[6];
|
||||
for (int a = 0; a < 6; a++) {
|
||||
inputFields = new EditTextBoldCursor[5];
|
||||
for (int a = 0; a < 5; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
|
@ -399,10 +412,6 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
inputFields[a].setHintText(LocaleController.getString("UseProxySecret", R.string.UseProxySecret));
|
||||
inputFields[a].setText(currentProxyInfo.secret);
|
||||
break;
|
||||
case FIELD_REMARKS:
|
||||
inputFields[a].setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
inputFields[a].setText(currentProxyInfo.getRemarks());
|
||||
break;
|
||||
}
|
||||
inputFields[a].setSelection(inputFields[a].length());
|
||||
|
||||
|
@ -482,6 +491,63 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
linearLayout2.addView(sectionCell[2], 1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
sectionCell[2].setVisibility(View.GONE);
|
||||
|
||||
shareCell = new TextSettingsCell(context);
|
||||
shareCell.setBackgroundDrawable(Theme.getSelectorDrawable(true));
|
||||
shareCell.setText(LocaleController.getString("ShareFile", R.string.ShareFile), false);
|
||||
shareCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4));
|
||||
linearLayout2.addView(shareCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
shareCell.setOnClickListener(v -> {
|
||||
StringBuilder params = new StringBuilder();
|
||||
String address = inputFields[FIELD_IP].getText().toString();
|
||||
String password = inputFields[FIELD_PASSWORD].getText().toString();
|
||||
String user = inputFields[FIELD_USER].getText().toString();
|
||||
String port = inputFields[FIELD_PORT].getText().toString();
|
||||
String secret = inputFields[FIELD_SECRET].getText().toString();
|
||||
String url;
|
||||
try {
|
||||
if (!TextUtils.isEmpty(address)) {
|
||||
params.append("server=").append(URLEncoder.encode(address, "UTF-8"));
|
||||
}
|
||||
if (!TextUtils.isEmpty(port)) {
|
||||
if (params.length() != 0) {
|
||||
params.append("&");
|
||||
}
|
||||
params.append("port=").append(URLEncoder.encode(port, "UTF-8"));
|
||||
}
|
||||
if (currentType == 1) {
|
||||
url = "https://t.me/proxy?";
|
||||
if (params.length() != 0) {
|
||||
params.append("&");
|
||||
}
|
||||
params.append("secret=").append(URLEncoder.encode(secret, "UTF-8"));
|
||||
} else {
|
||||
url = "https://t.me/socks?";
|
||||
if (!TextUtils.isEmpty(user)) {
|
||||
if (params.length() != 0) {
|
||||
params.append("&");
|
||||
}
|
||||
params.append("user=").append(URLEncoder.encode(user, "UTF-8"));
|
||||
}
|
||||
if (!TextUtils.isEmpty(password)) {
|
||||
if (params.length() != 0) {
|
||||
params.append("&");
|
||||
}
|
||||
params.append("pass=").append(URLEncoder.encode(password, "UTF-8"));
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
return;
|
||||
}
|
||||
if (params.length() == 0) {
|
||||
return;
|
||||
}
|
||||
String link = url + params.toString();
|
||||
QRCodeBottomSheet alert = new QRCodeBottomSheet(context, LocaleController.getString("ShareQrCode", R.string.ShareQrCode), link, LocaleController.getString("QRCodeLinkHelpProxy", R.string.QRCodeLinkHelpProxy), true);
|
||||
Bitmap icon = SvgHelper.getBitmap(RLottieDrawable.readRes(null, R.raw.qr_dog), AndroidUtilities.dp(60), AndroidUtilities.dp(60), false);
|
||||
alert.setCenterImage(icon);
|
||||
showDialog(alert);
|
||||
});
|
||||
|
||||
sectionCell[1] = new ShadowSectionCell(context);
|
||||
sectionCell[1].setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
linearLayout2.addView(sectionCell[1], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
@ -492,19 +558,8 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
shareDoneProgress = 1f;
|
||||
checkShareDone(false);
|
||||
|
||||
if (currentType == -1) {
|
||||
|
||||
setProxyType(TextUtils.isEmpty(currentProxyInfo.secret) ? 0 : 1, false);
|
||||
|
||||
} else {
|
||||
|
||||
int t = currentType;
|
||||
|
||||
currentType = -1;
|
||||
|
||||
setProxyType(t, false);
|
||||
|
||||
}
|
||||
currentType = -1;
|
||||
setProxyType(TextUtils.isEmpty(currentProxyInfo.secret) ? 0 : 1, false);
|
||||
|
||||
pasteType = -1;
|
||||
pasteString = null;
|
||||
|
@ -612,6 +667,7 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
shareDoneAnimator.setDuration(200);
|
||||
shareDoneAnimator.addUpdateListener(a -> {
|
||||
shareDoneProgress = AndroidUtilities.lerp(shareDoneProgressAnimValues, a.getAnimatedFraction());
|
||||
shareCell.setTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4), shareDoneProgress));
|
||||
doneItem.setAlpha(shareDoneProgress / 2f + 0.5f);
|
||||
});
|
||||
}
|
||||
|
@ -621,15 +677,17 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
shareDoneAnimator.start();
|
||||
} else {
|
||||
shareDoneProgress = enabled ? 1f : 0f;
|
||||
shareCell.setTextColor(enabled ? Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4) : Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
||||
doneItem.setAlpha(enabled ? 1f : .5f);
|
||||
}
|
||||
shareCell.setEnabled(enabled);
|
||||
doneItem.setEnabled(enabled);
|
||||
shareDoneEnabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkShareDone(boolean animated) {
|
||||
if (doneItem == null || inputFields[FIELD_IP] == null || inputFields[FIELD_PORT] == null) {
|
||||
if (shareCell == null || doneItem == null || inputFields[FIELD_IP] == null || inputFields[FIELD_PORT] == null) {
|
||||
return;
|
||||
}
|
||||
setShareDoneEnabled(inputFields[FIELD_IP].length() != 0 && Utilities.parseInt(inputFields[FIELD_PORT].getText().toString()) != 0, animated);
|
||||
|
@ -693,6 +751,8 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
((View) inputFields[FIELD_PASSWORD].getParent()).setVisibility(View.GONE);
|
||||
((View) inputFields[FIELD_USER].getParent()).setVisibility(View.GONE);
|
||||
}
|
||||
typeCell[0].setChecked(currentType == 0, animated);
|
||||
typeCell[1].setChecked(currentType == 1, animated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,6 +767,9 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (shareCell != null && (shareDoneAnimator == null || !shareDoneAnimator.isRunning())) {
|
||||
shareCell.setTextColor(shareDoneEnabled ? Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4) : Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
||||
}
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
|
@ -727,10 +790,23 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(shareCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(shareCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_listSelector));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
arrayList.add(new ThemeDescription(pasteCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(pasteCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_listSelector));
|
||||
arrayList.add(new ThemeDescription(pasteCell, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
|
||||
for (int a = 0; a < typeCell.length; a++) {
|
||||
arrayList.add(new ThemeDescription(typeCell[a], ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(typeCell[a], ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_listSelector));
|
||||
arrayList.add(new ThemeDescription(typeCell[a], 0, new Class[]{RadioCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(typeCell[a], ThemeDescription.FLAG_CHECKBOX, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackground));
|
||||
arrayList.add(new ThemeDescription(typeCell[a], ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackgroundChecked));
|
||||
}
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
|
@ -745,6 +821,8 @@ public class ProxySettingsActivity extends BaseFragment {
|
|||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
arrayList.add(new ThemeDescription(headerCell, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(headerCell, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
for (int a = 0; a < sectionCell.length; a++) {
|
||||
if (sectionCell[a] != null) {
|
||||
arrayList.add(new ThemeDescription(sectionCell[a], ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
|
|
|
@ -2,7 +2,6 @@ package tw.nekomimi.nekogram.database
|
|||
|
||||
import org.dizitart.no2.Nitrite
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import tw.nekomimi.nekogram.proxy.SubInfo
|
||||
import tw.nekomimi.nekogram.utils.FileUtil
|
||||
import java.io.File
|
||||
|
||||
|
@ -22,10 +21,6 @@ fun mkDatabase(name: String, delete: Boolean = false): Nitrite {
|
|||
|
||||
val test = nitrite.openSharedPreference("shared_preferences")
|
||||
test.connection.close()
|
||||
|
||||
val subs = nitrite.getRepository("proxy_sub", SubInfo::class.java)
|
||||
subs.close()
|
||||
|
||||
return nitrite
|
||||
}
|
||||
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
package tw.nekomimi.nekogram.parts
|
||||
|
||||
import android.os.SystemClock
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.telegram.messenger.AndroidUtilities
|
||||
import org.telegram.messenger.NotificationCenter
|
||||
import org.telegram.messenger.SharedConfig
|
||||
import org.telegram.messenger.SharedConfig.ExternalSocks5Proxy
|
||||
import org.telegram.messenger.UserConfig
|
||||
import org.telegram.tgnet.ConnectionsManager
|
||||
import org.telegram.ui.ProxyListActivity
|
||||
import tw.nekomimi.nekogram.utils.UIUtil
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
private suspend fun postCheckSingleProxy(proxyInfo: SharedConfig.ProxyInfo, repeat: Int) {
|
||||
|
||||
val lock = AtomicBoolean()
|
||||
|
||||
if (proxyInfo is ExternalSocks5Proxy && !proxyInfo.isStarted) {
|
||||
proxyInfo.start()
|
||||
delay(233L)
|
||||
}
|
||||
|
||||
var time = -1L
|
||||
val startAt = SystemClock.elapsedRealtime()
|
||||
|
||||
proxyInfo.proxyCheckPingId = ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(proxyInfo.address, proxyInfo.port, proxyInfo.username, proxyInfo.password, proxyInfo.secret) {
|
||||
time = it
|
||||
lock.set(true)
|
||||
}
|
||||
|
||||
while (!lock.get() && SystemClock.elapsedRealtime() - startAt < 4000L) delay(100L)
|
||||
|
||||
if (!lock.get()) {
|
||||
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime()
|
||||
proxyInfo.checking = false
|
||||
proxyInfo.available = false
|
||||
proxyInfo.ping = 0
|
||||
if (proxyInfo is ExternalSocks5Proxy && proxyInfo !== SharedConfig.currentProxy) {
|
||||
proxyInfo.stop()
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
if (time == -1L) {
|
||||
if (repeat > 0) {
|
||||
postCheckSingleProxy(proxyInfo, repeat - 1)
|
||||
} else {
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime()
|
||||
proxyInfo.checking = false
|
||||
proxyInfo.available = false
|
||||
proxyInfo.ping = -1L
|
||||
if (proxyInfo is ExternalSocks5Proxy && proxyInfo !== SharedConfig.currentProxy) {
|
||||
proxyInfo.stop()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime()
|
||||
proxyInfo.checking = false
|
||||
proxyInfo.ping = time
|
||||
proxyInfo.available = true
|
||||
if (proxyInfo is ExternalSocks5Proxy && proxyInfo !== SharedConfig.currentProxy) {
|
||||
proxyInfo.stop()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun postCheckProxyList() = GlobalScope.launch(Dispatchers.IO) {
|
||||
|
||||
SharedConfig.getProxyList().forEach { proxyInfo ->
|
||||
|
||||
if (proxyInfo.checking || SystemClock.elapsedRealtime() - proxyInfo.availableCheckTime < 2 * 60 * 1000L) {
|
||||
|
||||
return@forEach
|
||||
|
||||
}
|
||||
|
||||
synchronized(proxyInfo) {
|
||||
|
||||
if (proxyInfo.checking || SystemClock.elapsedRealtime() - proxyInfo.availableCheckTime < 2 * 60 * 1000L) {
|
||||
|
||||
return@forEach
|
||||
|
||||
}
|
||||
|
||||
proxyInfo.checking = true
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
postCheckSingleProxy(proxyInfo, 1)
|
||||
|
||||
}.onFailure {
|
||||
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime()
|
||||
proxyInfo.checking = false
|
||||
proxyInfo.available = false
|
||||
proxyInfo.ping = 0
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun ProxyListActivity.checkProxyList(force: Boolean, context: ExecutorService) {
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
|
||||
SharedConfig.proxyList.toList().forEach {
|
||||
|
||||
if (it.checking || SystemClock.elapsedRealtime() - it.availableCheckTime < 2 * 60 * 1000L && !force) {
|
||||
|
||||
return@forEach
|
||||
|
||||
}
|
||||
|
||||
it.checking = true
|
||||
|
||||
runCatching {
|
||||
|
||||
context.execute {
|
||||
|
||||
runCatching {
|
||||
|
||||
val lock = AtomicBoolean()
|
||||
|
||||
val startAt = SystemClock.elapsedRealtime()
|
||||
|
||||
UIUtil.runOnUIThread { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, it) }
|
||||
|
||||
checkSingleProxy(it, if (it is ExternalSocks5Proxy) 3 else 1) {
|
||||
|
||||
AndroidUtilities.runOnUIThread {
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, it)
|
||||
|
||||
}
|
||||
|
||||
lock.set(true)
|
||||
|
||||
}
|
||||
|
||||
while (!lock.get() && SystemClock.elapsedRealtime() - startAt < 4000L) Thread.sleep(100L)
|
||||
|
||||
if (!lock.get()) {
|
||||
|
||||
it.availableCheckTime = SystemClock.elapsedRealtime()
|
||||
it.checking = false
|
||||
it.available = false
|
||||
it.ping = 0
|
||||
if (it is ExternalSocks5Proxy && it !== SharedConfig.currentProxy) {
|
||||
it.stop()
|
||||
}
|
||||
|
||||
AndroidUtilities.runOnUIThread {
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, it)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}.onFailure {
|
||||
|
||||
return@launch
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package tw.nekomimi.nekogram.parts
|
||||
|
||||
import android.util.Base64
|
||||
import cn.hutool.http.HttpResponse
|
||||
import cn.hutool.http.HttpUtil
|
||||
import kotlinx.coroutines.*
|
||||
import org.telegram.messenger.FileLog
|
||||
import tw.nekomimi.nekogram.utils.DnsFactory
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil.parseProxies
|
||||
import tw.nekomimi.nekogram.NekoConfig
|
||||
import tw.nekomimi.nekogram.utils.StrUtil
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
fun loadProxiesPublic(urls: List<String>, exceptions: MutableMap<String, Exception>): List<String> {
|
||||
if (!NekoConfig.enablePublicProxy.Bool())
|
||||
return emptyList()
|
||||
// Try DoH first ( github.com is often blocked
|
||||
try {
|
||||
val content = DnsFactory.getTxts("nachonekodayo.sekai.icu").joinToString()
|
||||
|
||||
val proxiesString = StrUtil.getSubString(content, "#NekoXStart#", "#NekoXEnd#")
|
||||
if (proxiesString.equals(content)) {
|
||||
throw Exception("DoH get public proxy: Not found")
|
||||
}
|
||||
|
||||
return parseProxies(proxiesString)
|
||||
} catch (e: Exception) {
|
||||
FileLog.e(e)
|
||||
}
|
||||
|
||||
// Try Other Urls
|
||||
return loadProxies(urls, exceptions)
|
||||
}
|
||||
|
||||
|
||||
fun loadProxies(urls: List<String>, exceptions: MutableMap<String, Exception>): List<String> {
|
||||
|
||||
return runBlocking {
|
||||
|
||||
suspendCoroutine {
|
||||
|
||||
val ret = AtomicBoolean()
|
||||
val cl = AtomicInteger(urls.size)
|
||||
var defer: List<String>? = null
|
||||
|
||||
for (url in urls) {
|
||||
launch(Dispatchers.IO) {
|
||||
try {
|
||||
var subX = ""
|
||||
var subY = ""
|
||||
var urlFinal = url
|
||||
if (url.count { it == '@' } == 2) {
|
||||
subX = url.substringAfter("@")
|
||||
.substringBefore("@")
|
||||
subY = url.substringAfterLast("@")
|
||||
urlFinal = url.substringBefore("@")
|
||||
}
|
||||
var nextUrl = url
|
||||
var resp: HttpResponse
|
||||
while (true) {
|
||||
resp = HttpUtil.createGet(nextUrl).timeout(10 * 1000).execute();
|
||||
if (resp.status == 301 || resp.status == 302 || resp.status == 307) {
|
||||
nextUrl = resp.header("Location");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
var content = resp.body()
|
||||
if (subX.isNotBlank()) {
|
||||
content = content.substringAfter(subX)
|
||||
.substringBefore(subY)
|
||||
}
|
||||
|
||||
if (url.contains("https://api.github.com")) {
|
||||
content = content.replace("\\n", "", false)
|
||||
content = String(Base64.decode(content, Base64.NO_PADDING))
|
||||
}
|
||||
|
||||
val proxies = parseProxies(content)
|
||||
if (urlFinal.contains("https://gitee.com/") && cl.decrementAndGet() > 0) {
|
||||
defer = proxies
|
||||
} else {
|
||||
if (ret.getAndSet(true)) return@launch
|
||||
it.resume(proxies)
|
||||
}
|
||||
FileLog.d(url)
|
||||
FileLog.d("Success")
|
||||
} catch (e: Exception) {
|
||||
FileLog.d(url)
|
||||
FileLog.e(e)
|
||||
exceptions[url] = e
|
||||
if (cl.decrementAndGet() == 0) {
|
||||
if (defer != null) {
|
||||
it.resume(defer!!)
|
||||
} else {
|
||||
it.resumeWithException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package tw.nekomimi.nekogram.parts
|
||||
|
||||
import org.telegram.messenger.SharedConfig
|
||||
import org.telegram.tgnet.ConnectionsManager
|
||||
import tw.nekomimi.nekogram.NekoConfig
|
||||
import java.util.*
|
||||
|
||||
object ProxySwitcher {
|
||||
|
||||
var currentConnectionState = ConnectionsManager.ConnectionStateWaitingForNetwork
|
||||
val switchTimer by lazy { Timer("Proxy Switch Timer") }
|
||||
var currentTask: SwitchTask? = null
|
||||
|
||||
fun cancel() {
|
||||
|
||||
currentTask = null
|
||||
switchTimer.purge()
|
||||
|
||||
}
|
||||
|
||||
fun reschedule() {
|
||||
|
||||
cancel()
|
||||
switchTimer.schedule(SwitchTask().also { currentTask = it }, 3333L)
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun didReceivedNotification(connectionState: Int) {
|
||||
|
||||
if (!NekoConfig.proxyAutoSwitch.Bool()) return
|
||||
|
||||
currentConnectionState = connectionState
|
||||
|
||||
if (currentConnectionState == ConnectionsManager.ConnectionStateConnectingToProxy) {
|
||||
|
||||
reschedule()
|
||||
|
||||
} else {
|
||||
|
||||
cancel()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SwitchTask : TimerTask() {
|
||||
|
||||
override fun run() {
|
||||
|
||||
if (this != currentTask) return
|
||||
|
||||
if (currentConnectionState != ConnectionsManager.ConnectionStateConnectingToProxy) return
|
||||
|
||||
var proxyList = SharedConfig.getProxyList().takeIf { it.size > 1 } ?: return
|
||||
|
||||
val current = SharedConfig.currentProxy ?: return
|
||||
|
||||
val currIndex = proxyList.indexOf(current)
|
||||
|
||||
if (currIndex > 0) {
|
||||
|
||||
val proxyListNew = LinkedList<SharedConfig.ProxyInfo>()
|
||||
|
||||
proxyListNew.addAll(proxyList.subList(currIndex, proxyList.size))
|
||||
proxyListNew.addAll(proxyList.subList(0, currIndex + 1))
|
||||
|
||||
proxyList = proxyListNew
|
||||
|
||||
}
|
||||
|
||||
if (proxyList.all { it.availableCheckTime == 0L }) {
|
||||
|
||||
if (proxyList.all { !it.checking }) {
|
||||
|
||||
repeat(3) { postCheckProxyList() }
|
||||
|
||||
}
|
||||
|
||||
if (currentConnectionState != ConnectionsManager.ConnectionStateConnectingToProxy) return
|
||||
|
||||
SharedConfig.setCurrentProxy(proxyList[0])
|
||||
|
||||
reschedule()
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
proxyList.forEach {
|
||||
|
||||
if (it.availableCheckTime != 0L && !it.available) return@forEach
|
||||
|
||||
if (currentConnectionState != ConnectionsManager.ConnectionStateConnectingToProxy) return
|
||||
|
||||
SharedConfig.setCurrentProxy(it)
|
||||
|
||||
reschedule()
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
|
||||
* Copyright (C) 2017 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import android.os.Build
|
||||
import android.os.SystemClock
|
||||
import android.system.OsConstants
|
||||
import androidx.annotation.MainThread
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import org.telegram.messenger.FileLog
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "GuardedProcessPool"
|
||||
}
|
||||
|
||||
private inner class Guard(private val cmd: List<String>) {
|
||||
private lateinit var process: Process
|
||||
|
||||
private fun streamLogger(input: InputStream, logger: (String) -> Unit) = try {
|
||||
input.bufferedReader().forEachLine(logger)
|
||||
} catch (_: IOException) { } // ignore
|
||||
|
||||
fun start() {
|
||||
process = ProcessBuilder(cmd).directory(ApplicationLoader.applicationContext.cacheDir).start()
|
||||
}
|
||||
|
||||
suspend fun looper(onRestartCallback: (suspend () -> Unit)?) {
|
||||
var running = true
|
||||
val cmdName = File(cmd.first()).nameWithoutExtension
|
||||
val exitChannel = Channel<Int>()
|
||||
try {
|
||||
while (true) {
|
||||
thread(name = "stderr-$cmdName") {
|
||||
streamLogger(process.errorStream) {
|
||||
FileLog.e("[$cmdName]$it")
|
||||
}
|
||||
}
|
||||
thread(name = "stdout-$cmdName") {
|
||||
streamLogger(process.inputStream) {
|
||||
FileLog.d("[$cmdName]$it")
|
||||
}
|
||||
// this thread also acts as a daemon thread for waitFor
|
||||
runBlocking { exitChannel.send(process.waitFor()) }
|
||||
}
|
||||
val startTime = SystemClock.elapsedRealtime()
|
||||
val exitCode = exitChannel.receive()
|
||||
running = false
|
||||
when {
|
||||
SystemClock.elapsedRealtime() - startTime < 1000 -> throw IOException(
|
||||
"$cmdName exits too fast (exit code: $exitCode)")
|
||||
exitCode == 128 + OsConstants.SIGKILL -> FileLog.w("$cmdName was killed")
|
||||
else -> FileLog.e(IOException("$cmdName unexpectedly exits with code $exitCode"))
|
||||
}
|
||||
start()
|
||||
running = true
|
||||
onRestartCallback?.invoke()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
FileLog.w("error occurred. stop guard: " + cmd.joinToString(" "))
|
||||
GlobalScope.launch(Dispatchers.Main) { onFatal(e) }
|
||||
} finally {
|
||||
if (running) withContext(NonCancellable) {
|
||||
process.destroy() // kill the process
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
if (withTimeoutOrNull(1000) { exitChannel.receive() } != null) return@withContext
|
||||
process.destroyForcibly() // Force to kill the process if it's still alive
|
||||
}
|
||||
exitChannel.receive()
|
||||
} // otherwise process already exited, nothing to be done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val coroutineContext = Dispatchers.Main.immediate + Job()
|
||||
|
||||
@MainThread
|
||||
fun start(cmd: List<String>, onRestartCallback: (suspend () -> Unit)? = null) {
|
||||
FileLog.d("start process: " + cmd.joinToString (" "))
|
||||
Guard(cmd).apply {
|
||||
start() // if start fails, IOException will be thrown directly
|
||||
launch { looper(onRestartCallback) }
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
fun close(scope: CoroutineScope) {
|
||||
cancel()
|
||||
coroutineContext[Job]!!.also { job -> scope.launch { job.join() } }
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.ServerSocket
|
||||
import kotlin.random.Random
|
||||
|
||||
object ProxyManager {
|
||||
|
||||
@JvmStatic
|
||||
fun mkPort(): Int {
|
||||
|
||||
var port: Int
|
||||
|
||||
do {
|
||||
|
||||
port = mkNewPort()
|
||||
|
||||
} while (!isProxyAvailable(port))
|
||||
|
||||
return port
|
||||
|
||||
}
|
||||
|
||||
private fun mkNewPort() = Random.nextInt(2048, 32768)
|
||||
|
||||
@JvmStatic
|
||||
fun isProxyAvailable(port: Int): Boolean {
|
||||
|
||||
if (port !in 2048 until 32768) return false
|
||||
|
||||
runCatching {
|
||||
|
||||
val server = ServerSocket()
|
||||
|
||||
server.bind(InetSocketAddress("127.0.0.1",port))
|
||||
|
||||
server.close()
|
||||
|
||||
Thread.sleep(1000L)
|
||||
|
||||
}.onFailure {
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,290 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import cn.hutool.core.codec.Base64
|
||||
import com.github.shadowsocks.plugin.PluginConfiguration
|
||||
import com.github.shadowsocks.plugin.PluginManager
|
||||
import com.github.shadowsocks.plugin.PluginOptions
|
||||
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.json.JSONObject
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import org.telegram.messenger.FileLog
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil
|
||||
import tw.nekomimi.nekogram.utils.FileUtil
|
||||
import java.io.File
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
class ShadowsocksLoader {
|
||||
|
||||
lateinit var bean: Bean
|
||||
var port by Delegates.notNull<Int>()
|
||||
var shadowsocksProcess: GuardedProcessPool? = null
|
||||
|
||||
fun initConfig(bean: Bean, port: Int) {
|
||||
|
||||
this.bean = bean
|
||||
this.port = port
|
||||
|
||||
}
|
||||
|
||||
fun start() {
|
||||
|
||||
stop()
|
||||
|
||||
val cacheCfg = File(ApplicationLoader.applicationContext.cacheDir, "ss_cfg_${bean.hash}.json")
|
||||
|
||||
shadowsocksProcess = GuardedProcessPool {
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
}.apply {
|
||||
|
||||
runCatching {
|
||||
|
||||
cacheCfg.writeText(bean.toJson().toString())
|
||||
|
||||
start(listOf(FileUtil.extLib("ss-local").path,
|
||||
"--local-addr", "127.0.0.1:$port",
|
||||
"--config", cacheCfg.path)) {
|
||||
|
||||
cacheCfg.delete()
|
||||
|
||||
}
|
||||
|
||||
}.onFailure { it ->
|
||||
|
||||
AlertUtil.showToast("${it.javaClass.simpleName}: ${it.message}")
|
||||
|
||||
cacheCfg.delete()
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
|
||||
if (shadowsocksProcess != null) {
|
||||
|
||||
val proc = shadowsocksProcess!!
|
||||
|
||||
thread {
|
||||
|
||||
runCatching {
|
||||
|
||||
runBlocking { proc.close(this) }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
shadowsocksProcess = null
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class Bean(
|
||||
var host: String = "",
|
||||
var remotePort: Int = 443,
|
||||
var password: String = "",
|
||||
var method: String = "aes-256-cfb",
|
||||
var plugin: String = "",
|
||||
var remarks: String? = null
|
||||
) {
|
||||
|
||||
init {
|
||||
|
||||
if (method == "plain") method = "none"
|
||||
|
||||
val pl = PluginConfiguration(plugin)
|
||||
|
||||
if (pl.selected.contains("v2ray") && pl.selected != "v2ray-plugin") {
|
||||
|
||||
pl.pluginsOptions["v2ray-plugin"] = pl.getOptions().apply { id = "v2ray-plugin" }
|
||||
pl.pluginsOptions.remove(pl.selected)
|
||||
pl.selected = "v2ray-plugin"
|
||||
|
||||
// reslove v2ray plugin
|
||||
|
||||
}
|
||||
|
||||
if (pl.selected == "obfs") {
|
||||
|
||||
pl.pluginsOptions["obfs-local"] = pl.getOptions().apply { id = "obfs-local" }
|
||||
pl.pluginsOptions.remove(pl.selected)
|
||||
pl.selected = "obfs-local"
|
||||
|
||||
// reslove clash obfs
|
||||
|
||||
}
|
||||
|
||||
plugin = pl.toString()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is Bean && hash == other.hash)
|
||||
}
|
||||
|
||||
/*
|
||||
init {
|
||||
|
||||
if (method !in methods) error("method $method not supported")
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
val hash = (host + remotePort + password + method).hashCode()
|
||||
|
||||
val pluginInitResult by lazy {
|
||||
PluginManager.init(PluginConfiguration(plugin ?: ""))
|
||||
}
|
||||
|
||||
fun toJson(): JSONObject = JSONObject().apply {
|
||||
put("server", host)
|
||||
put("server_port", remotePort)
|
||||
put("password", password)
|
||||
put("method", method)
|
||||
put("ipv6", true)
|
||||
if (pluginInitResult != null) {
|
||||
put("plugin", pluginInitResult!!.first)
|
||||
put("plugin_opts", pluginInitResult!!.second.toString())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun parseJson(ssObj: JSONObject): Bean {
|
||||
var pluginStr = ""
|
||||
val pId = ssObj.optString("plugin")
|
||||
if (!pId.isNullOrBlank()) {
|
||||
val plugin = PluginOptions(pId, ssObj.optString("plugin_opts"))
|
||||
pluginStr = plugin.toString(false)
|
||||
}
|
||||
return Bean(
|
||||
ssObj.getString("server"),
|
||||
ssObj.getInt("server_port"),
|
||||
ssObj.getString("password"),
|
||||
ssObj.getString("method"),
|
||||
pluginStr,
|
||||
ssObj.optString("remarks")
|
||||
)
|
||||
}
|
||||
|
||||
fun parse(url: String): Bean {
|
||||
|
||||
if (url.contains("@")) {
|
||||
|
||||
// ss-android style
|
||||
|
||||
val link = url.replace(SS_PROTOCOL, "https://").toHttpUrlOrNull()
|
||||
?: error("invalid ss-android link $url")
|
||||
|
||||
if (link.password.isNotBlank()) {
|
||||
|
||||
return Bean(
|
||||
link.host,
|
||||
link.port,
|
||||
link.password,
|
||||
link.username,
|
||||
link.queryParameter("plugin") ?: "",
|
||||
link.fragment
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
val methodAndPswd = Base64.decodeStr(link.username)
|
||||
|
||||
return Bean(
|
||||
link.host,
|
||||
link.port,
|
||||
methodAndPswd.substringAfter(":"),
|
||||
methodAndPswd.substringBefore(":"),
|
||||
link.queryParameter("plugin") ?: "",
|
||||
link.fragment
|
||||
)
|
||||
|
||||
} else {
|
||||
|
||||
// v2rayNG style
|
||||
|
||||
var v2Url = url
|
||||
|
||||
if (v2Url.contains("#")) v2Url = v2Url.substringBefore("#")
|
||||
|
||||
val link = ("https://" + Base64.decodeStr(v2Url.substringAfter(SS_PROTOCOL))).toHttpUrlOrNull()
|
||||
?: error("invalid v2rayNG link $url")
|
||||
|
||||
return Bean(
|
||||
link.host,
|
||||
link.port,
|
||||
link.password,
|
||||
link.username,
|
||||
"",
|
||||
link.fragment
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
val url = HttpUrl.Builder()
|
||||
.scheme("https")
|
||||
.encodedUsername(Base64.encodeUrlSafe("$method:$password"))
|
||||
.host(host)
|
||||
.port(remotePort)
|
||||
|
||||
if (!remarks.isNullOrBlank()) url.fragment(remarks)
|
||||
|
||||
if (plugin.isNotBlank()) url.addQueryParameter("plugin", plugin)
|
||||
|
||||
return url.build().toString().replace("https://", "ss://")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val methods = arrayOf(
|
||||
|
||||
"none",
|
||||
"rc4-md5",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf",
|
||||
"aes-128-gcm",
|
||||
"aes-192-gcm",
|
||||
"aes-256-gcm",
|
||||
"chacha20-ietf-poly1305",
|
||||
"xchacha20-ietf-poly1305"
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import cn.hutool.core.codec.Base64
|
||||
import com.v2ray.ang.V2RayConfig.SSR_PROTOCOL
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import org.json.JSONObject
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import org.telegram.messenger.FileLog
|
||||
import tw.nekomimi.nekogram.utils.FileUtil
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class ShadowsocksRLoader {
|
||||
|
||||
lateinit var bean: Bean
|
||||
var port by Delegates.notNull<Int>()
|
||||
var shadowsocksProcess: GuardedProcessPool? = null
|
||||
|
||||
fun initConfig(bean: Bean, port: Int) {
|
||||
|
||||
this.bean = bean
|
||||
this.port = port
|
||||
|
||||
}
|
||||
|
||||
fun start() {
|
||||
|
||||
stop()
|
||||
|
||||
val cacheCfg = File(ApplicationLoader.applicationContext.cacheDir, "ssr_cfg_${bean.hash}.json")
|
||||
|
||||
cacheCfg.writeText(bean.toJson().toString())
|
||||
|
||||
shadowsocksProcess = GuardedProcessPool {
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
}.apply {
|
||||
|
||||
runCatching {
|
||||
|
||||
start(listOf(FileUtil.extLib("ssr-local").path,
|
||||
"-b", "127.0.0.1",
|
||||
"--host", bean.host,
|
||||
"-t", "600",
|
||||
"-c", cacheCfg.path,
|
||||
"-l", port.toString())) {
|
||||
|
||||
cacheCfg.delete()
|
||||
|
||||
}
|
||||
|
||||
}.onFailure {
|
||||
|
||||
cacheCfg.delete()
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
|
||||
if (shadowsocksProcess != null) {
|
||||
|
||||
val proc = shadowsocksProcess!!
|
||||
|
||||
thread {
|
||||
|
||||
runCatching {
|
||||
|
||||
runBlocking { proc.close(this) }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
shadowsocksProcess = null
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class Bean(
|
||||
var host: String = "",
|
||||
var remotePort: Int = 443,
|
||||
var password: String = "",
|
||||
var protocol: String = "origin",
|
||||
var protocol_param: String = "",
|
||||
var obfs: String = "plain",
|
||||
var obfs_param: String = "",
|
||||
var method: String = "aes-256-cfb",
|
||||
var remarks: String? = null
|
||||
) {
|
||||
|
||||
val hash get() = (host + remotePort + password + protocol + obfs + method).hashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is Bean && hash == other.hash)
|
||||
}
|
||||
|
||||
/*
|
||||
init {
|
||||
|
||||
if (method !in methods) error("method $method not supported")
|
||||
if (protocol !in protocols) error("protocol $protocol not supported")
|
||||
if (obfs !in obfses) error("obfs $obfs not supported")
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
fun toJson(): JSONObject = JSONObject().apply {
|
||||
put("server", host)
|
||||
put("server_port", remotePort)
|
||||
put("password", password)
|
||||
put("method", method)
|
||||
put("protocol", protocol)
|
||||
put("protocol_param", protocol_param)
|
||||
put("obfs", obfs)
|
||||
put("obfs_param", obfs_param)
|
||||
put("remarks", remarks)
|
||||
put("route", "all")
|
||||
put("remote_dns", "8.8.8.8:53")
|
||||
put("ipv6", true)
|
||||
put("metered", false)
|
||||
put("proxy_apps", JSONObject().apply {
|
||||
put("enabled", false)
|
||||
})
|
||||
put("udpdns", false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun parse(url: String): Bean {
|
||||
|
||||
val params = Base64.decodeStr(url.substringAfter(SSR_PROTOCOL)).split(":")
|
||||
|
||||
val bean = Bean(params[0],
|
||||
params[1].toInt(),
|
||||
protocol = params[2],
|
||||
method = params[3],
|
||||
obfs = params[4],
|
||||
password = Base64.decodeStr(params[5].substringBefore("/")))
|
||||
|
||||
val httpUrl = ("https://localhost" + params[5].substringAfter("/")).toHttpUrl()
|
||||
|
||||
runCatching {
|
||||
|
||||
bean.obfs_param = Base64.decodeStr(httpUrl.queryParameter("obfsparam")!!)
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
bean.protocol_param = Base64.decodeStr(httpUrl.queryParameter("protoparam")!!)
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
val remarks = httpUrl.queryParameter("remarks")
|
||||
|
||||
if (remarks?.isNotBlank() == true) {
|
||||
|
||||
bean.remarks = Base64.decodeStr(remarks)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bean
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
return "ssr://" + Base64.encodeUrlSafe("%s:%d:%s:%s:%s:%s/?obfsparam=%s&protoparam=%s&remarks=%s".format(Locale.ENGLISH, host, remotePort, protocol, method, obfs,
|
||||
Base64.encodeUrlSafe("%s".format(Locale.ENGLISH, password)),
|
||||
Base64.encodeUrlSafe("%s".format(Locale.ENGLISH, obfs_param)),
|
||||
Base64.encodeUrlSafe("%s".format(Locale.ENGLISH, protocol_param)),
|
||||
Base64.encodeUrlSafe("%s".format(Locale.ENGLISH, remarks ?: ""))))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val methods = arrayOf(
|
||||
|
||||
"none",
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5",
|
||||
"rc4-md5-6",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf"
|
||||
|
||||
)
|
||||
|
||||
val protocols = arrayOf(
|
||||
"origin",
|
||||
"verify_simple",
|
||||
"verify_sha1",
|
||||
"auth_sha1",
|
||||
"auth_sha1_v2",
|
||||
"auth_sha1_v4",
|
||||
"auth_aes128_sha1",
|
||||
"auth_aes128_md5",
|
||||
"auth_chain_a",
|
||||
"auth_chain_b"
|
||||
)
|
||||
|
||||
val obfses = arrayOf(
|
||||
"plain",
|
||||
"http_simple",
|
||||
"http_post",
|
||||
"tls_simple",
|
||||
"tls1.2_ticket_auth"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,469 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.ui.PopupBuilder;
|
||||
|
||||
public class ShadowsocksRSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
|
||||
private EditTextBoldCursor ipField;
|
||||
private EditTextBoldCursor portField;
|
||||
private EditTextBoldCursor passwordField;
|
||||
private TextSettingsCell methodField;
|
||||
|
||||
private TextSettingsCell protocolField;
|
||||
private EditTextBoldCursor protocolParamField;
|
||||
|
||||
private TextSettingsCell obfsField;
|
||||
private EditTextBoldCursor obfsParamField;
|
||||
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private TextInfoPrivacyCell bottomCell;
|
||||
|
||||
private SharedConfig.ShadowsocksRProxy currentProxyInfo;
|
||||
private ShadowsocksRLoader.Bean currentBean;
|
||||
|
||||
private boolean ignoreOnTextChange;
|
||||
|
||||
private static final int done_button = 1;
|
||||
|
||||
public class TypeCell extends FrameLayout {
|
||||
|
||||
private TextView textView;
|
||||
private ImageView checkImage;
|
||||
private boolean needDivider;
|
||||
|
||||
public TypeCell(Context context) {
|
||||
super(context);
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setValue(String name, boolean checked, boolean divider) {
|
||||
textView.setText(name);
|
||||
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
}
|
||||
|
||||
public void setTypeChecked(boolean value) {
|
||||
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ShadowsocksRSettingsActivity() {
|
||||
super();
|
||||
currentBean = new ShadowsocksRLoader.Bean();
|
||||
}
|
||||
|
||||
public ShadowsocksRSettingsActivity(SharedConfig.ShadowsocksRProxy proxyInfo) {
|
||||
super();
|
||||
currentProxyInfo = proxyInfo;
|
||||
currentBean = proxyInfo.bean;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(ipField.getText())) {
|
||||
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(portField.getText())) {
|
||||
|
||||
portField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(portField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(passwordField.getText())) {
|
||||
|
||||
passwordField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(passwordField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
currentBean.setHost(ipField.getText().toString());
|
||||
currentBean.setRemotePort(Utilities.parseInt(portField.getText().toString()));
|
||||
currentBean.setPassword(passwordField.getText().toString());
|
||||
currentBean.setMethod(methodField.getValueTextView().getText().toString());
|
||||
currentBean.setProtocol(protocolField.getValueTextView().getText().toString());
|
||||
currentBean.setProtocol_param(protocolParamField.getText().toString());
|
||||
currentBean.setObfs(obfsField.getValueTextView().getText().toString());
|
||||
currentBean.setObfs_param(obfsParamField.getText().toString());
|
||||
currentBean.setRemarks(remarksField.getText().toString());
|
||||
|
||||
if (currentProxyInfo == null) {
|
||||
currentProxyInfo = new SharedConfig.ShadowsocksRProxy(currentBean);
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
} else {
|
||||
currentProxyInfo.proxyCheckPingId = 0;
|
||||
currentProxyInfo.availableCheckTime = 0;
|
||||
currentProxyInfo.ping = 0;
|
||||
SharedConfig.saveProxyList();
|
||||
SharedConfig.setProxyEnable(false);
|
||||
}
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ActionBarMenuItem doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[6];
|
||||
|
||||
for (int a = 0; a < 6; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
EditTextBoldCursor cursor = mkCursor();
|
||||
inputFields[a] = cursor;
|
||||
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
switch (a) {
|
||||
case 0:
|
||||
ipField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
|
||||
cursor.setText(currentBean.getHost());
|
||||
break;
|
||||
case 1:
|
||||
portField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPort", R.string.UseProxyPort));
|
||||
cursor.setText("" + currentBean.getRemotePort());
|
||||
break;
|
||||
case 2:
|
||||
passwordField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword));
|
||||
cursor.setText(currentBean.getPassword());
|
||||
break;
|
||||
case 3:
|
||||
protocolParamField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("SSRProtocolParams", R.string.SSRProtocolParams));
|
||||
cursor.setText(currentBean.getProtocol_param());
|
||||
break;
|
||||
case 4:
|
||||
obfsParamField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("SSRObfsParam", R.string.SSRObfsParam));
|
||||
cursor.setText(currentBean.getObfs_param());
|
||||
break;
|
||||
case 5:
|
||||
remarksField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
cursor.setText(currentBean.getRemarks());
|
||||
break;
|
||||
}
|
||||
cursor.setSelection(cursor.length());
|
||||
|
||||
cursor.setPadding(0, 0, 0, 0);
|
||||
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
|
||||
|
||||
}
|
||||
|
||||
inputFieldsContainer.addView((View) ipField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) portField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) passwordField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
|
||||
methodField = new TextSettingsCell(context);
|
||||
methodField.setBackground(Theme.getSelectorDrawable(false));
|
||||
methodField.setTextAndValue(LocaleController.getString("SSMethod", R.string.SSMethod), currentBean.getMethod(), false);
|
||||
container.addView(methodField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
methodField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(ShadowsocksRLoader.Companion.getMethods(), (__,value) -> {
|
||||
|
||||
methodField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
container = new FrameLayout(context);
|
||||
protocolField = new TextSettingsCell(context);
|
||||
protocolField.setBackground(Theme.getSelectorDrawable(false));
|
||||
protocolField.setTextAndValue(LocaleController.getString("SSRProtocol", R.string.SSRProtocol), currentBean.getProtocol(), false);
|
||||
container.addView(protocolField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
protocolField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(ShadowsocksRLoader.Companion.getProtocols(), (__,value) -> {
|
||||
|
||||
protocolField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) protocolParamField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
container = new FrameLayout(context);
|
||||
obfsField = new TextSettingsCell(context);
|
||||
obfsField.setBackground(Theme.getSelectorDrawable(false));
|
||||
obfsField.setTextAndValue(LocaleController.getString("SSRObfs", R.string.SSRObfs), currentBean.getObfs(), false);
|
||||
container.addView(obfsField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
obfsField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(ShadowsocksRLoader.Companion.getObfses(), (__,value) -> {
|
||||
|
||||
obfsField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) obfsParamField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
bottomCell = new TextInfoPrivacyCell(context);
|
||||
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
bottomCell.setText(LocaleController.getString("ProxyInfoSSR", R.string.ProxyInfoSSR));
|
||||
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && !backward && currentProxyInfo == null) {
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,569 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.github.shadowsocks.plugin.PluginConfiguration;
|
||||
import com.github.shadowsocks.plugin.PluginContract;
|
||||
import com.github.shadowsocks.plugin.PluginList;
|
||||
import com.github.shadowsocks.plugin.PluginManager;
|
||||
import com.github.shadowsocks.plugin.PluginOptions;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.ui.PopupBuilder;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public class ShadowsocksSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
|
||||
private EditTextBoldCursor ipField;
|
||||
private EditTextBoldCursor portField;
|
||||
private EditTextBoldCursor passwordField;
|
||||
private TextSettingsCell methodField;
|
||||
private TextSettingsCell pluginField;
|
||||
private TextSettingsCell pluginOptsField;
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private TextInfoPrivacyCell bottomCell;
|
||||
|
||||
private SharedConfig.ShadowsocksProxy currentProxyInfo;
|
||||
private ShadowsocksLoader.Bean currentBean;
|
||||
private PluginConfiguration plugin;
|
||||
|
||||
private boolean ignoreOnTextChange;
|
||||
|
||||
private static final int done_button = 1;
|
||||
|
||||
public class TypeCell extends FrameLayout {
|
||||
|
||||
private TextView textView;
|
||||
private ImageView checkImage;
|
||||
private boolean needDivider;
|
||||
|
||||
public TypeCell(Context context) {
|
||||
super(context);
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setValue(String name, boolean checked, boolean divider) {
|
||||
textView.setText(name);
|
||||
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
}
|
||||
|
||||
public void setTypeChecked(boolean value) {
|
||||
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ShadowsocksSettingsActivity() {
|
||||
super();
|
||||
currentBean = new ShadowsocksLoader.Bean();
|
||||
plugin = new PluginConfiguration("");
|
||||
}
|
||||
|
||||
public ShadowsocksSettingsActivity(SharedConfig.ShadowsocksProxy proxyInfo) {
|
||||
super();
|
||||
currentProxyInfo = proxyInfo;
|
||||
currentBean = proxyInfo.bean;
|
||||
plugin = new PluginConfiguration(currentBean.getPlugin());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(ipField.getText())) {
|
||||
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(portField.getText())) {
|
||||
|
||||
portField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(portField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(passwordField.getText()) && !"plain".equals(methodField.getTextView().getText().toString().toLowerCase())) {
|
||||
|
||||
passwordField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(passwordField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
currentBean.setHost(ipField.getText().toString());
|
||||
currentBean.setRemotePort(Utilities.parseInt(portField.getText().toString()));
|
||||
currentBean.setPassword(passwordField.getText().toString());
|
||||
currentBean.setMethod(methodField.getValueTextView().getText().toString());
|
||||
currentBean.setPlugin(plugin.toString());
|
||||
currentBean.setRemarks(remarksField.getText().toString());
|
||||
|
||||
if (currentProxyInfo == null) {
|
||||
currentProxyInfo = new SharedConfig.ShadowsocksProxy(currentBean);
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
} else {
|
||||
currentProxyInfo.proxyCheckPingId = 0;
|
||||
currentProxyInfo.availableCheckTime = 0;
|
||||
currentProxyInfo.ping = 0;
|
||||
SharedConfig.saveProxyList();
|
||||
SharedConfig.setProxyEnable(false);
|
||||
}
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ActionBarMenuItem doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[4];
|
||||
|
||||
for (int a = 0; a < 4; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
EditTextBoldCursor cursor = mkCursor();
|
||||
inputFields[a] = cursor;
|
||||
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
switch (a) {
|
||||
case 0:
|
||||
ipField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
|
||||
cursor.setText(currentBean.getHost());
|
||||
break;
|
||||
case 1:
|
||||
portField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPort", R.string.UseProxyPort));
|
||||
cursor.setText("" + currentBean.getRemotePort());
|
||||
break;
|
||||
case 2:
|
||||
passwordField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword));
|
||||
cursor.setText(currentBean.getPassword());
|
||||
break;
|
||||
case 3:
|
||||
remarksField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
cursor.setText(currentBean.getRemarks());
|
||||
break;
|
||||
}
|
||||
cursor.setSelection(cursor.length());
|
||||
|
||||
cursor.setPadding(0, 0, 0, 0);
|
||||
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
|
||||
|
||||
}
|
||||
|
||||
inputFieldsContainer.addView((View) ipField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) portField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) passwordField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
|
||||
methodField = new TextSettingsCell(context);
|
||||
methodField.setBackground(Theme.getSelectorDrawable(false));
|
||||
methodField.setTextAndValue(LocaleController.getString("SSMethod", R.string.SSMethod), currentBean.getMethod(), false);
|
||||
container.addView(methodField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
methodField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(ShadowsocksLoader.Companion.getMethods(), (__, value) -> {
|
||||
|
||||
methodField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
container = new FrameLayout(context);
|
||||
pluginField = new TextSettingsCell(context);
|
||||
pluginField.setBackground(Theme.getSelectorDrawable(false));
|
||||
pluginField.setTextAndValue(LocaleController.getString("SSPlugin", R.string.SSPlugin), plugin.getSelectedName(), false);
|
||||
container.addView(pluginField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
pluginField.setOnClickListener((v) -> {
|
||||
|
||||
PluginList plugins = PluginManager.fetchPlugins();
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
try {
|
||||
|
||||
select.setItems(plugins.getLookupNames(), (index, __) -> {
|
||||
|
||||
String pluginId = plugins.get(index).getId();
|
||||
|
||||
plugin.setSelected(pluginId);
|
||||
|
||||
((View) pluginOptsField.getParent()).setVisibility(StrUtil.isBlank(pluginId) ? View.GONE : View.VISIBLE);
|
||||
|
||||
pluginField.getValueTextView().setText(plugin.getSelectedName());
|
||||
pluginOptsField.getValueTextView().setText(plugin.getOptions(pluginId).toString());
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
AlertUtil.showSimpleAlert(getParentActivity(),e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
container = new FrameLayout(context);
|
||||
pluginOptsField = new TextSettingsCell(context);
|
||||
pluginOptsField.setBackground(Theme.getSelectorDrawable(false));
|
||||
pluginOptsField.setTextAndValue(LocaleController.getString("SSPluginOpts", R.string.SSPluginOpts), plugin.getOptions().toString(), false);
|
||||
container.addView(pluginOptsField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
pluginOptsField.setOnClickListener((v) -> {
|
||||
|
||||
Intent intent = PluginManager.buildIntent(plugin.getSelected(), PluginContract.ACTION_CONFIGURE);
|
||||
intent.putExtra(PluginContract.EXTRA_OPTIONS, plugin.getOptions().toString());
|
||||
|
||||
if (intent.resolveActivity(getParentActivity().getPackageManager()) == null) {
|
||||
showPluginEditor();
|
||||
} else {
|
||||
startActivityForResult(intent, 1919);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
((View) pluginOptsField.getParent()).setVisibility(StrUtil.isBlank(plugin.getSelected()) ? View.GONE : View.VISIBLE);
|
||||
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
bottomCell = new TextInfoPrivacyCell(context);
|
||||
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
bottomCell.setText(LocaleController.getString("ProxyInfoSS", R.string.ProxyInfoSS));
|
||||
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityResultFragment(int requestCode, int resultCode, Intent data) {
|
||||
|
||||
if (requestCode == 1919) {
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
||||
String options = data.getStringExtra(PluginContract.EXTRA_OPTIONS);
|
||||
|
||||
if (options != null) {
|
||||
|
||||
onPreferenceChange(options);
|
||||
|
||||
}
|
||||
|
||||
} else if (resultCode == PluginContract.RESULT_FALLBACK) {
|
||||
|
||||
showPluginEditor();
|
||||
|
||||
}
|
||||
|
||||
} else if (requestCode == 810) {
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
||||
CharSequence helpMessage = data.getCharSequenceExtra(PluginContract.EXTRA_HELP_MESSAGE);
|
||||
|
||||
if (StrUtil.isBlank(helpMessage)) {
|
||||
|
||||
helpMessage = "No Help :(";
|
||||
|
||||
}
|
||||
|
||||
AlertUtil.showSimpleAlert(getParentActivity(),LocaleController.getString("BotHelp",R.string.BotHelp),helpMessage.toString());
|
||||
|
||||
} else {
|
||||
|
||||
AlertUtil.showSimpleAlert(getParentActivity(),"Get Help Message Error :(");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showPluginEditor() {
|
||||
|
||||
BottomBuilder builder = new BottomBuilder(getParentActivity());
|
||||
|
||||
builder.addTitle(LocaleController.getString("SSPluginOpts", R.string.SSPluginOpts));
|
||||
|
||||
EditText options = builder.addEditText();
|
||||
options.setSingleLine(false);
|
||||
options.setGravity(Gravity.TOP | LocaleController.generateFlagStart());
|
||||
options.setMinLines(3);
|
||||
options.setText(plugin.getOptions().toString());
|
||||
|
||||
Intent intent = PluginManager.buildIntent(plugin.getSelected(), PluginContract.ACTION_HELP);
|
||||
intent.putExtra(PluginContract.EXTRA_OPTIONS, plugin.getOptions().toString());
|
||||
if (intent.resolveActivity(getParentActivity().getPackageManager()) != null) {
|
||||
|
||||
builder.addButton(LocaleController.getString("BotHelp", R.string.BotHelp), false,true, (it) -> {
|
||||
|
||||
getParentActivity().startActivityForResult(intent, 810);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
builder.addCancelButton(false);
|
||||
|
||||
} else {
|
||||
|
||||
builder.addCancelButton();
|
||||
|
||||
}
|
||||
|
||||
builder.addOkButton((it) -> {
|
||||
|
||||
onPreferenceChange(options.getText().toString());
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
builder.show();
|
||||
|
||||
}
|
||||
|
||||
private void onPreferenceChange(String newValue) {
|
||||
String selected = plugin.getSelected();
|
||||
plugin.getPluginsOptions().put(selected, new PluginOptions(selected, newValue));
|
||||
pluginOptsField.getValueTextView().setText(newValue);
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && !backward && currentProxyInfo == null) {
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.dizitart.no2.Document;
|
||||
import org.dizitart.no2.mapper.Mappable;
|
||||
import org.dizitart.no2.mapper.NitriteMapper;
|
||||
import org.dizitart.no2.objects.Id;
|
||||
import org.dizitart.no2.objects.Index;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.parts.ProxyLoadsKt;
|
||||
|
||||
@Index("id")
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SubInfo implements Mappable {
|
||||
|
||||
@Id
|
||||
public long id;
|
||||
public String name;
|
||||
public List<String> urls = new LinkedList<>();
|
||||
public List<String> proxies = new LinkedList<>();
|
||||
public Long lastFetch = -1L;
|
||||
public boolean enable = true;
|
||||
public boolean internal;
|
||||
|
||||
public String displayName() {
|
||||
|
||||
if (id == SubManager.publicProxySubID)
|
||||
return LocaleController.getString("PublicPrefix", R.string.PublicPrefix);
|
||||
|
||||
if (name.length() < 10) return name;
|
||||
|
||||
return name.substring(0, 10) + "...";
|
||||
}
|
||||
|
||||
public List<String> reloadProxies() throws IOException {
|
||||
|
||||
HashMap<String, Exception> exceptions = new HashMap<>();
|
||||
|
||||
try {
|
||||
if (id == SubManager.publicProxySubID) {
|
||||
if (!NekoConfig.enablePublicProxy.Bool())
|
||||
return new ArrayList<>();
|
||||
List<String> pubs = ProxyLoadsKt.loadProxiesPublic(urls, exceptions);
|
||||
if (!NekoConfig.enablePublicProxy.Bool())
|
||||
return new ArrayList<>();
|
||||
else
|
||||
return pubs;
|
||||
} else {
|
||||
return ProxyLoadsKt.loadProxies(urls, exceptions);
|
||||
}
|
||||
// return id == SubManager.publicProxySubID ? :
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
throw new AllTriesFailed(exceptions);
|
||||
|
||||
}
|
||||
|
||||
public static class AllTriesFailed extends IOException {
|
||||
|
||||
public AllTriesFailed(HashMap<String, Exception> exceptions) {
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
public HashMap<String, Exception> exceptions;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, Exception> e : exceptions.entrySet()) {
|
||||
|
||||
errors.append(e.getKey()).append(": ");
|
||||
|
||||
errors.append(e.getValue().getClass().getSimpleName());
|
||||
|
||||
if (!StrUtil.isBlank(e.getValue().getMessage())) {
|
||||
|
||||
errors.append(" ( ");
|
||||
errors.append(e.getValue().getMessage());
|
||||
errors.append(" )");
|
||||
|
||||
}
|
||||
|
||||
errors.append("\n\n");
|
||||
|
||||
}
|
||||
|
||||
return errors.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SubInfo subInfo = (SubInfo) o;
|
||||
return id == subInfo.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document write(NitriteMapper mapper) {
|
||||
|
||||
Document document = new Document();
|
||||
|
||||
document.put("id", id);
|
||||
document.put("name", name);
|
||||
document.put("urls", urls);
|
||||
document.put("proxies", proxies);
|
||||
document.put("lastFetch", lastFetch);
|
||||
document.put("enable", enable);
|
||||
document.put("internal", internal);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(NitriteMapper mapper, Document document) {
|
||||
|
||||
id = document.get("id", Long.class);
|
||||
name = document.get("name", String.class);
|
||||
urls = (List<String>) document.get("urls");
|
||||
proxies = (List<String>) document.get("proxies");
|
||||
|
||||
lastFetch = document.get("lastFetch", Long.class);
|
||||
enable = document.get("enable", Boolean.class);
|
||||
internal = document.get("internal", Boolean.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import org.dizitart.no2.objects.filters.ObjectFilters
|
||||
import org.telegram.messenger.LocaleController
|
||||
import org.telegram.messenger.R
|
||||
import tw.nekomimi.nekogram.database.mkDatabase
|
||||
|
||||
object SubManager {
|
||||
|
||||
val database by lazy { mkDatabase("proxy_sub") }
|
||||
|
||||
const val publicProxySubID = 1L
|
||||
|
||||
@JvmStatic
|
||||
val count
|
||||
get() = subList.find().totalCount()
|
||||
|
||||
@JvmStatic
|
||||
val subList by lazy {
|
||||
|
||||
database.getRepository("proxy_sub", SubInfo::class.java).apply {
|
||||
|
||||
val public = find(ObjectFilters.eq("id", publicProxySubID)).firstOrDefault()
|
||||
|
||||
update(SubInfo().apply {
|
||||
// SubManager.kt -> SubInfo.java -> ProxyLoads.kt
|
||||
|
||||
name = LocaleController.getString("NekoXProxy", R.string.NekoXProxy)
|
||||
enable = public?.enable ?: true
|
||||
|
||||
urls = listOf(
|
||||
"https://nekox.pages.dev/proxy_list_pro", // Note: NO DoH apply to here and neko.services now.
|
||||
"https://github.com/NekoX-Dev/ProxyList/blob/master/proxy_list_pro@js-file-line\">@<",
|
||||
"https://api.github.com/repos/NekoX-Dev/ProxyList/contents/proxy_list_pro?ref=master@\"content\": \"@\"",
|
||||
)
|
||||
|
||||
id = publicProxySubID
|
||||
internal = true
|
||||
|
||||
proxies = public?.proxies ?: listOf()
|
||||
|
||||
}, true)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,347 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
public class SubSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditText[] inputFields;
|
||||
|
||||
private EditText urlsField;
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private SubInfo subInfo;
|
||||
|
||||
private boolean ignoreOnTextChange;
|
||||
|
||||
private static int done_button = 1;
|
||||
private static int menu_delete = 2;
|
||||
|
||||
public SubSettingsActivity() {
|
||||
super();
|
||||
subInfo = new SubInfo();
|
||||
subInfo.id = 0L;
|
||||
}
|
||||
|
||||
public SubSettingsActivity(SubInfo subInfo) {
|
||||
super();
|
||||
this.subInfo = subInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxySubDetails", R.string.ProxySubDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(urlsField.getText())) {
|
||||
|
||||
urlsField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(urlsField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(remarksField.getText())) {
|
||||
|
||||
remarksField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(remarksField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
subInfo.urls = ArraysKt.toList(urlsField.getText().toString().split("\n"));
|
||||
subInfo.name = remarksField.getText().toString();
|
||||
|
||||
doGetProxies();
|
||||
|
||||
} else if (id == menu_delete) {
|
||||
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
LocaleController.getString("SubscriptionDelete", R.string.SubscriptionDelete),
|
||||
R.drawable.baseline_delete_24, LocaleController.getString("Delete", R.string.Delete),
|
||||
true, () -> {
|
||||
|
||||
AlertDialog pro = AlertUtil.showProgress(getParentActivity());
|
||||
|
||||
pro.show();
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
SubManager.getSubList().remove(subInfo);
|
||||
|
||||
SharedConfig.reloadProxyList();
|
||||
|
||||
UIUtil.runOnUIThread(() -> {
|
||||
|
||||
pro.dismiss();
|
||||
|
||||
finishFragment();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ActionBarMenu menu = actionBar.createMenu();
|
||||
|
||||
if (subInfo.id != 0) {
|
||||
|
||||
menu.addItem(menu_delete, R.drawable.baseline_delete_24, AndroidUtilities.dp(56)).setContentDescription(LocaleController.getString("Delete", R.string.Delete));
|
||||
|
||||
}
|
||||
|
||||
menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)).setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditText[2];
|
||||
|
||||
urlsField = new EditText(context);
|
||||
inputFields[0] = urlsField;
|
||||
urlsField.setImeOptions(InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE);
|
||||
urlsField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
|
||||
urlsField.setHint(LocaleController.getString("SubscriptionUrls", R.string.SubscriptionUrls));
|
||||
urlsField.setText(CollectionsKt.joinToString(subInfo.urls, "\n", "", "", -1, "", null));
|
||||
urlsField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
urlsField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
urlsField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
urlsField.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||
urlsField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
urlsField.setSingleLine(false);
|
||||
urlsField.setMinLines(6);
|
||||
|
||||
inputFieldsContainer.addView(urlsField, LayoutHelper.createLinear(-1, -2, 17, 0, 17, 0));
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
|
||||
remarksField = mkCursor();
|
||||
inputFields[1] = remarksField;
|
||||
remarksField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
remarksField.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
remarksField.setText(subInfo.name);
|
||||
remarksField.setSelection(remarksField.length());
|
||||
|
||||
container.addView(remarksField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, 0, 17, 0));
|
||||
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
public void doGetProxies() {
|
||||
|
||||
AlertDialog pro = AlertUtil.showProgress(getParentActivity(), LocaleController.getString("SubscriptionUpdating", R.string.SubscriptionUpdating));
|
||||
|
||||
AtomicBoolean canceled = new AtomicBoolean();
|
||||
|
||||
pro.setOnCancelListener((it) -> {
|
||||
|
||||
canceled.set(true);
|
||||
|
||||
});
|
||||
|
||||
pro.show();
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
try {
|
||||
|
||||
subInfo.proxies = subInfo.reloadProxies();
|
||||
subInfo.lastFetch = System.currentTimeMillis();
|
||||
|
||||
} catch (IOException allTriesFailed) {
|
||||
|
||||
if (canceled.get()) return;
|
||||
|
||||
UIUtil.runOnUIThread(pro::dismiss);
|
||||
|
||||
AlertUtil.showSimpleAlert(getParentActivity(), "tries failed: " + allTriesFailed.toString().trim());
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (subInfo.id == 0) subInfo.id = SubManager.getCount() + 10;
|
||||
|
||||
do {
|
||||
|
||||
try {
|
||||
SubManager.getSubList().update(subInfo, true);
|
||||
break;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
subInfo.id ++;
|
||||
|
||||
} while (true);
|
||||
|
||||
SharedConfig.reloadProxyList();
|
||||
|
||||
UIUtil.runOnUIThread(() -> {
|
||||
|
||||
pro.dismiss();
|
||||
|
||||
finishFragment();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setText(Theme.getColor(Theme.key_windowBackgroundWhiteInputField));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,378 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.v2ray.ang.V2RayConfig;
|
||||
import com.v2ray.ang.dto.AngConfig;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
public class TrojanSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
|
||||
private EditTextBoldCursor ipField;
|
||||
private EditTextBoldCursor portField;
|
||||
private EditTextBoldCursor passwordField;
|
||||
private EditTextBoldCursor sniField;
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private TextInfoPrivacyCell bottomCell;
|
||||
private ActionBarMenuItem doneItem;
|
||||
|
||||
private SharedConfig.VmessProxy currentProxyInfo;
|
||||
private AngConfig.VmessBean currentBean;
|
||||
|
||||
private boolean ignoreOnTextChange;
|
||||
|
||||
private static final int done_button = 1;
|
||||
|
||||
public class TypeCell extends FrameLayout {
|
||||
|
||||
private TextView textView;
|
||||
private ImageView checkImage;
|
||||
private boolean needDivider;
|
||||
|
||||
public TypeCell(Context context) {
|
||||
super(context);
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setValue(String name, boolean checked, boolean divider) {
|
||||
textView.setText(name);
|
||||
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
}
|
||||
|
||||
public void setTypeChecked(boolean value) {
|
||||
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TrojanSettingsActivity() {
|
||||
super();
|
||||
currentBean = new AngConfig.VmessBean();
|
||||
currentBean.setConfigType(V2RayConfig.EConfigType.Trojan);
|
||||
}
|
||||
|
||||
public TrojanSettingsActivity(SharedConfig.VmessProxy proxyInfo) {
|
||||
super();
|
||||
currentProxyInfo = proxyInfo;
|
||||
currentBean = proxyInfo.bean;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(ipField.getText())) {
|
||||
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(portField.getText())) {
|
||||
|
||||
portField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(portField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(passwordField.getText())) {
|
||||
|
||||
passwordField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(passwordField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
currentBean.setAddress(ipField.getText().toString());
|
||||
currentBean.setPort(Utilities.parseInt(portField.getText().toString()));
|
||||
currentBean.setId(passwordField.getText().toString());
|
||||
currentBean.setRequestHost(sniField.getText().toString());
|
||||
currentBean.setRemarks(remarksField.getText().toString());
|
||||
|
||||
if (currentProxyInfo == null) {
|
||||
currentProxyInfo = new SharedConfig.VmessProxy(currentBean);
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
} else {
|
||||
currentProxyInfo.proxyCheckPingId = 0;
|
||||
currentProxyInfo.availableCheckTime = 0;
|
||||
currentProxyInfo.ping = 0;
|
||||
SharedConfig.saveProxyList();
|
||||
SharedConfig.setProxyEnable(false);
|
||||
}
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[5];
|
||||
|
||||
for (int a = 0; a < 5; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
EditTextBoldCursor cursor = mkCursor();
|
||||
inputFields[a] = cursor;
|
||||
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
switch (a) {
|
||||
case 0:
|
||||
ipField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
|
||||
cursor.setText(currentBean.getAddress());
|
||||
break;
|
||||
case 1:
|
||||
portField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPort", R.string.UseProxyPort));
|
||||
cursor.setText("" + currentBean.getPort());
|
||||
break;
|
||||
case 2:
|
||||
passwordField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("SSPassword", R.string.SSPassword));
|
||||
cursor.setText(currentBean.getId());
|
||||
break;
|
||||
case 3:
|
||||
remarksField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
cursor.setText(currentBean.getRemarks());
|
||||
break;
|
||||
case 4:
|
||||
sniField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("TrojanSNI", R.string.TrojanSNI));
|
||||
cursor.setText(currentBean.getRequestHost());
|
||||
break;
|
||||
}
|
||||
cursor.setSelection(cursor.length());
|
||||
|
||||
cursor.setPadding(0, 0, 0, 0);
|
||||
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
|
||||
|
||||
}
|
||||
|
||||
inputFieldsContainer.addView((View) ipField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) portField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) passwordField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) sniField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
bottomCell = new TextInfoPrivacyCell(context);
|
||||
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
bottomCell.setText(LocaleController.getString("ProxyInfoTrojan", R.string.ProxyInfoTrojan));
|
||||
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && !backward && currentProxyInfo == null) {
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,442 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy
|
||||
|
||||
import cn.hutool.core.codec.Base64
|
||||
import com.google.gson.Gson
|
||||
import com.v2ray.ang.V2RayConfig
|
||||
import com.v2ray.ang.V2RayConfig.SOCKS_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.TROJAN_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS1_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS_PROTOCOL
|
||||
import com.v2ray.ang.dto.AngConfig.VmessBean
|
||||
import com.v2ray.ang.dto.VmessQRCode
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.util.V2rayConfigUtil
|
||||
import libv2ray.Libv2ray
|
||||
import libv2ray.V2RayVPNServiceSupportsSet
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.telegram.messenger.FileLog
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.random.Random
|
||||
|
||||
class VmessLoader {
|
||||
|
||||
private val point = Libv2ray.newV2RayPoint(EmptyCallback(), false)
|
||||
|
||||
companion object {
|
||||
|
||||
fun parseVmess1Link(server: String): VmessBean {
|
||||
|
||||
val lnk = ("https://" + server.substringAfter(VMESS1_PROTOCOL)).toHttpUrl()
|
||||
|
||||
val bean = VmessBean()
|
||||
|
||||
bean.configType = V2RayConfig.EConfigType.Vmess
|
||||
bean.address = lnk.host
|
||||
bean.port = lnk.port
|
||||
bean.id = lnk.username
|
||||
bean.remarks = lnk.fragment ?: ""
|
||||
|
||||
lnk.queryParameterNames.forEach {
|
||||
|
||||
when (it) {
|
||||
|
||||
"tls" -> if (lnk.queryParameter(it) == "true") bean.streamSecurity = "tls"
|
||||
|
||||
"network" -> {
|
||||
|
||||
bean.network = lnk.queryParameter(it)!!
|
||||
|
||||
if (bean.network in arrayOf("http", "ws")) {
|
||||
|
||||
bean.path = Utils.urlDecode(lnk.encodedPath)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"header" -> {
|
||||
|
||||
bean.headerType = lnk.queryParameter(it)!!
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bean
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parseVmessLink(server: String): VmessBean {
|
||||
|
||||
try {
|
||||
if (server.isBlank()) error("empty link")
|
||||
|
||||
var vmess = VmessBean()
|
||||
|
||||
if (server.startsWith(VMESS_PROTOCOL)) {
|
||||
|
||||
val indexSplit = server.indexOf("?")
|
||||
if (indexSplit > 0) {
|
||||
vmess = resolveSimpleVmess1(server)
|
||||
} else {
|
||||
|
||||
var result = server.replace(VMESS_PROTOCOL, "")
|
||||
result = Base64.decodeStr(result)
|
||||
if (result.isBlank()) {
|
||||
error("invalid url format")
|
||||
}
|
||||
|
||||
if (result.contains("= vmess")) {
|
||||
|
||||
vmess = resolveSomeIOSAppShitCsvLink(result)
|
||||
|
||||
} else {
|
||||
|
||||
val vmessQRCode = Gson().fromJson(result, VmessQRCode::class.java)
|
||||
if (vmessQRCode.add.isBlank()
|
||||
|| vmessQRCode.port.isBlank()
|
||||
|| vmessQRCode.id.isBlank()
|
||||
|| vmessQRCode.aid.isBlank()
|
||||
|| vmessQRCode.net.isBlank()
|
||||
) {
|
||||
error("invalid protocol")
|
||||
}
|
||||
|
||||
vmess.configType = V2RayConfig.EConfigType.Vmess
|
||||
vmess.security = "auto"
|
||||
vmess.network = "tcp"
|
||||
vmess.headerType = "none"
|
||||
|
||||
vmess.configVersion = Utils.parseInt(vmessQRCode.v)
|
||||
vmess.remarks = vmessQRCode.ps
|
||||
vmess.address = vmessQRCode.add
|
||||
vmess.port = Utils.parseInt(vmessQRCode.port)
|
||||
vmess.id = vmessQRCode.id
|
||||
vmess.alterId = Utils.parseInt(vmessQRCode.aid)
|
||||
vmess.network = vmessQRCode.net
|
||||
vmess.headerType = vmessQRCode.type
|
||||
vmess.requestHost = vmessQRCode.host
|
||||
vmess.path = vmessQRCode.path
|
||||
vmess.streamSecurity = vmessQRCode.tls
|
||||
}
|
||||
}
|
||||
|
||||
upgradeServerVersion(vmess)
|
||||
|
||||
return vmess
|
||||
} else if (server.startsWith(VMESS1_PROTOCOL)) {
|
||||
|
||||
return parseVmess1Link(server)
|
||||
|
||||
} else if (server.startsWith(TROJAN_PROTOCOL)) {
|
||||
|
||||
vmess.configType = V2RayConfig.EConfigType.Trojan
|
||||
|
||||
val link = server.replace(TROJAN_PROTOCOL, "https://").toHttpUrlOrNull()
|
||||
?: error("invalid trojan link $server")
|
||||
|
||||
vmess.address = link.host
|
||||
vmess.port = link.port
|
||||
vmess.id = link.username
|
||||
|
||||
if (link.password.isNotBlank()) {
|
||||
|
||||
// https://github.com/trojan-gfw/igniter/issues/318
|
||||
|
||||
vmess.id += ":" + link.password
|
||||
|
||||
}
|
||||
|
||||
vmess.requestHost = link.queryParameter("sni") ?: vmess.requestHost
|
||||
vmess.remarks = link.fragment ?: ""
|
||||
|
||||
return vmess
|
||||
|
||||
} else if (server.startsWith(SOCKS_PROTOCOL)) {
|
||||
var result = server.replace(SOCKS_PROTOCOL, "")
|
||||
val indexSplit = result.indexOf("#")
|
||||
if (indexSplit > 0) {
|
||||
try {
|
||||
vmess.remarks = Utils.urlDecode(result.substring(indexSplit + 1, result.length))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
result = result.substring(0, indexSplit)
|
||||
}
|
||||
|
||||
//part decode
|
||||
val indexS = result.indexOf(":")
|
||||
if (indexS < 0) {
|
||||
result = Base64.decodeStr(result)
|
||||
}
|
||||
|
||||
val legacyPattern = "^(.+?):(\\d+?)$".toRegex()
|
||||
val match = legacyPattern.matchEntire(result) ?: error("invalid protocol")
|
||||
vmess.address = match.groupValues[1]
|
||||
if (vmess.address.firstOrNull() == '[' && vmess.address.lastOrNull() == ']')
|
||||
vmess.address = vmess.address.substring(1, vmess.address.length - 1)
|
||||
vmess.port = match.groupValues[2].toInt()
|
||||
|
||||
return vmess
|
||||
} else {
|
||||
error("invalid protocol")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
||||
throw IllegalArgumentException(e)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun resolveSomeIOSAppShitCsvLink(csv: String): VmessBean {
|
||||
|
||||
val args = csv.split(",")
|
||||
|
||||
val bean = VmessBean()
|
||||
|
||||
bean.configType = V2RayConfig.EConfigType.Vmess
|
||||
bean.address = args[1]
|
||||
bean.port = args[2].toInt()
|
||||
bean.security = args[3]
|
||||
bean.id = args[4].replace("\"", "")
|
||||
|
||||
args.subList(5, args.size).forEach {
|
||||
|
||||
when {
|
||||
|
||||
it == "over-tls=true" -> {
|
||||
|
||||
bean.streamSecurity = "tls"
|
||||
|
||||
}
|
||||
|
||||
it.startsWith("tls-host=") -> {
|
||||
|
||||
bean.requestHost = it.substringAfter("=")
|
||||
|
||||
}
|
||||
|
||||
it.startsWith("obfs=") -> {
|
||||
|
||||
bean.network = it.substringAfter("=")
|
||||
|
||||
}
|
||||
|
||||
it.startsWith("obfs-path=") || it.contains("Host:") -> {
|
||||
|
||||
runCatching {
|
||||
|
||||
bean.path = it
|
||||
.substringAfter("obfs-path=\"")
|
||||
.substringBefore("\"obfs")
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
bean.requestHost = it
|
||||
.substringAfter("Host:")
|
||||
.substringBefore("[")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bean
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* upgrade
|
||||
*/
|
||||
private fun upgradeServerVersion(vmess: VmessBean): Int {
|
||||
try {
|
||||
if (vmess.configVersion == 2) {
|
||||
return 0
|
||||
}
|
||||
|
||||
when (vmess.network) {
|
||||
"kcp" -> {
|
||||
}
|
||||
"ws" -> {
|
||||
var path = ""
|
||||
var host = ""
|
||||
val lstParameter = vmess.requestHost.split(";")
|
||||
if (lstParameter.size > 0) {
|
||||
path = lstParameter.get(0).trim()
|
||||
}
|
||||
if (lstParameter.size > 1) {
|
||||
path = lstParameter.get(0).trim()
|
||||
host = lstParameter.get(1).trim()
|
||||
}
|
||||
vmess.path = path
|
||||
vmess.requestHost = host
|
||||
}
|
||||
"h2" -> {
|
||||
var path = ""
|
||||
var host = ""
|
||||
val lstParameter = vmess.requestHost.split(";")
|
||||
if (lstParameter.isNotEmpty()) {
|
||||
path = lstParameter[0].trim()
|
||||
}
|
||||
if (lstParameter.size > 1) {
|
||||
path = lstParameter[0].trim()
|
||||
host = lstParameter[1].trim()
|
||||
}
|
||||
vmess.path = path
|
||||
vmess.requestHost = host
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
vmess.configVersion = 2
|
||||
return 0
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveSimpleVmess1(server: String): VmessBean {
|
||||
|
||||
val vmess = VmessBean()
|
||||
|
||||
var result = server.replace(VMESS_PROTOCOL, "")
|
||||
val indexSplit = result.indexOf("?")
|
||||
if (indexSplit > 0) {
|
||||
result = result.substring(0, indexSplit)
|
||||
}
|
||||
result = Base64.decodeStr(result)
|
||||
|
||||
val arr1 = result.split('@')
|
||||
if (arr1.count() != 2) {
|
||||
return vmess
|
||||
}
|
||||
val arr21 = arr1[0].split(':')
|
||||
val arr22 = arr1[1].split(':')
|
||||
if (arr21.count() != 2 || arr21.count() != 2) {
|
||||
return vmess
|
||||
}
|
||||
|
||||
vmess.address = arr22[0]
|
||||
vmess.port = Utils.parseInt(arr22[1])
|
||||
vmess.security = arr21[0]
|
||||
vmess.id = arr21[1]
|
||||
|
||||
vmess.security = "chacha20-poly1305"
|
||||
vmess.network = "tcp"
|
||||
vmess.headerType = "none"
|
||||
vmess.remarks = ""
|
||||
vmess.alterId = 0
|
||||
|
||||
return vmess
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lateinit var bean: VmessBean
|
||||
|
||||
fun initConfig(config: VmessBean) {
|
||||
|
||||
this.bean = config
|
||||
|
||||
}
|
||||
|
||||
fun start(): Int {
|
||||
|
||||
var retry = 3
|
||||
|
||||
do {
|
||||
|
||||
try {
|
||||
|
||||
val port = Random.nextInt(4096, 32768)
|
||||
|
||||
val conf = V2rayConfigUtil.getV2rayConfig(bean, port).content
|
||||
|
||||
FileLog.d(conf)
|
||||
|
||||
runCatching {
|
||||
|
||||
Libv2ray.testConfig(conf)
|
||||
|
||||
}.onFailure {
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
return -1
|
||||
|
||||
}
|
||||
|
||||
point.configureFileContent = conf
|
||||
point.domainName = V2rayConfigUtil.currDomain
|
||||
|
||||
point.runLoop(true)
|
||||
|
||||
return port
|
||||
|
||||
} catch (e: Throwable) {
|
||||
|
||||
retry--
|
||||
|
||||
if (retry <= 0) {
|
||||
|
||||
FileLog.e(e)
|
||||
|
||||
return -1
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while (true)
|
||||
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
|
||||
thread {
|
||||
|
||||
runCatching {
|
||||
|
||||
point.stopLoop()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class EmptyCallback : V2RayVPNServiceSupportsSet {
|
||||
override fun onEmitStatus(p0: Long, p1: String?): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun setup(p0: String?): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun prepare(): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun shutdown(): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun protect(p0: Long): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,505 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.v2ray.ang.V2RayConfig;
|
||||
import com.v2ray.ang.dto.AngConfig;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.ui.PopupBuilder;
|
||||
|
||||
public class VmessSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
|
||||
private EditTextBoldCursor ipField;
|
||||
private EditTextBoldCursor portField;
|
||||
private EditTextBoldCursor userIdField;
|
||||
private EditTextBoldCursor alterIdField;
|
||||
private TextSettingsCell securityField;
|
||||
private TextSettingsCell networkField;
|
||||
private TextSettingsCell headTypeField;
|
||||
private EditTextBoldCursor requestHostField;
|
||||
private EditTextBoldCursor pathField;
|
||||
private TextCheckCell useTlsField;
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private TextInfoPrivacyCell bottomCell;
|
||||
private ActionBarMenuItem doneItem;
|
||||
|
||||
private SharedConfig.VmessProxy currentProxyInfo;
|
||||
private AngConfig.VmessBean currentBean;
|
||||
|
||||
private boolean ignoreOnTextChange;
|
||||
|
||||
private static final int done_button = 1;
|
||||
|
||||
private static String[] securitySet = { "chacha20-poly1305","aes-128-gcm","auto","none","zero" };
|
||||
private static String[] networkSet = { "tcp","kcp","ws","h2","quic" };
|
||||
private static String[] headTypeSet = { "none","http","srtp","utp","wechat-video","dtls","wireguard" };
|
||||
|
||||
public class TypeCell extends FrameLayout {
|
||||
|
||||
private TextView textView;
|
||||
private ImageView checkImage;
|
||||
private boolean needDivider;
|
||||
|
||||
public TypeCell(Context context) {
|
||||
super(context);
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setValue(String name, boolean checked, boolean divider) {
|
||||
textView.setText(name);
|
||||
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
}
|
||||
|
||||
public void setTypeChecked(boolean value) {
|
||||
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VmessSettingsActivity() {
|
||||
super();
|
||||
currentBean = new AngConfig.VmessBean();
|
||||
currentBean.setConfigType(V2RayConfig.EConfigType.Vmess);
|
||||
}
|
||||
|
||||
public VmessSettingsActivity(SharedConfig.VmessProxy proxyInfo) {
|
||||
super();
|
||||
currentProxyInfo = proxyInfo;
|
||||
currentBean = proxyInfo.bean;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(ipField.getText())) {
|
||||
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(portField.getText())) {
|
||||
|
||||
portField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(portField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(userIdField.getText())) {
|
||||
|
||||
userIdField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(userIdField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(alterIdField.getText())) {
|
||||
|
||||
alterIdField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(alterIdField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
currentBean.setAddress(ipField.getText().toString());
|
||||
currentBean.setPort(Utilities.parseInt(portField.getText().toString()));
|
||||
currentBean.setId(userIdField.getText().toString());
|
||||
currentBean.setAlterId(Utilities.parseInt(alterIdField.getText().toString()));
|
||||
currentBean.setSecurity(securityField.getValueTextView().getText().toString());
|
||||
currentBean.setNetwork(networkField.getValueTextView().getText().toString());
|
||||
currentBean.setHeaderType(headTypeField.getValueTextView().getText().toString());
|
||||
currentBean.setRequestHost(requestHostField.getText().toString());
|
||||
currentBean.setPath(pathField.getText().toString());
|
||||
currentBean.setStreamSecurity(useTlsField.isChecked() ? "tls" : "");
|
||||
currentBean.setRemarks(remarksField.getText().toString());
|
||||
|
||||
if (currentProxyInfo == null) {
|
||||
currentProxyInfo = new SharedConfig.VmessProxy(currentBean);
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
} else {
|
||||
currentProxyInfo.proxyCheckPingId = 0;
|
||||
currentProxyInfo.availableCheckTime = 0;
|
||||
currentProxyInfo.ping = 0;
|
||||
SharedConfig.saveProxyList();
|
||||
SharedConfig.setProxyEnable(false);
|
||||
}
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[7];
|
||||
|
||||
for (int a = 0; a < 7; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
EditTextBoldCursor cursor = mkCursor();
|
||||
inputFields[a] = cursor;
|
||||
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
switch (a) {
|
||||
case 0:
|
||||
ipField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
|
||||
cursor.setText(currentBean.getAddress());
|
||||
break;
|
||||
case 1:
|
||||
portField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyPort", R.string.UseProxyPort));
|
||||
cursor.setText("" + currentBean.getPort());
|
||||
break;
|
||||
case 2:
|
||||
userIdField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("VmessUserId", R.string.VmessUserId));
|
||||
cursor.setText(currentBean.getId());
|
||||
break;
|
||||
case 3:
|
||||
alterIdField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
cursor.setHintText(LocaleController.getString("VmessAlterId", R.string.VmessAlterId));
|
||||
cursor.setText("" + currentBean.getAlterId());
|
||||
break;
|
||||
case 4:
|
||||
requestHostField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("VmessRequestHost", R.string.VmessRequestHost));
|
||||
cursor.setText(currentBean.getRequestHost());
|
||||
break;
|
||||
case 5:
|
||||
pathField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("VmessPath", R.string.VmessPath));
|
||||
cursor.setText(currentBean.getPath());
|
||||
break;
|
||||
case 6:
|
||||
remarksField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
cursor.setText(currentBean.getRemarks());
|
||||
break;
|
||||
}
|
||||
cursor.setSelection(cursor.length());
|
||||
|
||||
cursor.setPadding(0, 0, 0, 0);
|
||||
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
|
||||
|
||||
}
|
||||
|
||||
inputFieldsContainer.addView((View) ipField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) portField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) userIdField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) alterIdField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
|
||||
securityField = new TextSettingsCell(context);
|
||||
securityField.setBackground(Theme.getSelectorDrawable(false));
|
||||
securityField.setTextAndValue(LocaleController.getString("VmessSecurity", R.string.VmessSecurity), currentBean.getSecurity(), false);
|
||||
container.addView(securityField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
securityField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(securitySet, (__,value) -> {
|
||||
|
||||
securityField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
container = new FrameLayout(context);
|
||||
networkField = new TextSettingsCell(context);
|
||||
networkField.setBackground(Theme.getSelectorDrawable(false));
|
||||
networkField.setTextAndValue(LocaleController.getString("VmessNetwork", R.string.VmessNetwork), currentBean.getNetwork(), false);
|
||||
container.addView(networkField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
networkField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(networkSet, (__,value) -> {
|
||||
|
||||
networkField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
container = new FrameLayout(context);
|
||||
headTypeField = new TextSettingsCell(context);
|
||||
headTypeField.setBackground(Theme.getSelectorDrawable(false));
|
||||
headTypeField.setTextAndValue(LocaleController.getString("VmessHeadType", R.string.VmessHeadType), currentBean.getHeaderType(), false);
|
||||
container.addView(headTypeField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
headTypeField.setOnClickListener((v) -> {
|
||||
|
||||
PopupBuilder select = new PopupBuilder(v);
|
||||
|
||||
select.setItems(headTypeSet, (__,value) -> {
|
||||
|
||||
headTypeField.getValueTextView().setText(value);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
select.show();
|
||||
|
||||
});
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) requestHostField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) pathField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
container = new FrameLayout(context);
|
||||
useTlsField = new TextCheckCell(context);
|
||||
useTlsField.setBackground(Theme.getSelectorDrawable(false));
|
||||
useTlsField.setTextAndCheck(LocaleController.getString("VmessTls", R.string.VmessTls), !StrUtil.isBlank(currentBean.getStreamSecurity()), false);
|
||||
container.addView(useTlsField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
useTlsField.setOnClickListener((v) -> useTlsField.setChecked(!useTlsField.isChecked()));
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
bottomCell = new TextInfoPrivacyCell(context);
|
||||
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
bottomCell.setText(LocaleController.getString("ProxyInfoVmess", R.string.ProxyInfoVmess));
|
||||
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && !backward && currentProxyInfo == null) {
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,359 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package tw.nekomimi.nekogram.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import tw.nekomimi.nekogram.proxy.tcp2ws.WsLoader;
|
||||
|
||||
public class WsSettingsActivity extends BaseFragment {
|
||||
|
||||
private EditTextBoldCursor[] inputFields;
|
||||
|
||||
private EditTextBoldCursor ipField;
|
||||
private EditTextBoldCursor payloadField;
|
||||
private TextCheckCell useTlsField;
|
||||
private EditTextBoldCursor remarksField;
|
||||
|
||||
private ScrollView scrollView;
|
||||
private LinearLayout linearLayout2;
|
||||
private LinearLayout inputFieldsContainer;
|
||||
|
||||
private TextInfoPrivacyCell bottomCell;
|
||||
private ActionBarMenuItem doneItem;
|
||||
|
||||
private SharedConfig.WsProxy currentProxyInfo;
|
||||
private WsLoader.Bean currentBean;
|
||||
|
||||
private static final int done_button = 1;
|
||||
|
||||
public class TypeCell extends FrameLayout {
|
||||
|
||||
private TextView textView;
|
||||
private ImageView checkImage;
|
||||
private boolean needDivider;
|
||||
|
||||
public TypeCell(Context context) {
|
||||
super(context);
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
|
||||
|
||||
checkImage = new ImageView(context);
|
||||
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
|
||||
checkImage.setImageResource(R.drawable.sticker_added);
|
||||
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setValue(String name, boolean checked, boolean divider) {
|
||||
textView.setText(name);
|
||||
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
}
|
||||
|
||||
public void setTypeChecked(boolean value) {
|
||||
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WsSettingsActivity() {
|
||||
super();
|
||||
currentBean = new WsLoader.Bean();
|
||||
}
|
||||
|
||||
public WsSettingsActivity(SharedConfig.WsProxy proxyInfo) {
|
||||
super();
|
||||
currentProxyInfo = proxyInfo;
|
||||
currentBean = proxyInfo.bean;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setAllowOverlayTitle(false);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == done_button) {
|
||||
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(ipField.getText())) {
|
||||
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(payloadField.getText())) {
|
||||
|
||||
payloadField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(payloadField);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
currentBean.setServer(ipField.getText().toString());
|
||||
currentBean.setPayloadStr(payloadField.getText().toString());
|
||||
currentBean.setTls(useTlsField.isChecked());
|
||||
currentBean.setRemarks(remarksField.getText().toString());
|
||||
|
||||
if (currentProxyInfo == null) {
|
||||
currentProxyInfo = new SharedConfig.WsProxy(currentBean);
|
||||
SharedConfig.addProxy(currentProxyInfo);
|
||||
SharedConfig.setCurrentProxy(currentProxyInfo);
|
||||
} else {
|
||||
currentProxyInfo.proxyCheckPingId = 0;
|
||||
currentProxyInfo.availableCheckTime = 0;
|
||||
currentProxyInfo.ping = 0;
|
||||
SharedConfig.saveProxyList();
|
||||
SharedConfig.setProxyEnable(false);
|
||||
}
|
||||
|
||||
finishFragment();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
|
||||
|
||||
fragmentView = new FrameLayout(context);
|
||||
FrameLayout frameLayout = (FrameLayout) fragmentView;
|
||||
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||
|
||||
scrollView = new ScrollView(context);
|
||||
scrollView.setFillViewport(true);
|
||||
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
|
||||
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
linearLayout2 = new LinearLayout(context);
|
||||
linearLayout2.setOrientation(LinearLayout.VERTICAL);
|
||||
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
inputFieldsContainer = new LinearLayout(context);
|
||||
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// bring to front for transitions
|
||||
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
|
||||
inputFieldsContainer.setOutlineProvider(null);
|
||||
}
|
||||
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
inputFields = new EditTextBoldCursor[5];
|
||||
|
||||
for (int a = 0; a < 5; a++) {
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
EditTextBoldCursor cursor = mkCursor();
|
||||
inputFields[a] = cursor;
|
||||
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
switch (a) {
|
||||
case 0:
|
||||
ipField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
|
||||
cursor.setText(currentBean.getServer());
|
||||
break;
|
||||
case 1:
|
||||
payloadField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("WsPayload", R.string.WsPayload));
|
||||
cursor.setText(currentBean.getPayloadStr());
|
||||
break;
|
||||
case 2:
|
||||
remarksField = cursor;
|
||||
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
|
||||
cursor.setText(currentBean.getRemarks());
|
||||
break;
|
||||
}
|
||||
cursor.setSelection(cursor.length());
|
||||
|
||||
cursor.setPadding(0, 0, 0, 0);
|
||||
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
|
||||
|
||||
}
|
||||
|
||||
inputFieldsContainer.addView((View) ipField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
inputFieldsContainer.addView((View) payloadField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
useTlsField = new TextCheckCell(context);
|
||||
useTlsField.setBackground(Theme.getSelectorDrawable(false));
|
||||
useTlsField.setTextAndCheck(LocaleController.getString("VmessTls", R.string.VmessTls), currentBean.getTls(), false);
|
||||
container.addView(useTlsField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
|
||||
|
||||
useTlsField.setOnClickListener((v) -> useTlsField.setChecked(!useTlsField.isChecked()));
|
||||
|
||||
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
|
||||
|
||||
bottomCell = new TextInfoPrivacyCell(context);
|
||||
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
bottomCell.setText(LocaleController.getString("ProxyInfoWS", R.string.ProxyInfoWS));
|
||||
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
return fragmentView;
|
||||
|
||||
}
|
||||
|
||||
EditTextBoldCursor mkCursor() {
|
||||
|
||||
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
|
||||
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
|
||||
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setBackground(null);
|
||||
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
cursor.setCursorSize(AndroidUtilities.dp(20));
|
||||
cursor.setCursorWidth(1.5f);
|
||||
cursor.setSingleLine(true);
|
||||
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
cursor.setTransformHintToHeader(true);
|
||||
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && !backward && currentProxyInfo == null) {
|
||||
ipField.requestFocus();
|
||||
AndroidUtilities.showKeyboard(ipField);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ThemeDescription> getThemeDescriptions() {
|
||||
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
|
||||
if (inputFields != null) {
|
||||
for (int i = 0; i < inputFields.length; i++) {
|
||||
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
|
||||
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
}
|
||||
};
|
||||
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
|
||||
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
|
||||
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
|
||||
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
|
||||
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
|
||||
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
||||
|
||||
if (inputFields != null) {
|
||||
for (int a = 0; a < inputFields.length; a++) {
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
|
||||
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
|
||||
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
|
||||
}
|
||||
} else {
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
|
||||
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
|
||||
}
|
||||
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
|
||||
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
|
||||
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy.tcp2ws;
|
||||
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Tcp2wsServer extends Thread {
|
||||
|
||||
public final WsLoader.Bean bean;
|
||||
public final int port;
|
||||
|
||||
public Tcp2wsServer(WsLoader.Bean bean, int port) {
|
||||
this.bean = bean;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public static final Map<String, Integer> mapper = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
|
||||
put("149.154.175.5", 1);
|
||||
put("95.161.76.100", 2);
|
||||
put("149.154.175.100", 3);
|
||||
put("149.154.167.91", 4);
|
||||
put("149.154.167.92", 4);
|
||||
put("149.154.171.5", 5);
|
||||
put("2001:b28:f23d:f001:0000:0000:0000:000a", 1);
|
||||
put("2001:67c:4e8:f002:0000:0000:0000:000a", 2);
|
||||
put("2001:b28:f23d:f003:0000:0000:0000:000a", 3);
|
||||
put("2001:67c:4e8:f004:0000:0000:0000:000a", 4);
|
||||
put("2001:b28:f23f:f005:0000:0000:0000:000a", 5);
|
||||
put("149.154.161.144", 2);
|
||||
put("149.154.167.", 2);
|
||||
put("149.154.175.1", 3);
|
||||
put("91.108.4.", 4);
|
||||
put("149.154.164.", 4);
|
||||
put("149.154.165.", 4);
|
||||
put("149.154.166.", 4);
|
||||
put("91.108.56.", 5);
|
||||
put("2001:b28:f23d:f001:0000:0000:0000:000d", 1);
|
||||
put("2001:67c:4e8:f002:0000:0000:0000:000d", 2);
|
||||
put("2001:b28:f23d:f003:0000:0000:0000:000d", 3);
|
||||
put("2001:67c:4e8:f004:0000:0000:0000:000d", 4);
|
||||
put("2001:b28:f23f:f005:0000:0000:0000:000d", 5);
|
||||
put("149.154.175.40", 6);
|
||||
put("149.154.167.40", 7);
|
||||
put("149.154.175.117", 8);
|
||||
put("2001:b28:f23d:f001:0000:0000:0000:000e", 6);
|
||||
put("2001:67c:4e8:f002:0000:0000:0000:000e", 7);
|
||||
put("2001:b28:f23d:f003:0000:0000:0000:000e", 8);
|
||||
}});
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FileLog.d("SOCKS server started...");
|
||||
try {
|
||||
handleClients(port);
|
||||
FileLog.d("SOCKS server stopped...");
|
||||
} catch (Exception e) {
|
||||
FileLog.d("SOCKS server crashed...");
|
||||
FileLog.e(e);
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleClients(int port) throws Exception {
|
||||
final ServerSocket listenSocket = new ServerSocket(port);
|
||||
listenSocket.setSoTimeout(2000);
|
||||
FileLog.d("SOCKS server listening at port: " + listenSocket.getLocalPort());
|
||||
|
||||
while (isAlive() && !isInterrupted()) {
|
||||
try {
|
||||
final Socket clientSocket = listenSocket.accept();
|
||||
FileLog.d("Connection from : " + clientSocket.getRemoteSocketAddress().toString());
|
||||
new WsProxyHandler(clientSocket, bean).start();
|
||||
} catch (InterruptedIOException e) {
|
||||
// This exception is thrown when accept timeout is expired
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
listenSocket.close();
|
||||
} catch (IOException e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy.tcp2ws
|
||||
|
||||
import cn.hutool.core.codec.Base64
|
||||
import cn.hutool.core.util.StrUtil
|
||||
import okhttp3.Dns
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import tw.nekomimi.nekogram.NekoConfig
|
||||
import java.net.InetAddress
|
||||
|
||||
class WsLoader {
|
||||
|
||||
lateinit var server: Tcp2wsServer
|
||||
|
||||
fun init(bean: Bean, port: Int) {
|
||||
server = Tcp2wsServer(bean, port)
|
||||
}
|
||||
|
||||
fun start() {
|
||||
server.start()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
if (::server.isInitialized) {
|
||||
server.interrupt()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun parse(url: String): Bean {
|
||||
val lnk = url.replace("ws://", "http://")
|
||||
.replace("wss://", "https://")
|
||||
.toHttpUrlOrNull() ?: error("Invalid link")
|
||||
val payloadStr = lnk.queryParameter("payload") ?: error("Missing payload")
|
||||
val payload = Base64.decodeStr(payloadStr).split(",")
|
||||
if (payload.size < 5) error("Invalid payload")
|
||||
return Bean(
|
||||
lnk.host,
|
||||
payload,
|
||||
lnk.isHttps,
|
||||
lnk.fragment ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class Bean(
|
||||
var server: String = "",
|
||||
var payload: List<String> = arrayListOf(),
|
||||
var tls: Boolean = true,
|
||||
var remarks: String = ""
|
||||
) {
|
||||
|
||||
var payloadStr: String
|
||||
get() = Base64.encodeUrlSafe(payload.joinToString(","))
|
||||
set(value) {
|
||||
payload = Base64.decodeStr(value).split(",")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = HttpUrl.Builder()
|
||||
.scheme("http")
|
||||
.host(server)
|
||||
.addQueryParameter("payload", payloadStr);
|
||||
if (remarks.isNotBlank()) {
|
||||
builder.fragment(remarks)
|
||||
}
|
||||
return builder.build().toString().replace("http://", if (tls) "wss://" else "ws://")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
package tw.nekomimi.nekogram.proxy.tcp2ws;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import com.neovisionaries.ws.client.ThreadType;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFactory;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
import com.neovisionaries.ws.client.WebSocketListener;
|
||||
import com.neovisionaries.ws.client.WebSocketState;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.checkerframework.common.value.qual.IntVal;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import cn.hutool.http.ssl.AndroidSupportSSLFactory;
|
||||
import cn.hutool.http.ssl.CustomProtocolsSSLFactory;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.utils.DnsFactory;
|
||||
|
||||
public class WsProxyHandler extends Thread {
|
||||
|
||||
private InputStream clientInputStream = null;
|
||||
private OutputStream clientOutputStream = null;
|
||||
|
||||
private final WsLoader.Bean bean;
|
||||
private Socket clientSocket;
|
||||
private WebSocket webSocket = null;
|
||||
private final byte[] buffer = new byte[4096];
|
||||
|
||||
private String wsHost = "";
|
||||
|
||||
private final AtomicInteger wsStatus = new AtomicInteger(0);
|
||||
private final static int STATUS_OPENED = 1;
|
||||
private final static int STATUS_CLOSED = 2;
|
||||
private final static int STATUS_FAILED = 3;
|
||||
|
||||
private final CountDownLatch connecting = new CountDownLatch(1);
|
||||
|
||||
public WsProxyHandler(Socket clientSocket, WsLoader.Bean bean) {
|
||||
this.bean = bean;
|
||||
this.clientSocket = clientSocket;
|
||||
FileLog.d("ProxyHandler Created.");
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
@Override
|
||||
public void run() {
|
||||
FileLog.d("Proxy to " + wsHost + "Started.");
|
||||
try {
|
||||
clientInputStream = clientSocket.getInputStream();
|
||||
clientOutputStream = clientSocket.getOutputStream();
|
||||
// Handle Socks5 HandShake
|
||||
socks5Handshake();
|
||||
FileLog.d("socks5 handshake and websocket connection done");
|
||||
// Start read from client socket and send to websocket
|
||||
this.clientSocket.setSoTimeout(1000);
|
||||
while (clientSocket != null && webSocket != null && wsStatus.get() == STATUS_OPENED && !clientSocket.isClosed() && !clientSocket.isInputShutdown()) {
|
||||
int readLen = 0;
|
||||
try {
|
||||
readLen = this.clientInputStream.read(buffer);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
if (wsStatus.get() != STATUS_OPENED)
|
||||
throw new Exception(String.format("[%s] timeout and ws closed", wsHost));
|
||||
continue;
|
||||
}
|
||||
FileLog.d(String.format("[%s] read %d from local", wsHost, readLen));
|
||||
if (readLen == -1) throw new Exception(String.format("[%s] socks closed", wsHost));
|
||||
;
|
||||
if (wsStatus.get() != STATUS_OPENED)
|
||||
throw new Exception(String.format("[%s] ws closed when trying to write", wsHost));
|
||||
;
|
||||
this.webSocket.sendBinary(Arrays.copyOf(buffer, readLen));
|
||||
}
|
||||
} catch (SocketException se) {
|
||||
if ("Socket closed".equals(se.getMessage())) {
|
||||
FileLog.d("socket closed from ws when reading from client");
|
||||
close();
|
||||
} else {
|
||||
FileLog.e(se);
|
||||
close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (wsStatus.get() == STATUS_CLOSED)
|
||||
return;
|
||||
wsStatus.set(STATUS_CLOSED);
|
||||
FileLog.d("ws handler closed");
|
||||
|
||||
try {
|
||||
if (clientSocket != null)
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
if (webSocket != null) {
|
||||
webSocket.sendClose();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
clientSocket = null;
|
||||
webSocket = null;
|
||||
}
|
||||
|
||||
private void connectToServer(String wsHost) throws Exception {
|
||||
this.wsHost = wsHost;
|
||||
WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
|
||||
webSocket = factory.createSocket((bean.getTls() ? "wss://" : "ws://") + wsHost + "/api");
|
||||
webSocket.addListener(new WebSocketAdapter() {
|
||||
@Override
|
||||
public void onBinaryMessage(WebSocket websocket, byte[] binary) throws Exception {
|
||||
WsProxyHandler.this.clientOutputStream.write(binary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
|
||||
FileLog.e(cause);
|
||||
wsStatus.set(STATUS_FAILED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectError(WebSocket websocket, WebSocketException exception) throws Exception {
|
||||
FileLog.d(String.format("[%s] WS connect failed: %s", wsHost, exception.toString()));
|
||||
wsStatus.set(STATUS_FAILED);
|
||||
connecting.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
|
||||
FileLog.d(String.format("[%s] WS connected", wsHost));
|
||||
wsStatus.set(STATUS_OPENED);
|
||||
connecting.countDown();
|
||||
}
|
||||
});
|
||||
webSocket.addProtocol("binary");
|
||||
webSocket.connect();
|
||||
}
|
||||
|
||||
private static final byte[] RESP_AUTH = new byte[]{0x05, 0x00};
|
||||
private static final byte[] RESP_SUCCESS = new byte[]{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
private static final byte[] RESP_FAILED = new byte[]{0x05, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
private void socks5Handshake() throws Exception {
|
||||
byte socksVersion = readOneByteFromClient();
|
||||
|
||||
if (socksVersion != 0x05) {
|
||||
throw new Exception("Invalid socks version:" + socksVersion);
|
||||
}
|
||||
FileLog.d("Accepted socks5 requests.");
|
||||
|
||||
byte authMethodsLen = readOneByteFromClient();
|
||||
boolean isNoAuthSupport = false;
|
||||
for (int i = 0; i < authMethodsLen; i++) {
|
||||
byte authMethod = readOneByteFromClient();
|
||||
if (authMethod == 0x00)
|
||||
isNoAuthSupport = true;
|
||||
}
|
||||
if (!isNoAuthSupport) throw new Exception("NO_AUTH is not supported from client.");
|
||||
|
||||
this.clientOutputStream.write(RESP_AUTH);
|
||||
this.clientOutputStream.flush();
|
||||
|
||||
byte[] cmds = readBytesExactly(4);
|
||||
// cmds[0] -> VER
|
||||
// cmds[1] -> CMD
|
||||
// cmds[2] -> RSV
|
||||
// cmds[3] -> ADDR_TYPE
|
||||
if (cmds[0] != 0x05 || cmds[1] != 0x01 || cmds[2] != 0x00)
|
||||
throw new Exception("invalid socks5 cmds " + Arrays.toString(cmds));
|
||||
int addrType = cmds[3];
|
||||
String address;
|
||||
if (addrType == 0x01) { // ipv4
|
||||
address = InetAddress.getByAddress(readBytesExactly(4)).getHostAddress();
|
||||
} else if (addrType == 0x04) { // ipv6
|
||||
address = Inet6Address.getByAddress(readBytesExactly(16)).getHostAddress();
|
||||
} else { // not supported: domain
|
||||
throw new Exception("invalid addr type: " + addrType);
|
||||
}
|
||||
readBytesExactly(2); // read out port
|
||||
|
||||
String wsHost = getWsHost(address);
|
||||
connectToServer(wsHost);
|
||||
|
||||
connecting.await();
|
||||
|
||||
if (wsStatus.get() == STATUS_OPENED) {
|
||||
this.clientOutputStream.write(RESP_SUCCESS);
|
||||
this.clientOutputStream.flush();
|
||||
} else {
|
||||
this.clientOutputStream.write(RESP_FAILED);
|
||||
this.clientOutputStream.flush();
|
||||
throw new Exception("websocket connect failed");
|
||||
}
|
||||
// just set status byte and ignore bnd.addr and bnd.port in RFC1928, since Telegram Android ignores it:
|
||||
// proxyAuthState == 6 in tgnet/ConnectionSocket.cpp
|
||||
}
|
||||
|
||||
private String getWsHost(String address) throws Exception {
|
||||
Integer dcNumber = Tcp2wsServer.mapper.get(address);
|
||||
for (int i = 1; dcNumber == null && i < 4; i++) {
|
||||
dcNumber = Tcp2wsServer.mapper.get(address.substring(0, address.length() - i));
|
||||
}
|
||||
if (dcNumber == null)
|
||||
throw new Exception("no matched dc: " + address);
|
||||
if (dcNumber >= bean.getPayload().size())
|
||||
throw new Exception("invalid dc number & payload: " + dcNumber);
|
||||
String serverPrefix = bean.getPayload().get(dcNumber - 1);
|
||||
String wsHost = serverPrefix + "." + this.bean.getServer();
|
||||
FileLog.d("socks5 dest address: " + address + ", target ws host " + wsHost);
|
||||
return wsHost;
|
||||
}
|
||||
|
||||
private byte readOneByteFromClient() throws Exception {
|
||||
return (byte) clientInputStream.read();
|
||||
}
|
||||
|
||||
private byte[] readBytesExactly(int len) throws Exception {
|
||||
byte[] ret = new byte[len];
|
||||
int alreadyRead = 0;
|
||||
while (alreadyRead < len) {
|
||||
int read = this.clientInputStream.read(ret, alreadyRead, len - alreadyRead);
|
||||
alreadyRead += read;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,690 +0,0 @@
|
|||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.util.Base64
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.setPadding
|
||||
import com.github.shadowsocks.plugin.PluginOptions
|
||||
import com.google.zxing.*
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer
|
||||
import com.google.zxing.qrcode.QRCodeReader
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.v2ray.ang.V2RayConfig
|
||||
import com.v2ray.ang.V2RayConfig.SSR_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.TROJAN_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS1_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.WSS_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.WS_PROTOCOL
|
||||
import com.v2ray.ang.dto.AngConfig
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.telegram.messenger.*
|
||||
import org.telegram.messenger.browser.Browser
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder
|
||||
import tw.nekomimi.nekogram.proxy.ShadowsocksLoader
|
||||
import tw.nekomimi.nekogram.proxy.ShadowsocksRLoader
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil.showToast
|
||||
import java.io.File
|
||||
import java.net.NetworkInterface
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
|
||||
object ProxyUtil {
|
||||
|
||||
@JvmStatic
|
||||
fun isVPNEnabled(): Boolean {
|
||||
|
||||
val networkList = mutableListOf<String>()
|
||||
|
||||
runCatching {
|
||||
|
||||
Collections.list(NetworkInterface.getNetworkInterfaces()).forEach {
|
||||
|
||||
if (it.isUp) networkList.add(it.name)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return networkList.contains("tun0")
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun parseProxies(text: String, tryDecode: Boolean = true): MutableList<String> {
|
||||
|
||||
if (tryDecode && !text.contains("proxies:")) {
|
||||
try {
|
||||
return parseProxies(String(Base64.decode(text, Base64.NO_PADDING)), false)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
val proxies = mutableListOf<String>()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
// sip008
|
||||
val ssArray = JSONArray(text)
|
||||
for (index in 0 until ssArray.length()) {
|
||||
proxies.add(ShadowsocksLoader.Bean.parseJson(ssArray.getJSONObject(index)).toString())
|
||||
}
|
||||
return proxies
|
||||
} catch (ignored: JSONException) {
|
||||
}
|
||||
|
||||
if (text.contains("proxies:")) {
|
||||
|
||||
if (BuildVars.isMini) {
|
||||
error(LocaleController.getString("MiniVersionAlert", R.string.MiniVersionAlert))
|
||||
}
|
||||
|
||||
// clash
|
||||
|
||||
for (proxy in (Yaml().loadAs(text, Map::class.java)["proxies"] as List<Map<String, Any?>>)) {
|
||||
val type = proxy["type"] as String
|
||||
when (type) {
|
||||
"ss" -> {
|
||||
var pluginStr = ""
|
||||
if (proxy.contains("plugin")) {
|
||||
val opts = PluginOptions()
|
||||
opts.id = proxy["plugin"] as String
|
||||
opts.putAll(proxy["plugin-opts"] as Map<String, String?>)
|
||||
pluginStr = opts.toString(false)
|
||||
}
|
||||
proxies.add(
|
||||
ShadowsocksLoader.Bean(
|
||||
proxy["server"] as String,
|
||||
proxy["port"] as Int,
|
||||
proxy["password"] as String,
|
||||
proxy["cipher"] as String,
|
||||
pluginStr,
|
||||
proxy["name"] as String
|
||||
).toString())
|
||||
}
|
||||
"vmess" -> {
|
||||
val opts = AngConfig.VmessBean()
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.address = opt.value as String
|
||||
"port" -> opts.port = opt.value.toString().toInt()
|
||||
"uuid" -> opts.id = opt.value as String
|
||||
"alterId" -> opts.alterId = opt.value.toString().toInt()
|
||||
"cipher" -> opts.security = opt.value as String
|
||||
"network" -> opts.network = opt.value as String
|
||||
"tls" -> opts.streamSecurity = if (opt.value?.toString() == "true") "tls" else opts.streamSecurity
|
||||
"ws-path" -> opts.path = opt.value as String
|
||||
"servername" -> opts.requestHost = opt.value as String
|
||||
"h2-opts" -> for (h2Opt in (opt.value as Map<String, Any>)) {
|
||||
when (h2Opt.key) {
|
||||
"host" -> opts.requestHost = (h2Opt.value as List<String>).first()
|
||||
"path" -> opts.path = h2Opt.value as String
|
||||
}
|
||||
}
|
||||
"http-opts" -> for (httpOpt in (opt.value as Map<String, Any>)) {
|
||||
when (httpOpt.key) {
|
||||
"path" -> opts.path = (httpOpt.value as List<String>).first()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
"trojan" -> {
|
||||
val opts = AngConfig.VmessBean()
|
||||
opts.configType = V2RayConfig.EConfigType.Trojan
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.address = opt.value as String
|
||||
"port" -> opts.port = opt.value.toString().toInt()
|
||||
"password" -> opts.id = opt.value as String
|
||||
"sni" -> opts.requestHost = opt.value as String
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
"ssr" -> {
|
||||
val opts = ShadowsocksRLoader.Bean()
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.host = opt.value as String
|
||||
"port" -> opts.remotePort = opt.value.toString().toInt()
|
||||
"cipher" -> opts.method = opt.value as String
|
||||
"password" -> opts.password = opt.value as String
|
||||
"obfs" -> opts.obfs = opt.value as String
|
||||
"protocol" -> opts.protocol = opt.value as String
|
||||
"obfs-param" -> opts.obfs_param = opt.value as String
|
||||
"protocol-param" -> opts.protocol_param = opt.value as String
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
return proxies
|
||||
}
|
||||
}
|
||||
|
||||
text.split('\n').map { it.split(" ") }.forEach {
|
||||
|
||||
it.forEach { line ->
|
||||
|
||||
if (line.startsWith("tg://proxy") ||
|
||||
line.startsWith("tg://socks") ||
|
||||
line.startsWith("https://t.me/proxy") ||
|
||||
line.startsWith("https://t.me/socks") ||
|
||||
line.startsWith(VMESS_PROTOCOL) ||
|
||||
line.startsWith(VMESS1_PROTOCOL) ||
|
||||
line.startsWith(SS_PROTOCOL) ||
|
||||
line.startsWith(SSR_PROTOCOL) ||
|
||||
line.startsWith(WS_PROTOCOL) ||
|
||||
line.startsWith(WSS_PROTOCOL) ||
|
||||
line.startsWith(TROJAN_PROTOCOL) /*||
|
||||
line.startsWith(RB_PROTOCOL)*/) {
|
||||
|
||||
runCatching { proxies.add(SharedConfig.parseProxyInfo(line).toUrl()) }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (proxies.isEmpty()) error("no proxy link found")
|
||||
|
||||
return proxies
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun importFromClipboard(ctx: Activity) {
|
||||
|
||||
var text = (ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).primaryClip?.getItemAt(0)?.text?.toString()
|
||||
|
||||
val proxies = mutableListOf<SharedConfig.ProxyInfo>()
|
||||
|
||||
var error = false
|
||||
|
||||
text?.trim()?.split('\n')?.map { it.split(" ") }?.forEach {
|
||||
|
||||
it.forEach { line ->
|
||||
|
||||
if (line.startsWith("tg://proxy") ||
|
||||
line.startsWith("tg://socks") ||
|
||||
line.startsWith("https://t.me/proxy") ||
|
||||
line.startsWith("https://t.me/socks") ||
|
||||
line.startsWith(VMESS_PROTOCOL) ||
|
||||
line.startsWith(VMESS1_PROTOCOL) ||
|
||||
line.startsWith(SS_PROTOCOL) ||
|
||||
line.startsWith(SSR_PROTOCOL) ||
|
||||
line.startsWith(WS_PROTOCOL) ||
|
||||
line.startsWith(WSS_PROTOCOL) ||
|
||||
line.startsWith(TROJAN_PROTOCOL) /*||
|
||||
line.startsWith(RB_PROTOCOL)*/) {
|
||||
|
||||
runCatching { proxies.add(SharedConfig.parseProxyInfo(line)) }.onFailure {
|
||||
|
||||
error = true
|
||||
|
||||
showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
if (proxies.isNullOrEmpty() && !error) {
|
||||
|
||||
String(Base64.decode(text, Base64.NO_PADDING)).trim().split('\n').map { it.split(" ") }.forEach { str ->
|
||||
|
||||
str.forEach { line ->
|
||||
|
||||
if (line.startsWith("tg://proxy") ||
|
||||
line.startsWith("tg://socks") ||
|
||||
line.startsWith("https://t.me/proxy") ||
|
||||
line.startsWith("https://t.me/socks") ||
|
||||
line.startsWith(VMESS_PROTOCOL) ||
|
||||
line.startsWith(VMESS1_PROTOCOL) ||
|
||||
line.startsWith(SS_PROTOCOL) ||
|
||||
line.startsWith(SSR_PROTOCOL) ||
|
||||
line.startsWith(WS_PROTOCOL) ||
|
||||
line.startsWith(WSS_PROTOCOL) ||
|
||||
line.startsWith(TROJAN_PROTOCOL) /*||
|
||||
|
||||
line.startsWith(RB_PROTOCOL)*/) {
|
||||
|
||||
runCatching { proxies.add(SharedConfig.parseProxyInfo(line)) }.onFailure {
|
||||
|
||||
error = true
|
||||
|
||||
showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (proxies.isNullOrEmpty()) {
|
||||
|
||||
if (!error) showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink))
|
||||
|
||||
return
|
||||
|
||||
} else if (!error) {
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("ImportedProxies", R.string.ImportedProxies) + "\n\n" + proxies.joinToString("\n") { it.title })
|
||||
|
||||
}
|
||||
|
||||
proxies.forEach {
|
||||
|
||||
SharedConfig.addProxy(it)
|
||||
|
||||
}
|
||||
|
||||
UIUtil.runOnUIThread {
|
||||
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun importProxy(ctx: Context, link: String): Boolean {
|
||||
|
||||
runCatching {
|
||||
|
||||
if (link.startsWith(VMESS_PROTOCOL) || link.startsWith(VMESS1_PROTOCOL)) {
|
||||
|
||||
AndroidUtilities.showVmessAlert(ctx, SharedConfig.VmessProxy(link))
|
||||
|
||||
} else if (link.startsWith(TROJAN_PROTOCOL)) {
|
||||
|
||||
AndroidUtilities.showTrojanAlert(ctx, SharedConfig.VmessProxy(link))
|
||||
|
||||
} else if (link.startsWith(SS_PROTOCOL)) {
|
||||
|
||||
AndroidUtilities.showShadowsocksAlert(ctx, SharedConfig.ShadowsocksProxy(link))
|
||||
|
||||
} else if (link.startsWith(SSR_PROTOCOL)) {
|
||||
|
||||
AndroidUtilities.showShadowsocksRAlert(ctx, SharedConfig.ShadowsocksRProxy(link))
|
||||
|
||||
} else if (link.startsWith(WS_PROTOCOL) || link.startsWith(WSS_PROTOCOL)) {
|
||||
|
||||
AndroidUtilities.showWsAlert(ctx, SharedConfig.WsProxy(link))
|
||||
|
||||
} else {
|
||||
|
||||
val url = link.replace("tg://", "https://t.me/").toHttpUrlOrNull()!!
|
||||
|
||||
AndroidUtilities.showProxyAlert(ctx,
|
||||
url.queryParameter("server") ?: return false,
|
||||
url.queryParameter("port") ?: return false,
|
||||
url.queryParameter("user"),
|
||||
url.queryParameter("pass"),
|
||||
url.queryParameter("secret"),
|
||||
url.fragment)
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}.onFailure {
|
||||
|
||||
FileLog.e(it)
|
||||
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, it)
|
||||
|
||||
} else {
|
||||
|
||||
showToast("${LocaleController.getString("BrokenLink", R.string.BrokenLink)}: ${it.message}")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun importInBackground(link: String): SharedConfig.ProxyInfo {
|
||||
|
||||
val info = runCatching {
|
||||
|
||||
if (link.startsWith(VMESS_PROTOCOL) || link.startsWith(VMESS1_PROTOCOL)) {
|
||||
|
||||
SharedConfig.VmessProxy(link)
|
||||
|
||||
} else if (link.startsWith(SS_PROTOCOL)) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
||||
error(LocaleController.getString("MinApi21Required", R.string.MinApi21Required))
|
||||
|
||||
}
|
||||
|
||||
SharedConfig.ShadowsocksProxy(link)
|
||||
|
||||
} else if (link.startsWith(SSR_PROTOCOL)) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
||||
error(LocaleController.getString("MinApi21Required", R.string.MinApi21Required))
|
||||
|
||||
}
|
||||
|
||||
SharedConfig.ShadowsocksRProxy(link)
|
||||
|
||||
} else if (link.startsWith(WS_PROTOCOL) || link.startsWith(WSS_PROTOCOL)) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
||||
error(LocaleController.getString("MinApi21Required", R.string.MinApi21Required))
|
||||
|
||||
}
|
||||
|
||||
SharedConfig.WsProxy(link)
|
||||
|
||||
} else {
|
||||
|
||||
SharedConfig.ProxyInfo.fromUrl(link)
|
||||
|
||||
}
|
||||
|
||||
}.getOrThrow()
|
||||
|
||||
if (!(SharedConfig.addProxy(info) === info)) {
|
||||
|
||||
error("already exists")
|
||||
|
||||
}
|
||||
|
||||
return info
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shareProxy(ctx: Activity, info: SharedConfig.ProxyInfo, type: Int) {
|
||||
|
||||
val url = info.toUrl();
|
||||
|
||||
if (type == 1) {
|
||||
|
||||
AndroidUtilities.addToClipboard(url)
|
||||
|
||||
Toast.makeText(ctx, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_LONG).show()
|
||||
|
||||
} else if (type == 0) {
|
||||
|
||||
val shareIntent = Intent(Intent.ACTION_SEND)
|
||||
|
||||
shareIntent.type = "text/plain"
|
||||
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url)
|
||||
|
||||
val chooserIntent = Intent.createChooser(shareIntent, LocaleController.getString("ShareLink", R.string.ShareLink))
|
||||
|
||||
chooserIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
|
||||
ctx.startActivity(chooserIntent)
|
||||
|
||||
} else {
|
||||
|
||||
showQrDialog(ctx, url)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getOwnerActivity(ctx: Context): Activity {
|
||||
|
||||
if (ctx is Activity) return ctx
|
||||
|
||||
if (ctx is ContextWrapper) return getOwnerActivity(ctx.baseContext)
|
||||
|
||||
error("unable cast ${ctx.javaClass.name} to activity")
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun showQrDialog(ctx: Context, text: String, icon: ((Int) -> Bitmap)? = null): AlertDialog {
|
||||
|
||||
val code = createQRCode(text, icon = icon)
|
||||
|
||||
ctx.setTheme(R.style.Theme_TMessages)
|
||||
|
||||
return AlertDialog.Builder(ctx).setView(LinearLayout(ctx).apply {
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundColor(Color.TRANSPARENT)
|
||||
|
||||
addView(LinearLayout(ctx).apply {
|
||||
val root = this
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundColor(Color.WHITE)
|
||||
setPadding(AndroidUtilities.dp(16f))
|
||||
|
||||
val width = AndroidUtilities.dp(260f)
|
||||
|
||||
addView(ImageView(ctx).apply {
|
||||
|
||||
setImageBitmap(code)
|
||||
|
||||
scaleType = ImageView.ScaleType.FIT_XY
|
||||
|
||||
setOnLongClickListener {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
builder.addItems(arrayOf(
|
||||
|
||||
LocaleController.getString("SaveToGallery", R.string.SaveToGallery),
|
||||
LocaleController.getString("Cancel", R.string.Cancel)
|
||||
|
||||
), intArrayOf(
|
||||
|
||||
R.drawable.baseline_image_24,
|
||||
R.drawable.baseline_cancel_24
|
||||
|
||||
)) { i, _, _ ->
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23 && ctx.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
getOwnerActivity(ctx).requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 4)
|
||||
|
||||
return@addItems
|
||||
|
||||
}
|
||||
|
||||
val saveTo = File(Environment.getExternalStorageDirectory(), "${Environment.DIRECTORY_PICTURES}/share_${text.hashCode()}.jpg")
|
||||
|
||||
saveTo.parentFile?.mkdirs()
|
||||
|
||||
runCatching {
|
||||
|
||||
saveTo.createNewFile()
|
||||
|
||||
saveTo.outputStream().use {
|
||||
|
||||
loadBitmapFromView(root).compress(Bitmap.CompressFormat.JPEG, 100, it);
|
||||
|
||||
}
|
||||
|
||||
AndroidUtilities.addMediaToGallery(saveTo.path)
|
||||
showToast(LocaleController.getString("PhotoSavedHint", R.string.PhotoSavedHint))
|
||||
|
||||
}.onFailure {
|
||||
FileLog.e(it)
|
||||
showToast(it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
return@setOnLongClickListener true
|
||||
|
||||
}
|
||||
|
||||
}, LinearLayout.LayoutParams(width, width))
|
||||
|
||||
}, LinearLayout.LayoutParams(-2, -2).apply {
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
|
||||
})
|
||||
|
||||
}).create().apply {
|
||||
|
||||
show()
|
||||
window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun loadBitmapFromView(v: View): Bitmap {
|
||||
val b = Bitmap.createBitmap(v.width, v.height, Bitmap.Config.ARGB_8888)
|
||||
val c = Canvas(b)
|
||||
v.layout(v.left, v.top, v.right, v.bottom)
|
||||
v.draw(c)
|
||||
return b
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createQRCode(text: String, size: Int = 768, icon: ((Int) -> Bitmap)? = null): Bitmap {
|
||||
return try {
|
||||
val hints = HashMap<EncodeHintType, Any>()
|
||||
hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.M
|
||||
QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, size, size, hints, null, null, icon)
|
||||
} catch (e: WriterException) {
|
||||
FileLog.e(e);
|
||||
Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
}
|
||||
}
|
||||
|
||||
val qrReader = QRCodeReader()
|
||||
|
||||
@JvmStatic
|
||||
fun tryReadQR(ctx: Activity, bitmap: Bitmap) {
|
||||
|
||||
val intArray = IntArray(bitmap.width * bitmap.height)
|
||||
bitmap.getPixels(intArray, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
|
||||
val source = RGBLuminanceSource(bitmap.width, bitmap.height, intArray)
|
||||
|
||||
try {
|
||||
|
||||
val result = try {
|
||||
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source)), mapOf(
|
||||
DecodeHintType.TRY_HARDER to true
|
||||
))
|
||||
} catch (e: NotFoundException) {
|
||||
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source.invert())), mapOf(
|
||||
DecodeHintType.TRY_HARDER to true
|
||||
))
|
||||
}
|
||||
|
||||
showLinkAlert(ctx, result.text)
|
||||
|
||||
} catch (e: Throwable) {
|
||||
|
||||
showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun showLinkAlert(ctx: Activity, text: String, tryInternal: Boolean = true) {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
if (tryInternal) {
|
||||
runCatching {
|
||||
if (Browser.isInternalUrl(text, booleanArrayOf(false))) {
|
||||
Browser.openUrl(ctx, text)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.addTitle(text)
|
||||
|
||||
builder.addItems(arrayOf(
|
||||
LocaleController.getString("Open", R.string.Open),
|
||||
LocaleController.getString("Copy", R.string.Copy),
|
||||
LocaleController.getString("ShareQRCode", R.string.ShareQRCode)
|
||||
), intArrayOf(
|
||||
R.drawable.baseline_open_in_browser_24,
|
||||
R.drawable.baseline_content_copy_24,
|
||||
R.drawable.wallet_qr
|
||||
)) { which, _, _ ->
|
||||
when (which) {
|
||||
0 -> Browser.openUrl(ctx, text)
|
||||
1 -> {
|
||||
AndroidUtilities.addToClipboard(text)
|
||||
showToast(LocaleController.getString("LinkCopied", R.string.LinkCopied))
|
||||
}
|
||||
else -> showQrDialog(ctx, text)
|
||||
}
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.setPadding
|
||||
import com.google.zxing.*
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer
|
||||
import com.google.zxing.qrcode.QRCodeReader
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import org.telegram.messenger.*
|
||||
import org.telegram.messenger.browser.Browser
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil.showToast
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
|
||||
object QrUtil {
|
||||
|
||||
@JvmStatic
|
||||
fun getOwnerActivity(ctx: Context): Activity {
|
||||
|
||||
if (ctx is Activity) return ctx
|
||||
|
||||
if (ctx is ContextWrapper) return getOwnerActivity(ctx.baseContext)
|
||||
|
||||
error("unable cast ${ctx.javaClass.name} to activity")
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun showQrDialog(ctx: Context, text: String, icon: ((Int) -> Bitmap)? = null): AlertDialog {
|
||||
|
||||
val code = createQRCode(text, icon = icon)
|
||||
|
||||
ctx.setTheme(R.style.Theme_TMessages)
|
||||
|
||||
return AlertDialog.Builder(ctx).setView(LinearLayout(ctx).apply {
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundColor(Color.TRANSPARENT)
|
||||
|
||||
addView(LinearLayout(ctx).apply {
|
||||
val root = this
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundColor(Color.WHITE)
|
||||
setPadding(AndroidUtilities.dp(16f))
|
||||
|
||||
val width = AndroidUtilities.dp(260f)
|
||||
|
||||
addView(ImageView(ctx).apply {
|
||||
|
||||
setImageBitmap(code)
|
||||
|
||||
scaleType = ImageView.ScaleType.FIT_XY
|
||||
|
||||
setOnLongClickListener {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
builder.addItems(arrayOf(
|
||||
|
||||
LocaleController.getString("SaveToGallery", R.string.SaveToGallery),
|
||||
LocaleController.getString("Cancel", R.string.Cancel)
|
||||
|
||||
), intArrayOf(
|
||||
|
||||
R.drawable.baseline_image_24,
|
||||
R.drawable.baseline_cancel_24
|
||||
|
||||
)) { i, _, _ ->
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23 && ctx.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
getOwnerActivity(ctx).requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 4)
|
||||
|
||||
return@addItems
|
||||
|
||||
}
|
||||
|
||||
val saveTo = File(Environment.getExternalStorageDirectory(), "${Environment.DIRECTORY_PICTURES}/share_${text.hashCode()}.jpg")
|
||||
|
||||
saveTo.parentFile?.mkdirs()
|
||||
|
||||
runCatching {
|
||||
|
||||
saveTo.createNewFile()
|
||||
|
||||
saveTo.outputStream().use {
|
||||
|
||||
loadBitmapFromView(root).compress(Bitmap.CompressFormat.JPEG, 100, it);
|
||||
|
||||
}
|
||||
|
||||
AndroidUtilities.addMediaToGallery(saveTo.path)
|
||||
showToast(LocaleController.getString("PhotoSavedHint", R.string.PhotoSavedHint))
|
||||
|
||||
}.onFailure {
|
||||
FileLog.e(it)
|
||||
showToast(it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
return@setOnLongClickListener true
|
||||
|
||||
}
|
||||
|
||||
}, LinearLayout.LayoutParams(width, width))
|
||||
|
||||
}, LinearLayout.LayoutParams(-2, -2).apply {
|
||||
|
||||
gravity = Gravity.CENTER
|
||||
|
||||
})
|
||||
|
||||
}).create().apply {
|
||||
|
||||
show()
|
||||
window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun loadBitmapFromView(v: View): Bitmap {
|
||||
val b = Bitmap.createBitmap(v.width, v.height, Bitmap.Config.ARGB_8888)
|
||||
val c = Canvas(b)
|
||||
v.layout(v.left, v.top, v.right, v.bottom)
|
||||
v.draw(c)
|
||||
return b
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createQRCode(text: String, size: Int = 768, icon: ((Int) -> Bitmap)? = null): Bitmap {
|
||||
return try {
|
||||
val hints = HashMap<EncodeHintType, Any>()
|
||||
hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.M
|
||||
QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, size, size, hints, null, null, icon)
|
||||
} catch (e: WriterException) {
|
||||
FileLog.e(e);
|
||||
Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
}
|
||||
}
|
||||
|
||||
val qrReader = QRCodeReader()
|
||||
|
||||
@JvmStatic
|
||||
fun tryReadQR(ctx: Activity, bitmap: Bitmap) {
|
||||
|
||||
val intArray = IntArray(bitmap.width * bitmap.height)
|
||||
bitmap.getPixels(intArray, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
|
||||
val source = RGBLuminanceSource(bitmap.width, bitmap.height, intArray)
|
||||
|
||||
try {
|
||||
|
||||
val result = try {
|
||||
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source)), mapOf(
|
||||
DecodeHintType.TRY_HARDER to true
|
||||
))
|
||||
} catch (e: NotFoundException) {
|
||||
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source.invert())), mapOf(
|
||||
DecodeHintType.TRY_HARDER to true
|
||||
))
|
||||
}
|
||||
|
||||
showLinkAlert(ctx, result.text)
|
||||
|
||||
} catch (e: Throwable) {
|
||||
|
||||
showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun showLinkAlert(ctx: Activity, text: String, tryInternal: Boolean = true) {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
if (tryInternal) {
|
||||
runCatching {
|
||||
if (Browser.isInternalUrl(text, booleanArrayOf(false))) {
|
||||
Browser.openUrl(ctx, text)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.addTitle(text)
|
||||
|
||||
builder.addItems(arrayOf(
|
||||
LocaleController.getString("Open", R.string.Open),
|
||||
LocaleController.getString("Copy", R.string.Copy),
|
||||
LocaleController.getString("ShareQRCode", R.string.ShareQRCode)
|
||||
), intArrayOf(
|
||||
R.drawable.baseline_open_in_browser_24,
|
||||
R.drawable.baseline_content_copy_24,
|
||||
R.drawable.wallet_qr
|
||||
)) { which, _, _ ->
|
||||
when (which) {
|
||||
0 -> Browser.openUrl(ctx, text)
|
||||
1 -> {
|
||||
AndroidUtilities.addToClipboard(text)
|
||||
showToast(LocaleController.getString("LinkCopied", R.string.LinkCopied))
|
||||
}
|
||||
else -> showQrDialog(ctx, text)
|
||||
}
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,3 @@ source "bin/init/env.sh"
|
|||
bin/init/libs/libvpx.sh
|
||||
bin/init/libs/ffmpeg.sh
|
||||
bin/init/libs/boringssl.sh
|
||||
|
||||
# Build v2ray-core
|
||||
bin/libs/v2ray/build.sh
|
|
@ -29,7 +29,3 @@ rm jni/boringssl/util/ar/testdata/mac/libsample.a
|
|||
rm jni/boringssl/util/ar/testdata/linux/libsample.a
|
||||
|
||||
popd
|
||||
|
||||
rm -rf ssr-libev/src/main/jni/pcre/dist/testdata
|
||||
rm -rf ssr-libev/src/main/jni/mbedtls/programs/fuzz/corpuses
|
||||
rm -rf ssr-libev/src/main/jni/mbedtls/tests/data_files
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source "bin/init/env.sh"
|
||||
|
||||
git submodule update --init ss-rust/src/main/rust/shadowsocks-rust
|
||||
rm -rf ss-rust/build/outputs/aar
|
||||
./gradlew ss-rust:assembleRelease || exit 1
|
||||
mkdir -p TMessagesProj/libs
|
||||
cp ss-rust/build/outputs/aar/* TMessagesProj/libs
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source "bin/init/env.sh"
|
||||
|
||||
git submodule update --init 'ssr-libev/src/main/jni/*'
|
||||
rm -rf ssr-libev/build/outputs/aar
|
||||
./gradlew ssr-libev:assembleRelease || exit 1
|
||||
mkdir -p TMessagesProj/libs
|
||||
cp ssr-libev/build/outputs/aar/* TMessagesProj/libs
|
|
@ -1,6 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
bin/libs/v2ray.sh || exit 1
|
||||
bin/libs/shadowsocks.sh || exit 1
|
||||
bin/libs/ssr.sh || exit 1
|
||||
bin/libs/native.sh || exit 1
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
bin/libs/v2ray/init.sh
|
||||
bin/libs/v2ray/build.sh
|
|
@ -1,12 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source "bin/init/env.sh"
|
||||
export GO111MOUDLE=on
|
||||
export GO386=softfloat
|
||||
|
||||
cd "$PROJECT/v2ray"
|
||||
gomobile init
|
||||
gomobile bind -v -ldflags='-s -w' . || exit 1
|
||||
|
||||
mkdir -p "$PROJECT/TMessagesProj/libs"
|
||||
/bin/cp -f libv2ray.aar "$PROJECT/TMessagesProj/libs"
|
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source "bin/init/env.sh"
|
||||
export GO111MOUDLE=on
|
||||
export PATH="$PATH:$(go env GOPATH)/bin"
|
||||
|
||||
cd $PROJECT
|
||||
[ -f v2ray/go.mod ] || git submodule update --init v2ray
|
||||
cd v2ray
|
||||
git reset --hard && git clean -fdx
|
||||
go mod download -x && go get -v golang.org/x/mobile/cmd/... || exit 1
|
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,77 +0,0 @@
|
|||
import com.android.build.gradle.internal.tasks.factory.dependsOn
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("org.mozilla.rust-android-gradle.rust-android")
|
||||
}
|
||||
|
||||
var targetAbi = ""
|
||||
if (gradle.startParameter.taskNames.isNotEmpty()) {
|
||||
if (gradle.startParameter.taskNames.size == 1) {
|
||||
val targetTask = gradle.startParameter.taskNames[0].toLowerCase()
|
||||
if (targetTask.contains("arm64")) {
|
||||
targetAbi = "arm64"
|
||||
} else if (targetTask.contains("arm")) {
|
||||
targetAbi = "arm"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
ndkVersion = rootProject.extra.get("ndkVersion").toString()
|
||||
|
||||
compileSdk = 31
|
||||
defaultConfig {
|
||||
minSdk = 23
|
||||
targetSdk = 31
|
||||
}
|
||||
buildToolsVersion = "31.0.0"
|
||||
namespace = "io.nekohasekai.ss_rust"
|
||||
|
||||
if (targetAbi.isNotBlank()) splits.abi {
|
||||
reset()
|
||||
include(* when (targetAbi) {
|
||||
"arm" -> arrayOf("armeabi-v7a")
|
||||
"arm64" -> arrayOf("arm64-v8a")
|
||||
else -> arrayOf("x86", "x86_64")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cargo {
|
||||
module = "src/main/rust/shadowsocks-rust"
|
||||
libname = "ss-local"
|
||||
targets = when {
|
||||
targetAbi.isBlank() -> listOf("arm", "arm64", "x86", "x86_64")
|
||||
targetAbi == "arm" -> listOf("arm")
|
||||
targetAbi == "arm64" -> listOf("arm64")
|
||||
else -> listOf("arm", "arm64")
|
||||
}
|
||||
profile = findProperty("CARGO_PROFILE")?.toString() ?: "release"
|
||||
extraCargoBuildArguments = listOf("--bin", "sslocal")
|
||||
featureSpec.noDefaultBut(arrayOf(
|
||||
"stream-cipher",
|
||||
"logging",
|
||||
"local-flow-stat",
|
||||
"local-dns"))
|
||||
exec = { spec, toolchain ->
|
||||
spec.environment("RUST_ANDROID_GRADLE_LINKER_WRAPPER_PY", "$projectDir/$module/../linker-wrapper.py")
|
||||
spec.environment("RUST_ANDROID_GRADLE_TARGET", "target/${toolchain.target}/$profile/lib$libname.so")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded {
|
||||
when (name) {
|
||||
"mergeDebugJniLibFolders", "mergeReleaseJniLibFolders" -> dependsOn("cargoBuild")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoClean") {
|
||||
executable("cargo") // cargo.cargoCommand
|
||||
args("clean")
|
||||
workingDir("$projectDir/${cargo.module}")
|
||||
}
|
||||
|
||||
tasks.clean.dependsOn("cargoClean")
|
|
@ -1,3 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
|
@ -1,18 +0,0 @@
|
|||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import os
|
||||
import pipes
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
args = [os.environ['RUST_ANDROID_GRADLE_CC'], os.environ['RUST_ANDROID_GRADLE_CC_LINK_ARG']] + sys.argv[1:]
|
||||
|
||||
# This only appears when the subprocess call fails, but it's helpful then.
|
||||
printable_cmd = ' '.join(pipes.quote(arg) for arg in args)
|
||||
print(printable_cmd)
|
||||
|
||||
code = subprocess.call(args)
|
||||
if code == 0:
|
||||
shutil.copyfile(sys.argv[sys.argv.index('-o') + 1], os.environ['RUST_ANDROID_GRADLE_TARGET'])
|
||||
sys.exit(code)
|
|
@ -1 +0,0 @@
|
|||
Subproject commit f805b5d3503e5ca0f85c22dabdeac3341618ec86
|
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,55 +0,0 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
def targetAbi = ""
|
||||
if (!gradle.startParameter.taskNames.isEmpty()) {
|
||||
if (gradle.startParameter.taskNames.size == 1) {
|
||||
def targetTask = gradle.startParameter.taskNames[0].toLowerCase()
|
||||
if (targetTask.contains("arm64")) {
|
||||
targetAbi = "arm64"
|
||||
} else if (targetTask.contains("arm")) {
|
||||
targetAbi = "arm"
|
||||
}
|
||||
} else {
|
||||
targetAbi = "~"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 30
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
if (!targetAbi.isBlank()) {
|
||||
if (targetAbi == "arm64") {
|
||||
abiFilters 'arm64-v8a'
|
||||
} else if (targetAbi == "arm") {
|
||||
abiFilters 'armeabi-v7a'
|
||||
} else {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
||||
}
|
||||
} else {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
}
|
||||
|
||||
arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk", "APP_PLATFORM:=android-21", "--jobs=${Runtime.getRuntime().availableProcessors()}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path 'src/main/jni/Android.mk'
|
||||
}
|
||||
}
|
||||
namespace 'io.nekohasekai.ssr_libev'
|
||||
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
|
@ -1,293 +0,0 @@
|
|||
# Copyright (C) 2009 The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
ROOT_PATH := $(LOCAL_PATH)
|
||||
|
||||
BUILD_SHARED_EXECUTABLE := $(LOCAL_PATH)/build-shared-executable.mk
|
||||
|
||||
########################################################
|
||||
## libsodium
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
SODIUM_SOURCE := \
|
||||
crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c \
|
||||
crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c \
|
||||
crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c \
|
||||
crypto_core/ed25519/ref10/ed25519_ref10.c \
|
||||
crypto_core/hchacha20/core_hchacha20.c \
|
||||
crypto_core/salsa/ref/core_salsa_ref.c \
|
||||
crypto_generichash/blake2b/ref/blake2b-compress-ref.c \
|
||||
crypto_generichash/blake2b/ref/blake2b-ref.c \
|
||||
crypto_generichash/blake2b/ref/generichash_blake2b.c \
|
||||
crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \
|
||||
crypto_onetimeauth/poly1305/donna/poly1305_donna.c \
|
||||
crypto_pwhash/crypto_pwhash.c \
|
||||
crypto_pwhash/argon2/argon2-core.c \
|
||||
crypto_pwhash/argon2/argon2.c \
|
||||
crypto_pwhash/argon2/argon2-encoding.c \
|
||||
crypto_pwhash/argon2/argon2-fill-block-ref.c \
|
||||
crypto_pwhash/argon2/blake2b-long.c \
|
||||
crypto_pwhash/argon2/pwhash_argon2i.c \
|
||||
crypto_scalarmult/curve25519/scalarmult_curve25519.c \
|
||||
crypto_scalarmult/curve25519/ref10/x25519_ref10.c \
|
||||
crypto_stream/chacha20/stream_chacha20.c \
|
||||
crypto_stream/chacha20/ref/chacha20_ref.c \
|
||||
crypto_stream/salsa20/stream_salsa20.c \
|
||||
crypto_stream/salsa20/ref/salsa20_ref.c \
|
||||
crypto_verify/sodium/verify.c \
|
||||
randombytes/randombytes.c \
|
||||
randombytes/sysrandom/randombytes_sysrandom.c \
|
||||
sodium/core.c \
|
||||
sodium/runtime.c \
|
||||
sodium/utils.c \
|
||||
sodium/version.c
|
||||
|
||||
LOCAL_MODULE := sodium
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/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_BUGREPORT=\"https://github.com/jedisct1/libsodium/issues\" \
|
||||
-DPACKAGE_URL=\"https://github.com/jedisct1/libsodium\" \
|
||||
-DPACKAGE=\"libsodium\" -DVERSION=\"1.0.15\" \
|
||||
-DHAVE_PTHREAD=1 \
|
||||
-DSTDC_HEADERS=1 \
|
||||
-DHAVE_SYS_TYPES_H=1 \
|
||||
-DHAVE_SYS_STAT_H=1 \
|
||||
-DHAVE_STDLIB_H=1 \
|
||||
-DHAVE_STRING_H=1 \
|
||||
-DHAVE_MEMORY_H=1 \
|
||||
-DHAVE_STRINGS_H=1 \
|
||||
-DHAVE_INTTYPES_H=1 \
|
||||
-DHAVE_STDINT_H=1 \
|
||||
-DHAVE_UNISTD_H=1 \
|
||||
-D__EXTENSIONS__=1 \
|
||||
-D_ALL_SOURCE=1 \
|
||||
-D_GNU_SOURCE=1 \
|
||||
-D_POSIX_PTHREAD_SEMANTICS=1 \
|
||||
-D_TANDEM_SOURCE=1 \
|
||||
-DHAVE_DLFCN_H=1 \
|
||||
-DLT_OBJDIR=\".libs/\" \
|
||||
-DHAVE_SYS_MMAN_H=1 \
|
||||
-DNATIVE_LITTLE_ENDIAN=1 \
|
||||
-DASM_HIDE_SYMBOL=.hidden \
|
||||
-DHAVE_WEAK_SYMBOLS=1 \
|
||||
-DHAVE_ATOMIC_OPS=1 \
|
||||
-DHAVE_ARC4RANDOM=1 \
|
||||
-DHAVE_ARC4RANDOM_BUF=1 \
|
||||
-DHAVE_MMAP=1 \
|
||||
-DHAVE_MLOCK=1 \
|
||||
-DHAVE_MADVISE=1 \
|
||||
-DHAVE_MPROTECT=1 \
|
||||
-DHAVE_NANOSLEEP=1 \
|
||||
-DHAVE_POSIX_MEMALIGN=1 \
|
||||
-DHAVE_GETPID=1 \
|
||||
-DCONFIGURED=1
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix libsodium/src/libsodium/,$(SODIUM_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libancillary
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ANCILLARY_SOURCE := fd_recv.c fd_send.c
|
||||
|
||||
LOCAL_MODULE := libancillary
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/libancillary
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix libancillary/, $(ANCILLARY_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libipset
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
|
||||
bdd/reachable.c bdd/read.c bdd/write.c
|
||||
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
|
||||
map/storage.c
|
||||
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
|
||||
set/iterator.c set/storage.c
|
||||
|
||||
IPSET_SOURCE := general.c $(bdd_src) $(map_src) $(set_src)
|
||||
|
||||
LOCAL_MODULE := libipset
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libipset/,$(IPSET_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libcork
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
cli_src := cli/commands.c
|
||||
core_src := core/allocator.c core/error.c core/gc.c \
|
||||
core/hash.c core/ip-address.c core/mempool.c \
|
||||
core/timestamp.c core/u128.c
|
||||
ds_src := ds/array.c ds/bitset.c ds/buffer.c ds/dllist.c \
|
||||
ds/file-stream.c ds/hash-table.c ds/managed-buffer.c \
|
||||
ds/ring-buffer.c ds/slice.c
|
||||
posix_src := posix/directory-walker.c posix/env.c posix/exec.c \
|
||||
posix/files.c posix/process.c posix/subprocess.c
|
||||
pthreads_src := pthreads/thread.c
|
||||
|
||||
CORK_SOURCE := $(cli_src) $(core_src) $(ds_src) $(posix_src) $(pthreads_src)
|
||||
|
||||
LOCAL_MODULE := libcork
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
|
||||
-DCORK_API=CORK_LOCAL
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libcork/,$(CORK_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libudns
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
UDNS_SOURCES := udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_init.c \
|
||||
udns_misc.c udns_XtoX.c \
|
||||
udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
|
||||
udns_rr_srv.c udns_rr_naptr.c udns_codes.c udns_jran.c
|
||||
|
||||
LOCAL_MODULE := libudns
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libudns \
|
||||
-DHAVE_DECL_INET_NTOP
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libudns/,$(UDNS_SOURCES))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libev
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libev
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/include/libev
|
||||
LOCAL_SRC_FILES := \
|
||||
shadowsocks-libev/libev/ev.c \
|
||||
shadowsocks-libev/libev/event.c
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## shadowsocks-libev local
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c \
|
||||
utils.c netutils.c json.c jconf.c acl.c http.c tls.c rule.c \
|
||||
android.c
|
||||
|
||||
LOCAL_MODULE := ssr-local
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
|
||||
LOCAL_CFLAGS := -Wall -fno-strict-aliasing -DMODULE_LOCAL \
|
||||
-DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H \
|
||||
-DCONNECT_IN_PROGRESS=EINPROGRESS \
|
||||
-I$(LOCAL_PATH)/include/shadowsocks-libev \
|
||||
-I$(LOCAL_PATH)/include \
|
||||
-I$(LOCAL_PATH)/libancillary \
|
||||
-I$(LOCAL_PATH)/mbedtls/include \
|
||||
-I$(LOCAL_PATH)/pcre \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libudns \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
|
||||
-I$(LOCAL_PATH)/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/libsodium/src/libsodium/include/sodium \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libev \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/src
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libev libmbedtls libipset libcork libudns \
|
||||
libsodium libancillary libpcre
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_SHARED_EXECUTABLE)
|
||||
|
||||
########################################################
|
||||
## mbed TLS
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := mbedtls
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/mbedtls/include
|
||||
|
||||
MBEDTLS_SOURCES := $(wildcard $(LOCAL_PATH)/mbedtls/library/*.c)
|
||||
|
||||
LOCAL_SRC_FILES := $(MBEDTLS_SOURCES:$(LOCAL_PATH)/%=%)
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## pcre
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := pcre
|
||||
|
||||
LOCAL_CFLAGS += -DHAVE_CONFIG_H
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/pcre/dist $(LOCAL_PATH)/pcre
|
||||
|
||||
libpcre_src_files := \
|
||||
dist/pcre_byte_order.c \
|
||||
dist/pcre_compile.c \
|
||||
dist/pcre_config.c \
|
||||
dist/pcre_dfa_exec.c \
|
||||
dist/pcre_exec.c \
|
||||
dist/pcre_fullinfo.c \
|
||||
dist/pcre_get.c \
|
||||
dist/pcre_globals.c \
|
||||
dist/pcre_jit_compile.c \
|
||||
dist/pcre_maketables.c \
|
||||
dist/pcre_newline.c \
|
||||
dist/pcre_ord2utf8.c \
|
||||
dist/pcre_refcount.c \
|
||||
dist/pcre_string_utils.c \
|
||||
dist/pcre_study.c \
|
||||
dist/pcre_tables.c \
|
||||
dist/pcre_ucd.c \
|
||||
dist/pcre_valid_utf8.c \
|
||||
dist/pcre_version.c \
|
||||
dist/pcre_xclass.c
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files)) $(LOCAL_PATH)/patch/pcre/pcre_chartables.c
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
|
@ -1,4 +0,0 @@
|
|||
APP_CFLAGS := -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
APP_LDFLAGS := -Wl,--hash-style=both -Wl,-exclude-libs,ALL -Wl,--gc-sections
|
||||
APP_THIN_ARCHIVE := true
|
||||
APP_STL := c++_static
|
|
@ -1,31 +0,0 @@
|
|||
# Copyright (C) 2009 The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# this file is included from Android.mk files to build a target-specific
|
||||
# executable program
|
||||
#
|
||||
# Modified by @Mygod, based on:
|
||||
# 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))
|
||||
$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
|
||||
$(call check-LOCAL_MODULE_FILENAME)
|
||||
# we are building target objects
|
||||
my := TARGET_
|
||||
$(call handle-module-filename,lib,$(TARGET_SONAME_EXTENSION))
|
||||
$(call handle-module-built)
|
||||
LOCAL_MODULE_CLASS := EXECUTABLE
|
||||
include $(BUILD_SYSTEM)/build-module.mk
|
|
@ -1,129 +0,0 @@
|
|||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
/* #undef HAVE_CLOCK_GETTIME */
|
||||
|
||||
/* Define to 1 to use the syscall interface for clock_gettime */
|
||||
#define HAVE_CLOCK_SYSCALL 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
#define HAVE_EPOLL_CTL 1
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
#define HAVE_EVENTFD 1
|
||||
|
||||
/* Define to 1 if the floor function is available */
|
||||
#define HAVE_FLOOR 1
|
||||
|
||||
/* Define to 1 if you have the `inotify_init' function. */
|
||||
#define HAVE_INOTIFY_INIT 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef HAVE_KQUEUE */
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
/* #undef HAVE_LIBRT */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#define HAVE_NANOSLEEP 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#define HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef HAVE_PORT_H */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#define HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `signalfd' function. */
|
||||
#define HAVE_SIGNALFD 0
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
#define HAVE_SYS_EPOLL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
#define HAVE_SYS_EVENTFD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/inotify.h> header file. */
|
||||
#define HAVE_SYS_INOTIFY_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/signalfd.h> header file. */
|
||||
#define HAVE_SYS_SIGNALFD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libev"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "4.11"
|
||||
|
||||
#define DNDEBUG 1
|
||||
#define HAVE_CONFIG_H 1
|
|
@ -1,425 +0,0 @@
|
|||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* errno for incomplete non-blocking connect(2) */
|
||||
#define CONNECT_IN_PROGRESS EINPROGRESS
|
||||
|
||||
/* Override libev default fd conversion macro. */
|
||||
/* #undef EV_FD_TO_WIN32_HANDLE */
|
||||
|
||||
/* Override libev default fd close macro. */
|
||||
/* #undef EV_WIN32_CLOSE_FD */
|
||||
|
||||
/* Override libev default handle conversion macro. */
|
||||
/* #undef EV_WIN32_HANDLE_TO_FD */
|
||||
|
||||
/* Reset max file descriptor size. */
|
||||
/* #undef FD_SETSIZE */
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the `CCCryptorCreateWithMode' function. */
|
||||
/* #undef HAVE_CCCRYPTORCREATEWITHMODE */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
/* #undef HAVE_CLOCK_GETTIME */
|
||||
|
||||
/* Define to 1 to use the syscall interface for clock_gettime */
|
||||
/* #undef HAVE_CLOCK_SYSCALL */
|
||||
|
||||
/* Define to 1 if you have the <CommonCrypto/CommonCrypto.h> header file. */
|
||||
/* #undef HAVE_COMMONCRYPTO_COMMONCRYPTO_H */
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_INET_NTOP 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
/* #undef HAVE_EPOLL_CTL */
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
/* #undef HAVE_EVENTFD */
|
||||
|
||||
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
|
||||
/* #undef HAVE_EVP_ENCRYPTINIT_EX */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if the floor function is available */
|
||||
#define HAVE_FLOOR 1
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#define HAVE_FORK 1
|
||||
|
||||
/* Define to 1 if you have the `getpwnam_r' function. */
|
||||
#define HAVE_GETPWNAM_R 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
/* #undef HAVE_INET_NTOP */
|
||||
|
||||
/* Define to 1 if you have the `inotify_init' function. */
|
||||
/* #undef HAVE_INOTIFY_INIT */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Enable IPv6 support in libudns */
|
||||
#define HAVE_IPv6 1
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
#define HAVE_KQUEUE 1
|
||||
|
||||
/* Define to 1 if you have the <langinfo.h> header file. */
|
||||
#define HAVE_LANGINFO_H 1
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
/* #undef HAVE_LIBRT */
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef HAVE_LIBSOCKET */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <linux/if.h> header file. */
|
||||
/* #undef HAVE_LINUX_IF_H */
|
||||
|
||||
/* Define to 1 if you have the <linux/netfilter_ipv4.h> header file. */
|
||||
/* #undef HAVE_LINUX_NETFILTER_IPV4_H */
|
||||
|
||||
/* Define to 1 if you have the <linux/netfilter_ipv6/ip6_tables.h> header
|
||||
file. */
|
||||
/* #undef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H */
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if you have the `malloc' function. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#define HAVE_NANOSLEEP 1
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define HAVE_NETDB_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <net/if.h> header file. */
|
||||
#define HAVE_NET_IF_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/engine.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_ENGINE_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/err.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_ERR_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/evp.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_EVP_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/pem.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_PEM_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/rand.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_RAND_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/rsa.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_RSA_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/sha.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_SHA_H */
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#define HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef HAVE_PORT_H */
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#define HAVE_PTHREAD_PRIO_INHERIT 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_pseudo_bytes' function. */
|
||||
/* #undef HAVE_RAND_PSEUDO_BYTES */
|
||||
|
||||
/* Define to 1 if you have the 'select' function. */
|
||||
#define HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `setresuid' function. */
|
||||
/* #undef HAVE_SETRESUID */
|
||||
|
||||
/* Define to 1 if you have the `setreuid' function. */
|
||||
#define HAVE_SETREUID 1
|
||||
|
||||
/* Define to 1 if you have the `setrlimit' function. */
|
||||
#define HAVE_SETRLIMIT 1
|
||||
|
||||
/* Define to 1 if you have the `signalfd' function. */
|
||||
/* #undef HAVE_SIGNALFD */
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#define HAVE_SOCKET 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
/* #undef HAVE_SYS_EPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
/* #undef HAVE_SYS_EVENTFD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
#define HAVE_SYS_EVENT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/inotify.h> header file. */
|
||||
/* #undef HAVE_SYS_INOTIFY_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/signalfd.h> header file. */
|
||||
/* #undef HAVE_SYS_SIGNALFD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#define HAVE_VFORK 1
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
/* #undef HAVE_VFORK_H */
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
/* #undef HAVE_WINDOWS_H */
|
||||
|
||||
/* Define to 1 if you have the <winsock2.h> header file. */
|
||||
/* #undef HAVE_WINSOCK2_H */
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#define HAVE_WORKING_FORK 1
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#define HAVE_WORKING_VFORK 1
|
||||
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
/* #undef HAVE_WS2TCPIP_H */
|
||||
|
||||
/* have zlib compression support */
|
||||
/* #undef HAVE_ZLIB */
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
/* #undef HAVE_ZLIB_H */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Define to 1 if assertions should be disabled. */
|
||||
/* #undef NDEBUG */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "shadowsocks-libev"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "max.c.lv@gmail.com"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "shadowsocks-libev"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "shadowsocks-libev 2.4.8"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "shadowsocks-libev"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "2.4.8"
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
#define SELECT_TYPE_ARG1 int
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
#define SELECT_TYPE_ARG234 (fd_set *)
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
#define SELECT_TYPE_ARG5 (struct timeval *)
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* If the compiler supports a TLS storage class define it to that here */
|
||||
#define TLS __thread
|
||||
|
||||
/* Use Apple CommonCrypto library */
|
||||
/* #undef USE_CRYPTO_APPLECC */
|
||||
|
||||
/* Use mbed TLS library */
|
||||
#define USE_CRYPTO_MBEDTLS 1
|
||||
|
||||
/* Use OpenSSL library */
|
||||
/* #undef USE_CRYPTO_OPENSSL */
|
||||
|
||||
/* Use PolarSSL library */
|
||||
/* #undef USE_CRYPTO_POLARSSL */
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# define _ALL_SOURCE 1
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# define _TANDEM_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.4.8"
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
/* #undef _MINIX */
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
/* #undef _POSIX_1_SOURCE */
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
/* #undef _POSIX_SOURCE */
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
/* #undef _UINT8_T */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to the equivalent of the C99 'restrict' keyword, or to
|
||||
nothing if this is not supported. Do not define if restrict is
|
||||
supported directly. */
|
||||
#define restrict __restrict
|
||||
/* Work around a bug in Sun C++: it does not support _Restrict or
|
||||
__restrict__, even though the corresponding Sun C compiler ends up with
|
||||
"#define restrict _Restrict" or "#define restrict __restrict__" in the
|
||||
previous line. Perhaps some future version of Sun C++ will work with
|
||||
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
|
||||
#if defined __SUNPRO_CC && !defined __RESTRICT
|
||||
# define _Restrict
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef ssize_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint16_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint8_t */
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
/* #undef vfork */
|
||||
|
||||
/* Define to 1 if you have the <pcre.h> header file. */
|
||||
#define HAVE_PCRE_H 1
|
||||
|
||||
/* Define to 1 if you have the <pcre/pcre.h> header file. */
|
||||
/* #undef HAVE_PCRE_PCRE_H */
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
#ifndef sodium_version_H
|
||||
#define sodium_version_H
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#define SODIUM_VERSION_STRING "1.0.7"
|
||||
|
||||
#define SODIUM_LIBRARY_VERSION_MAJOR 9
|
||||
#define SODIUM_LIBRARY_VERSION_MINOR 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SODIUM_EXPORT
|
||||
const char *sodium_version_string(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_library_version_major(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_library_version_minor(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 311e5d14f593f16c785bc6605220517eb1f21f6b
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 3b689a6ab443cb7b467c2cb6c8434d97fd807168
|
|
@ -1 +0,0 @@
|
|||
Subproject commit d414c32a160a45725430d99b3c11904760ac8b9c
|
|
@ -1,198 +0,0 @@
|
|||
/*************************************************
|
||||
* 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 */
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 222bbf4b3fb8e13c21686803e47e31aa3e4ad130
|
|
@ -1 +0,0 @@
|
|||
Subproject commit ca93436e5b1be02f9f4bfca79b8202c400161994
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 70921a02a860b0ca2df4069a609951bc4182c245
|
1
v2ray
1
v2ray
|
@ -1 +0,0 @@
|
|||
Subproject commit a697372e996000fa748f87b4c2bad4da038b5ddf
|
Loading…
Reference in New Issue