feat: 初始化XMBOX项目

This commit is contained in:
Tosencen
2025-07-03 06:16:21 +08:00
commit 0a10f73143
914 changed files with 71817 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+40
View File
@@ -0,0 +1,40 @@
plugins {
id 'com.android.library'
}
android {
namespace 'com.github.catvod.crawler'
compileSdk 35
defaultConfig {
minSdk 21
targetSdk 28
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
api 'androidx.annotation:annotation:1.6.0'
api 'androidx.preference:preference:1.2.1'
api 'com.google.code.gson:gson:' + gsonVersion
api 'com.google.net.cronet:cronet-okhttp:0.1.0'
api 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3'
api 'com.orhanobut:logger:2.2.0'
api 'com.squareup.okhttp3:okhttp:' + okhttpVersion
api 'com.squareup.okhttp3:okhttp-dnsoverhttps:' + okhttpVersion
api 'com.squareup.okhttp3:logging-interceptor:' + okhttpVersion
api 'org.chromium.net:cronet-embedded:76.3809.111'
api('com.google.guava:guava:33.3.1-android') {
exclude group: 'com.google.code.findbugs', module: 'jsr305'
exclude group: 'org.checkerframework', module: 'checker-compat-qual'
exclude group: 'org.checkerframework', module: 'checker-qual'
exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
exclude group: 'com.google.j2objc', module: 'j2objc-annotations'
exclude group: 'org.codehaus.mojo', module: 'animal-sniffer-annotations'
}
}
+2
View File
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest />
@@ -0,0 +1,26 @@
package com.github.catvod;
import android.content.Context;
import java.lang.ref.WeakReference;
public class Init {
private WeakReference<Context> context;
private static class Loader {
static volatile Init INSTANCE = new Init();
}
private static Init get() {
return Loader.INSTANCE;
}
public static void set(Context context) {
get().context = new WeakReference<>(context);
}
public static Context context() {
return get().context.get();
}
}
@@ -0,0 +1,20 @@
package com.github.catvod;
import com.github.catvod.utils.Util;
public class Proxy {
private static int port = -1;
public static void set(int port) {
Proxy.port = port;
}
public static int getPort() {
return port;
}
public static String getUrl(boolean local) {
return "http://" + (local ? "127.0.0.1" : Util.getIp()) + ":" + getPort() + "/proxy";
}
}
@@ -0,0 +1,93 @@
package com.github.catvod.bean;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.github.catvod.crawler.R;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Doh {
@SerializedName("name")
private String name;
@SerializedName("url")
private String url;
@SerializedName("ips")
private List<String> ips;
public static List<Doh> get(Context context) {
List<Doh> items = new ArrayList<>();
String[] urls = context.getResources().getStringArray(R.array.doh_url);
String[] names = context.getResources().getStringArray(R.array.doh_name);
for (int i = 0; i < names.length; i++) items.add(new Doh().name(names[i]).url(urls[i]));
return items;
}
public static Doh objectFrom(String str) {
Doh item = new Gson().fromJson(str, Doh.class);
return item == null ? new Doh() : item;
}
public static List<Doh> arrayFrom(JsonElement element) {
Type listType = new TypeToken<List<Doh>>() {}.getType();
List<Doh> items = new Gson().fromJson(element, listType);
return items == null ? new ArrayList<>() : items;
}
public Doh name(String name) {
this.name = name;
return this;
}
public Doh url(String url) {
this.url = url;
return this;
}
public String getName() {
return TextUtils.isEmpty(name) ? "" : name;
}
public String getUrl() {
return TextUtils.isEmpty(url) ? "" : url;
}
public List<String> getIps() {
return ips == null ? Collections.emptyList() : ips;
}
public List<InetAddress> getHosts() {
try {
List<InetAddress> list = new ArrayList<>();
for (String ip : getIps()) list.add(InetAddress.getByName(ip));
return list.isEmpty() ? null : list;
} catch (Exception ignored) {
return null;
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Doh)) return false;
Doh it = (Doh) obj;
return getUrl().equals(it.getUrl());
}
@NonNull
@Override
public String toString() {
return new Gson().toJson(this);
}
}
@@ -0,0 +1,81 @@
package com.github.catvod.crawler;
import android.content.Context;
import com.github.catvod.net.OkHttp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.Dns;
import okhttp3.OkHttpClient;
public abstract class Spider {
public void init(Context context) throws Exception {
}
public void init(Context context, String extend) throws Exception {
init(context);
}
public String homeContent(boolean filter) throws Exception {
return "";
}
public String homeVideoContent() throws Exception {
return "";
}
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
return "";
}
public String detailContent(List<String> ids) throws Exception {
return "";
}
public String searchContent(String key, boolean quick) throws Exception {
return "";
}
public String searchContent(String key, boolean quick, String pg) throws Exception {
return "";
}
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
return "";
}
public String liveContent(String url) throws Exception {
return "";
}
public boolean manualVideoCheck() throws Exception {
return false;
}
public boolean isVideoFormat(String url) throws Exception {
return false;
}
public Object[] proxyLocal(Map<String, String> params) throws Exception {
return null;
}
public String action(String action) throws Exception {
return null;
}
public void destroy() {
}
public static Dns safeDns() {
return OkHttp.dns();
}
public static OkHttpClient client() {
return OkHttp.client();
}
}
@@ -0,0 +1,18 @@
package com.github.catvod.crawler;
import android.text.TextUtils;
import com.orhanobut.logger.Logger;
public class SpiderDebug {
private static final String TAG = SpiderDebug.class.getSimpleName();
public static void log(Throwable th) {
if (th != null) th.printStackTrace();
}
public static void log(String msg) {
if (!TextUtils.isEmpty(msg)) Logger.t(TAG).d(msg);
}
}
@@ -0,0 +1,4 @@
package com.github.catvod.crawler;
public class SpiderNull extends Spider {
}
@@ -0,0 +1,87 @@
package com.github.catvod.net;
import android.text.TextUtils;
import android.webkit.CookieManager;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import com.google.common.net.HttpHeaders;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.Request;
public class OkCookieJar implements CookieJar {
private CookieManager manager;
private static class Loader {
static volatile OkCookieJar INSTANCE = new OkCookieJar();
}
public static OkCookieJar get() {
return Loader.INSTANCE;
}
private OkCookieJar() {
try {
manager = CookieManager.getInstance();
} catch (Throwable ignored) {
}
}
public static void setAcceptThirdPartyCookies(WebView view) {
try {
get().manager.setAcceptThirdPartyCookies(view, true);
} catch (Throwable ignored) {
}
}
public static void sync(HttpUrl url, Request request) {
if (!"127.0.0.1".equals(url.host())) sync(url.toString(), request.header(HttpHeaders.COOKIE));
}
public static void sync(String url, String cookie) {
try {
if (TextUtils.isEmpty(cookie)) return;
for (String split : cookie.split(";")) get().manager.setCookie(url, split);
get().manager.flush();
} catch (Throwable ignored) {
}
}
private void add(List<Cookie> items, Cookie cookie) {
if (cookie != null) items.add(cookie);
}
@NonNull
@Override
public synchronized List<Cookie> loadForRequest(@NonNull HttpUrl url) {
try {
List<Cookie> items = new ArrayList<>();
String cookie = manager.getCookie(url.toString());
if (TextUtils.isEmpty(cookie)) return Collections.emptyList();
if ("127.0.0.1".equals(url.host())) return Collections.emptyList();
for (String split : cookie.split(";")) add(items, Cookie.parse(url, split));
return items;
} catch (Throwable e) {
return Collections.emptyList();
}
}
@Override
public synchronized void saveFromResponse(@NonNull HttpUrl url, @NonNull List<Cookie> cookies) {
try {
if ("127.0.0.1".equals(url.host())) return;
for (Cookie cookie : cookies) manager.setCookie(url.toString(), cookie.toString());
manager.flush();
} catch (Throwable ignored) {
}
}
}
@@ -0,0 +1,49 @@
package com.github.catvod.net;
import androidx.annotation.NonNull;
import com.github.catvod.utils.Util;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Dns;
import okhttp3.dnsoverhttps.DnsOverHttps;
public class OkDns implements Dns {
private final ConcurrentHashMap<String, String> map;
private DnsOverHttps doh;
public OkDns() {
this.map = new ConcurrentHashMap<>();
}
public void setDoh(DnsOverHttps doh) {
this.doh = doh;
}
public void clear() {
map.clear();
}
public synchronized void addAll(List<String> hosts) {
for (String host : hosts) {
if (!host.contains("=")) continue;
String[] splits = host.split("=", 2);
String oldHost = splits[0];
String newHost = splits[1];
map.put(oldHost, newHost);
}
}
@NonNull
@Override
public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
for (Map.Entry<String, String> entry : map.entrySet()) if (Util.containOrMatch(hostname, entry.getKey())) hostname = entry.getValue();
return (doh != null ? doh : Dns.SYSTEM).lookup(hostname);
}
}
@@ -0,0 +1,242 @@
package com.github.catvod.net;
import android.annotation.SuppressLint;
import android.text.TextUtils;
import androidx.collection.ArrayMap;
import com.github.catvod.bean.Doh;
import com.github.catvod.net.interceptor.AuthInterceptor;
import com.github.catvod.net.interceptor.RequestInterceptor;
import com.github.catvod.net.interceptor.ResponseInterceptor;
import java.net.ProxySelector;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.dnsoverhttps.DnsOverHttps;
import okhttp3.logging.HttpLoggingInterceptor;
public class OkHttp {
private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(30);
private static final ProxySelector defaultSelector;
private ResponseInterceptor responseInterceptor;
private RequestInterceptor requestInterceptor;
private AuthInterceptor authInterceptor;
private OkProxySelector selector;
private OkHttpClient client;
private OkDns dns;
private boolean proxy;
static {
defaultSelector = ProxySelector.getDefault();
}
private static class Loader {
static volatile OkHttp INSTANCE = new OkHttp();
}
public static OkHttp get() {
return Loader.INSTANCE;
}
public void clear() {
cancelAll();
dns().clear();
selector().clear();
authInterceptor().clear();
requestInterceptor().clear();
responseInterceptor().clear();
}
public void setDoh(Doh doh) {
dns().setDoh(doh.getUrl().isEmpty() ? null : new DnsOverHttps.Builder().client(new OkHttpClient()).url(HttpUrl.get(doh.getUrl())).bootstrapDnsHosts(doh.getHosts()).build());
client = null;
}
public void setProxy(String proxy) {
ProxySelector.setDefault(TextUtils.isEmpty(proxy) ? defaultSelector : selector());
if (!TextUtils.isEmpty(proxy)) selector().setProxy(proxy);
this.proxy = !TextUtils.isEmpty(proxy);
client = null;
}
public static OkDns dns() {
if (get().dns != null) return get().dns;
return get().dns = new OkDns();
}
public static ResponseInterceptor responseInterceptor() {
if (get().responseInterceptor != null) return get().responseInterceptor;
return get().responseInterceptor = new ResponseInterceptor();
}
public static RequestInterceptor requestInterceptor() {
if (get().requestInterceptor != null) return get().requestInterceptor;
return get().requestInterceptor = new RequestInterceptor();
}
public static AuthInterceptor authInterceptor() {
if (get().authInterceptor != null) return get().authInterceptor;
return get().authInterceptor = new AuthInterceptor();
}
public static OkProxySelector selector() {
if (get().selector != null) return get().selector;
return get().selector = new OkProxySelector();
}
public static OkHttpClient client() {
if (get().client != null) return get().client;
return get().client = getBuilder().build();
}
public static OkHttpClient client(long timeout) {
return client().newBuilder().connectTimeout(timeout, TimeUnit.MILLISECONDS).readTimeout(timeout, TimeUnit.MILLISECONDS).writeTimeout(timeout, TimeUnit.MILLISECONDS).build();
}
public static OkHttpClient noRedirect(long timeout) {
return client().newBuilder().connectTimeout(timeout, TimeUnit.MILLISECONDS).readTimeout(timeout, TimeUnit.MILLISECONDS).writeTimeout(timeout, TimeUnit.MILLISECONDS).followRedirects(false).followSslRedirects(false).build();
}
public static OkHttpClient client(boolean redirect, long timeout) {
return redirect ? client(timeout) : noRedirect(timeout);
}
public static String string(String url) {
if (!url.startsWith("http")) return "";
try (Response res = newCall(url).execute()) {
return res.body().string();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static String string(String url, Map<String, String> headers) {
if (!url.startsWith("http")) return "";
try (Response res = newCall(url, Headers.of(headers)).execute()) {
return res.body().string();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static byte[] bytes(String url) {
if (!url.startsWith("http")) return new byte[0];
try (Response res = newCall(url).execute()) {
return res.body().bytes();
} catch (Exception e) {
e.printStackTrace();
return new byte[0];
}
}
public static Call newCall(String url) {
return client().newCall(new Request.Builder().url(url).build());
}
public static Call newCall(String url, String tag) {
return client().newCall(new Request.Builder().url(url).tag(tag).build());
}
public static Call newCall(OkHttpClient client, String url) {
return client.newCall(new Request.Builder().url(url).build());
}
public static Call newCall(OkHttpClient client, String url, String tag) {
return client.newCall(new Request.Builder().url(url).tag(tag).build());
}
public static Call newCall(String url, Headers headers) {
return client().newCall(new Request.Builder().url(url).headers(headers).build());
}
public static Call newCall(String url, Headers headers, ArrayMap<String, String> params) {
return client().newCall(new Request.Builder().url(buildUrl(url, params)).headers(headers).build());
}
public static Call newCall(String url, Headers headers, RequestBody body) {
return client().newCall(new Request.Builder().url(url).headers(headers).post(body).build());
}
public static Call newCall(OkHttpClient client, String url, RequestBody body) {
return client.newCall(new Request.Builder().url(url).post(body).build());
}
public static void cancel(String tag) {
for (Call call : client().dispatcher().queuedCalls()) if (tag.equals(call.request().tag())) call.cancel();
for (Call call : client().dispatcher().runningCalls()) if (tag.equals(call.request().tag())) call.cancel();
}
public static void cancelAll() {
client().dispatcher().cancelAll();
}
public static FormBody toBody(ArrayMap<String, String> params) {
FormBody.Builder body = new FormBody.Builder();
for (Map.Entry<String, String> entry : params.entrySet()) body.add(entry.getKey(), entry.getValue());
return body.build();
}
private static HttpUrl buildUrl(String url, ArrayMap<String, String> params) {
HttpUrl.Builder builder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) builder.addQueryParameter(entry.getKey(), entry.getValue());
return builder.build();
}
private static OkHttpClient.Builder getBuilder() {
OkHttpClient.Builder builder = new OkHttpClient.Builder().cookieJar(OkCookieJar.get()).addInterceptor(requestInterceptor()).addInterceptor(authInterceptor()).addNetworkInterceptor(responseInterceptor()).connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS).readTimeout(TIMEOUT, TimeUnit.MILLISECONDS).writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS).dns(dns()).hostnameVerifier((hostname, session) -> true).sslSocketFactory(getSSLContext().getSocketFactory(), trustAllCertificates());
HttpLoggingInterceptor logging = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
builder.proxySelector(get().proxy ? selector() : defaultSelector);
//builder.addNetworkInterceptor(logging);
return builder;
}
private static SSLContext getSSLContext() {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{trustAllCertificates()}, new SecureRandom());
return context;
} catch (Throwable e) {
return null;
}
}
@SuppressLint({"TrustAllX509TrustManager", "CustomX509TrustManager"})
private static X509TrustManager trustAllCertificates() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}
}
@@ -0,0 +1,68 @@
package com.github.catvod.net;
import android.net.Uri;
import com.github.catvod.utils.Util;
import java.io.IOException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class OkProxySelector extends ProxySelector {
private final List<String> hosts;
private Proxy proxy;
public OkProxySelector() {
this.hosts = new ArrayList<>();
}
public synchronized void addAll(List<String> hosts) {
this.hosts.addAll(hosts);
}
public void clear() {
this.hosts.clear();
}
public void setProxy(String proxy) {
this.proxy = getProxy(proxy);
}
@Override
public List<Proxy> select(URI uri) {
if (proxy == null || hosts.isEmpty() || uri.getHost() == null || "127.0.0.1".equals(uri.getHost())) return List.of(Proxy.NO_PROXY);
for (String host : hosts) if (Util.containOrMatch(uri.getHost(), host)) return List.of(proxy);
return List.of(Proxy.NO_PROXY);
}
@Override
public void connectFailed(URI uri, SocketAddress socketAddress, IOException e) {
}
private Proxy getProxy(String proxy) {
Uri uri = Uri.parse(proxy);
String userInfo = uri.getUserInfo();
if (userInfo != null && userInfo.contains(":")) setAuthenticator(userInfo);
if (uri.getScheme() == null || uri.getHost() == null || uri.getPort() <= 0) return Proxy.NO_PROXY;
if (uri.getScheme().startsWith("http")) return new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(uri.getHost(), uri.getPort()));
if (uri.getScheme().startsWith("socks")) return new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(uri.getHost(), uri.getPort()));
return Proxy.NO_PROXY;
}
private void setAuthenticator(String userInfo) {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userInfo.split(":")[0], userInfo.split(":")[1].toCharArray());
}
});
}
}
@@ -0,0 +1,54 @@
package com.github.catvod.net.interceptor;
import androidx.annotation.NonNull;
import com.github.catvod.utils.Util;
import com.google.common.net.HttpHeaders;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class AuthInterceptor implements Interceptor {
private final ConcurrentHashMap<String, String> userMap;
public AuthInterceptor() {
userMap = new ConcurrentHashMap<>();
}
public void clear() {
userMap.clear();
}
@NonNull
@Override
public Response intercept(Chain chain) throws IOException {
Request request = check(chain.request());
Response response = chain.proceed(request);
if (response.code() != 401) return response;
String host = request.url().host();
String user = request.url().uri().getUserInfo();
String header = response.header(HttpHeaders.WWW_AUTHENTICATE);
if (user == null && userMap.containsKey(host)) user = userMap.get(host);
if (user == null) return response;
else response.close();
String auth = digest(header) ? Util.digest(user, header, request) : Util.basic(user);
return chain.proceed(request.newBuilder().header(HttpHeaders.AUTHORIZATION, auth).build());
}
private boolean digest(String header) {
return header != null && header.startsWith("Digest");
}
private Request check(Request request) {
URI uri = request.url().uri();
if (uri.getUserInfo() == null) return request;
userMap.put(request.url().host(), uri.getUserInfo());
return request.newBuilder().header(HttpHeaders.AUTHORIZATION, Util.basic(uri.getUserInfo())).build();
}
}
@@ -0,0 +1,43 @@
package com.github.catvod.net.interceptor;
import androidx.annotation.NonNull;
import com.github.catvod.net.OkCookieJar;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class RequestInterceptor implements Interceptor {
private final ConcurrentHashMap<String, String> authMap;
public RequestInterceptor() {
authMap = new ConcurrentHashMap<>();
}
public void clear() {
authMap.clear();
}
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
HttpUrl url = request.url();
checkAuth(url, builder);
OkCookieJar.sync(url, request);
return chain.proceed(builder.build());
}
private void checkAuth(HttpUrl url, Request.Builder builder) {
String auth = url.queryParameter("auth");
if (auth != null) authMap.put(url.host(), auth);
if (authMap.containsKey(url.host()) && auth == null) builder.url(url.newBuilder().addQueryParameter("auth", authMap.get(url.host())).build());
}
}
@@ -0,0 +1,92 @@
package com.github.catvod.net.interceptor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.github.catvod.utils.Json;
import com.google.common.net.HttpHeaders;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSource;
import okio.Okio;
public class ResponseInterceptor implements Interceptor {
private final ConcurrentHashMap<String, String> redirectMap;
private final ConcurrentHashMap<String, JsonObject> headerMap;
public ResponseInterceptor() {
headerMap = new ConcurrentHashMap<>();
redirectMap = new ConcurrentHashMap<>();
}
public synchronized void setHeaders(List<JsonElement> items) {
for (JsonElement item : items) {
JsonObject object = Json.safeObject(item);
headerMap.put(object.get("host").getAsString(), object.get("header").getAsJsonObject());
}
}
public void clear() {
headerMap.clear();
redirectMap.clear();
}
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = check(chain.request());
Response response = chain.proceed(request);
if ("deflate".equals(response.header(HttpHeaders.CONTENT_ENCODING))) return deflate(response);
if (response.code() == 406 && redirectMap.containsKey(request.url().toString())) return redirect(request, response);
if (response.code() == 302 && response.header(HttpHeaders.LOCATION) != null) redirectMap.put(response.header(HttpHeaders.LOCATION), request.url().toString());
return response;
}
private Request check(Request request) {
String host = request.url().host();
Request.Builder builder = request.newBuilder();
if (!headerMap.containsKey(host)) return request;
for (Map.Entry<String, JsonElement> entry : headerMap.get(host).entrySet()) builder.header(entry.getKey(), entry.getValue().getAsString());
return builder.build();
}
private Response redirect(Request request, Response response) {
return new Response.Builder().request(request).protocol(response.protocol()).code(302).message("Found").header(HttpHeaders.LOCATION, redirectMap.get(request.url().toString())).build();
}
private Response deflate(Response response) {
InflaterInputStream is = new InflaterInputStream(response.body().byteStream(), new Inflater(true));
return response.newBuilder().headers(response.headers()).body(new ResponseBody() {
@Nullable
@Override
public MediaType contentType() {
return response.body().contentType();
}
@Override
public long contentLength() {
return response.body().contentLength();
}
@NonNull
@Override
public BufferedSource source() {
return Okio.buffer(Okio.source(is));
}
}).build();
}
}
@@ -0,0 +1,24 @@
package com.github.catvod.utils;
import com.github.catvod.Init;
import java.io.InputStream;
public class Asset {
public static InputStream open(String fileName) {
try {
return Init.context().getAssets().open(fileName.replace("assets://", ""));
} catch (Exception e) {
return null;
}
}
public static String read(String fileName) {
try {
return Path.read(open(fileName));
} catch (Exception e) {
return "";
}
}
}
@@ -0,0 +1,18 @@
package com.github.catvod.utils;
public class Github {
public static final String URL = "https://github.com/Tosencen/XMBOX";
private static String getUrl(String path, String name) {
return URL + "/" + path + "/" + name;
}
public static String getJson(boolean dev, String name) {
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".json");
}
public static String getApk(boolean dev, String name) {
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".apk");
}
}
@@ -0,0 +1,96 @@
package com.github.catvod.utils;
import android.text.TextUtils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Json {
public static JsonElement parse(String json) {
try {
return JsonParser.parseString(json);
} catch (Throwable e) {
return new JsonParser().parse(json);
}
}
public static boolean isObj(String text) {
try {
if (TextUtils.isEmpty(text)) return false;
new JSONObject(text);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isArray(String text) {
try {
if (TextUtils.isEmpty(text)) return false;
new JSONArray(text);
return true;
} catch (Exception e) {
return false;
}
}
public static String safeString(JsonObject obj, String key) {
try {
return obj.getAsJsonPrimitive(key).getAsString().trim();
} catch (Exception e) {
return "";
}
}
public static List<String> safeListString(JsonObject obj, String key) {
List<String> result = new ArrayList<>();
if (!obj.has(key)) return result;
if (obj.get(key).isJsonObject()) result.add(safeString(obj, key));
else for (JsonElement opt : obj.getAsJsonArray(key)) result.add(opt.getAsString());
return result;
}
public static List<JsonElement> safeListElement(JsonObject obj, String key) {
List<JsonElement> result = new ArrayList<>();
if (!obj.has(key)) return result;
if (obj.get(key).isJsonObject()) result.add(obj.get(key).getAsJsonObject());
for (JsonElement opt : obj.getAsJsonArray(key)) result.add(opt.getAsJsonObject());
return result;
}
public static JsonObject safeObject(JsonElement element) {
try {
if (element.isJsonPrimitive()) element = parse(element.getAsJsonPrimitive().getAsString());
return element.getAsJsonObject();
} catch (Exception e) {
return new JsonObject();
}
}
public static Map<String, String> toMap(String json) {
return TextUtils.isEmpty(json) ? null : toMap(parse(json));
}
public static Map<String, String> toMap(JsonElement element) {
Map<String, String> map = new HashMap<>();
JsonObject object = safeObject(element);
for (Map.Entry<String, JsonElement> entry : object.entrySet()) map.put(entry.getKey(), safeString(object, entry.getKey()));
return map;
}
public static JsonObject toObject(Map<String, String> map) {
JsonObject object = new JsonObject();
for (String key : map.keySet()) object.addProperty(key, map.get(key));
return object;
}
}
@@ -0,0 +1,227 @@
package com.github.catvod.utils;
import android.os.Environment;
import android.util.Log;
import com.github.catvod.Init;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Path {
private static final String TAG = Path.class.getSimpleName();
private static File mkdir(File file) {
if (!file.exists()) file.mkdirs();
return file;
}
public static boolean exists(String path) {
return new File(path.replace("file://", "")).exists();
}
public static File root() {
return Environment.getExternalStorageDirectory();
}
public static File cache() {
return Init.context().getCacheDir();
}
public static File files() {
return Init.context().getFilesDir();
}
public static String rootPath() {
return root().getAbsolutePath();
}
public static File tv() {
return mkdir(new File(root() + File.separator + "TV"));
}
public static File so() {
return mkdir(new File(files() + File.separator + "so"));
}
public static File js() {
return mkdir(new File(cache() + File.separator + "js"));
}
public static File py() {
return mkdir(new File(cache() + File.separator + "py"));
}
public static File jar() {
return mkdir(new File(cache() + File.separator + "jar"));
}
public static File exo() {
return mkdir(new File(cache() + File.separator + "exo"));
}
public static File epg() {
return mkdir(new File(cache() + File.separator + "epg"));
}
public static File jpa() {
return mkdir(new File(cache() + File.separator + "jpa"));
}
public static File thunder() {
return mkdir(new File(cache() + File.separator + "thunder"));
}
public static File root(String name) {
return new File(root(), name);
}
public static File root(String child, String name) {
return new File(mkdir(new File(root(), child)), name);
}
public static File cache(String name) {
return new File(cache(), name);
}
public static File files(String name) {
return new File(files(), name);
}
public static File epg(String name) {
return new File(epg(), name);
}
public static File js(String name) {
return new File(js(), name);
}
public static File py(String name) {
return new File(py(), name);
}
public static File jar(String name) {
return new File(jar(), Util.md5(name).concat(".jar"));
}
public static File thunder(String name) {
return mkdir(new File(thunder(), name));
}
public static File local(String path) {
path = path.replace("file:/", "");
File file = new File(root(), path);
return file.exists() ? file : new File(path);
}
public static String read(File file) {
try {
return read(new FileInputStream(file));
} catch (Exception e) {
return "";
}
}
public static String read(InputStream is) {
try {
byte[] data = new byte[is.available()];
is.read(data);
is.close();
return new String(data, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
public static byte[] readToByte(File file) {
try {
FileInputStream is = new FileInputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
is.close();
return data;
} catch (IOException e) {
e.printStackTrace();
return new byte[0];
}
}
public static File write(File file, byte[] data) {
try {
FileOutputStream fos = new FileOutputStream(create(file));
fos.write(data);
fos.flush();
fos.close();
return file;
} catch (Exception e) {
e.printStackTrace();
return file;
}
}
public static void move(File in, File out) {
copy(in, out);
clear(in);
}
public static void copy(File in, File out) {
try {
copy(new FileInputStream(in), out);
} catch (Exception ignored) {
}
}
public static void copy(InputStream in, File out) {
try {
int read;
byte[] buffer = new byte[8192];
FileOutputStream fos = new FileOutputStream(create(out));
while ((read = in.read(buffer)) != -1) fos.write(buffer, 0, read);
fos.close();
in.close();
} catch (Exception ignored) {
}
}
public static void sort(File[] files) {
Arrays.sort(files, (o1, o2) -> {
if (o1.isDirectory() && o2.isFile()) return -1;
if (o1.isFile() && o2.isDirectory()) return 1;
return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
});
}
public static List<File> list(File dir) {
File[] files = dir.listFiles();
if (files != null) sort(files);
return files == null ? new ArrayList<>() : Arrays.asList(files);
}
public static void clear(File dir) {
if (dir == null) return;
if (dir.isDirectory()) for (File file : list(dir)) clear(file);
if (dir.delete()) Log.d(TAG, "Deleted:" + dir.getAbsolutePath());
}
public static File create(File file) {
try {
if (file.getParentFile() != null) mkdir(file.getParentFile());
if (!file.canWrite()) file.setWritable(true);
if (!file.exists()) file.createNewFile();
Shell.exec("chmod 777 " + file);
return file;
} catch (Exception e) {
e.printStackTrace();
return file;
}
}
}
@@ -0,0 +1,86 @@
package com.github.catvod.utils;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;
import com.github.catvod.Init;
import com.google.gson.internal.LazilyParsedNumber;
public class Prefers {
public static SharedPreferences getPrefers() {
return PreferenceManager.getDefaultSharedPreferences(Init.context());
}
public static String getString(String key) {
return getString(key, "");
}
public static String getString(String key, String defaultValue) {
try {
return getPrefers().getString(key, defaultValue);
} catch (Exception e) {
return defaultValue;
}
}
public static int getInt(String key) {
return getInt(key, 0);
}
public static int getInt(String key, int defaultValue) {
try {
return getPrefers().getInt(key, defaultValue);
} catch (Exception e) {
return defaultValue;
}
}
public static float getFloat(String key) {
return getFloat(key, 0f);
}
public static float getFloat(String key, float defaultValue) {
try {
return getPrefers().getFloat(key, defaultValue);
} catch (Exception e) {
return defaultValue;
}
}
public static boolean getBoolean(String key) {
return getBoolean(key, false);
}
public static boolean getBoolean(String key, boolean defaultValue) {
try {
return getPrefers().getBoolean(key, defaultValue);
} catch (Exception e) {
return defaultValue;
}
}
public static void put(String key, Object obj) {
if (obj == null) return;
if (obj instanceof String) {
getPrefers().edit().putString(key, (String) obj).apply();
} else if (obj instanceof Boolean) {
getPrefers().edit().putBoolean(key, (Boolean) obj).apply();
} else if (obj instanceof Float) {
getPrefers().edit().putFloat(key, (Float) obj).apply();
} else if (obj instanceof Integer) {
getPrefers().edit().putInt(key, (Integer) obj).apply();
} else if (obj instanceof Long) {
getPrefers().edit().putLong(key, (Long) obj).apply();
} else if (obj instanceof LazilyParsedNumber) {
LazilyParsedNumber number = (LazilyParsedNumber) obj;
if (number.toString().contains(".")) put(key, number.floatValue());
else put(key, number.intValue());
}
}
public static void remove(String key) {
getPrefers().edit().remove(key).apply();
}
}
@@ -0,0 +1,26 @@
package com.github.catvod.utils;
import com.orhanobut.logger.Logger;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Shell {
private static final String TAG = Shell.class.getSimpleName();
public static String exec(String command) {
try {
StringBuilder sb = new StringBuilder();
Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) sb.append(line).append("\n");
Logger.t(TAG).d("Shell command '%s' with exit code '%s'", command, p.waitFor());
return Util.substring(sb.toString());
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
@@ -0,0 +1,68 @@
package com.github.catvod.utils;
import android.text.TextUtils;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class Trans {
private final Map<Character, Character> s2t;
private final Map<Character, Character> t2s;
private final boolean trans;
private static class Loader {
static volatile Trans INSTANCE = new Trans();
}
private static Trans get() {
return Loader.INSTANCE;
}
private Trans() {
s2t = new HashMap<>();
t2s = new HashMap<>();
trans = "TW".equals(Locale.getDefault().getCountry());
if (trans) init();
}
private void init() {
char[] UTF8T = "萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳歷厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備復夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽黿鼂鼉鞀鼴齇齊齏齒齔齕齗齟齡齙齠齜齦齬齪齲齷龍龔龕龜誌谘範鬆嚐嘗鬨準鐘閒乾儘臟拚恆".toCharArray();
char[] UTF8S = "万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊强状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾鼋鼌鼍鼗鼹齄齐齑齿龀龁龂龃龄龅龆龇龈龉龊龋龌龙龚龛龟志咨范松尝尝闹准钟闲干尽脏拼恒".toCharArray();
for (int i = 0, n = UTF8T.length; i < n; ++i) {
s2t.put(UTF8S[i], UTF8T[i]);
t2s.put(UTF8T[i], UTF8S[i]);
}
}
private String get(String text, Map<Character, Character> map) {
if (TextUtils.isEmpty(text)) return text;
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; ++i) {
Character found = map.get(chars[i]);
if (found != null) chars[i] = found;
}
return String.valueOf(chars);
}
public static boolean pass() {
return !get().trans;
}
public static String s2t(String text) {
return text == null ? "" : s2t(pass(), text);
}
public static String t2s(String text) {
return text == null ? "" : t2s(pass(), text);
}
public static String s2t(boolean pass, String text) {
return pass ? text : get().get(text, get().s2t);
}
public static String t2s(boolean pass, String text) {
return pass ? text : get().get(text, get().t2s);
}
}
@@ -0,0 +1,231 @@
package com.github.catvod.utils;
import android.text.TextUtils;
import androidx.annotation.Nullable;
/**
* Utility methods for manipulating URIs.
*/
public final class UriUtil {
/**
* The length of arrays returned by {@link #getUriIndices(String)}.
*/
private static final int INDEX_COUNT = 4;
/**
* An index into an array returned by {@link #getUriIndices(String)}.
*
* <p>The value at this position in the array is the index of the ':' after the scheme. Equals -1
* if the URI is a relative reference (no scheme). The hier-part starts at (schemeColon + 1),
* including when the URI has no scheme.
*/
private static final int SCHEME_COLON = 0;
/**
* An index into an array returned by {@link #getUriIndices(String)}.
*
* <p>The value at this position in the array is the index of the path part. Equals (schemeColon +
* 1) if no authority part, (schemeColon + 3) if the authority part consists of just "//", and
* (query) if no path part. The characters starting at this index can be "//" only if the
* authority part is non-empty (in this case the double-slash means the first segment is empty).
*/
private static final int PATH = 1;
/**
* An index into an array returned by {@link #getUriIndices(String)}.
*
* <p>The value at this position in the array is the index of the query part, including the '?'
* before the query. Equals fragment if no query part, and (fragment - 1) if the query part is a
* single '?' with no data.
*/
private static final int QUERY = 2;
/**
* An index into an array returned by {@link #getUriIndices(String)}.
*
* <p>The value at this position in the array is the index of the fragment part, including the '#'
* before the fragment. Equal to the length of the URI if no fragment part, and (length - 1) if
* the fragment part is a single '#' with no data.
*/
private static final int FRAGMENT = 3;
/**
* Performs relative resolution of a {@code referenceUri} with respect to a {@code baseUri}.
*
* <p>The resolution is performed as specified by RFC-3986.
*
* @param baseUri The base URI.
* @param referenceUri The reference URI to resolve.
*/
public static String resolve(@Nullable String baseUri, @Nullable String referenceUri) {
StringBuilder uri = new StringBuilder();
// Map null onto empty string, to make the following logic simpler.
baseUri = baseUri == null ? "" : baseUri;
referenceUri = referenceUri == null ? "" : referenceUri;
int[] refIndices = getUriIndices(referenceUri);
if (refIndices[SCHEME_COLON] != -1) {
// The reference is absolute. The target Uri is the reference.
uri.append(referenceUri);
removeDotSegments(uri, refIndices[PATH], refIndices[QUERY]);
return uri.toString();
}
int[] baseIndices = getUriIndices(baseUri);
if (refIndices[FRAGMENT] == 0) {
// The reference is empty or contains just the fragment part, then the target Uri is the
// concatenation of the base Uri without its fragment, and the reference.
return uri.append(baseUri, 0, baseIndices[FRAGMENT]).append(referenceUri).toString();
}
if (refIndices[QUERY] == 0) {
// The reference starts with the query part. The target is the base up to (but excluding) the
// query, plus the reference.
return uri.append(baseUri, 0, baseIndices[QUERY]).append(referenceUri).toString();
}
if (refIndices[PATH] != 0) {
// The reference has authority. The target is the base scheme plus the reference.
int baseLimit = baseIndices[SCHEME_COLON] + 1;
uri.append(baseUri, 0, baseLimit).append(referenceUri);
return removeDotSegments(uri, baseLimit + refIndices[PATH], baseLimit + refIndices[QUERY]);
}
if (referenceUri.charAt(refIndices[PATH]) == '/') {
// The reference path is rooted. The target is the base scheme and authority (if any), plus
// the reference.
uri.append(baseUri, 0, baseIndices[PATH]).append(referenceUri);
return removeDotSegments(uri, baseIndices[PATH], baseIndices[PATH] + refIndices[QUERY]);
}
// The target Uri is the concatenation of the base Uri up to (but excluding) the last segment,
// and the reference. This can be split into 2 cases:
if (baseIndices[SCHEME_COLON] + 2 < baseIndices[PATH] && baseIndices[PATH] == baseIndices[QUERY]) {
// Case 1: The base hier-part is just the authority, with an empty path. An additional '/' is
// needed after the authority, before appending the reference.
uri.append(baseUri, 0, baseIndices[PATH]).append('/').append(referenceUri);
return removeDotSegments(uri, baseIndices[PATH], baseIndices[PATH] + refIndices[QUERY] + 1);
} else {
// Case 2: Otherwise, find the last '/' in the base hier-part and append the reference after
// it. If base hier-part has no '/', it could only mean that it is completely empty or
// contains only one segment, in which case the whole hier-part is excluded and the reference
// is appended right after the base scheme colon without an added '/'.
int lastSlashIndex = baseUri.lastIndexOf('/', baseIndices[QUERY] - 1);
int baseLimit = lastSlashIndex == -1 ? baseIndices[PATH] : lastSlashIndex + 1;
uri.append(baseUri, 0, baseLimit).append(referenceUri);
return removeDotSegments(uri, baseIndices[PATH], baseLimit + refIndices[QUERY]);
}
}
/**
* Removes dot segments from the path of a URI.
*
* @param uri A {@link StringBuilder} containing the URI.
* @param offset The index of the start of the path in {@code uri}.
* @param limit The limit (exclusive) of the path in {@code uri}.
*/
private static String removeDotSegments(StringBuilder uri, int offset, int limit) {
if (offset >= limit) {
// Nothing to do.
return uri.toString();
}
if (uri.charAt(offset) == '/') {
// If the path starts with a /, always retain it.
offset++;
}
// The first character of the current path segment.
int segmentStart = offset;
int i = offset;
while (i <= limit) {
int nextSegmentStart;
if (i == limit) {
nextSegmentStart = i;
} else if (uri.charAt(i) == '/') {
nextSegmentStart = i + 1;
} else {
i++;
continue;
}
// We've encountered the end of a segment or the end of the path. If the final segment was
// "." or "..", remove the appropriate segments of the path.
if (i == segmentStart + 1 && uri.charAt(segmentStart) == '.') {
// Given "abc/def/./ghi", remove "./" to get "abc/def/ghi".
uri.delete(segmentStart, nextSegmentStart);
limit -= nextSegmentStart - segmentStart;
i = segmentStart;
} else if (i == segmentStart + 2 && uri.charAt(segmentStart) == '.' && uri.charAt(segmentStart + 1) == '.') {
// Given "abc/def/../ghi", remove "def/../" to get "abc/ghi".
int prevSegmentStart = uri.lastIndexOf("/", segmentStart - 2) + 1;
int removeFrom = Math.max(prevSegmentStart, offset);
uri.delete(removeFrom, nextSegmentStart);
limit -= nextSegmentStart - removeFrom;
segmentStart = prevSegmentStart;
i = prevSegmentStart;
} else {
i++;
segmentStart = i;
}
}
return uri.toString();
}
/**
* Calculates indices of the constituent components of a URI.
*
* @param uriString The URI as a string.
* @return The corresponding indices.
*/
private static int[] getUriIndices(String uriString) {
int[] indices = new int[INDEX_COUNT];
if (TextUtils.isEmpty(uriString)) {
indices[SCHEME_COLON] = -1;
return indices;
}
// Determine outer structure from right to left.
// Uri = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
int length = uriString.length();
int fragmentIndex = uriString.indexOf('#');
if (fragmentIndex == -1) {
fragmentIndex = length;
}
int queryIndex = uriString.indexOf('?');
if (queryIndex == -1 || queryIndex > fragmentIndex) {
// '#' before '?': '?' is within the fragment.
queryIndex = fragmentIndex;
}
// Slashes are allowed only in hier-part so any colon after the first slash is part of the
// hier-part, not the scheme colon separator.
int schemeIndexLimit = uriString.indexOf('/');
if (schemeIndexLimit == -1 || schemeIndexLimit > queryIndex) {
schemeIndexLimit = queryIndex;
}
int schemeIndex = uriString.indexOf(':');
if (schemeIndex > schemeIndexLimit) {
// '/' before ':'
schemeIndex = -1;
}
// Determine hier-part structure: hier-part = "//" authority path / path
// This block can also cope with schemeIndex == -1.
boolean hasAuthority = schemeIndex + 2 < queryIndex && uriString.charAt(schemeIndex + 1) == '/' && uriString.charAt(schemeIndex + 2) == '/';
int pathIndex;
if (hasAuthority) {
pathIndex = uriString.indexOf('/', schemeIndex + 3); // find first '/' after "://"
if (pathIndex == -1 || pathIndex > queryIndex) {
pathIndex = queryIndex;
}
} else {
pathIndex = schemeIndex + 1;
}
indices[SCHEME_COLON] = schemeIndex;
indices[PATH] = pathIndex;
indices[QUERY] = queryIndex;
indices[FRAGMENT] = fragmentIndex;
return indices;
}
}
@@ -0,0 +1,190 @@
package com.github.catvod.utils;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Base64;
import com.github.catvod.Init;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.OkHttp;
import okhttp3.Request;
public class Util {
public static final String OKHTTP = "okhttp/" + OkHttp.VERSION;
public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
public static final int URL_SAFE = Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP;
public static String base64(String s) {
return base64(s.getBytes());
}
public static String base64(byte[] bytes) {
return base64(bytes, Base64.DEFAULT | Base64.NO_WRAP);
}
public static String base64(String s, int flags) {
return base64(s.getBytes(), flags);
}
public static String base64(byte[] bytes, int flags) {
return Base64.encodeToString(bytes, flags);
}
public static byte[] decode(String s) {
return decode(s, Base64.DEFAULT | Base64.NO_WRAP);
}
public static byte[] decode(String s, int flags) {
return Base64.decode(s, flags);
}
public static String basic(String userInfo) {
if (!userInfo.contains(":")) userInfo += ":";
return "Basic " + base64(userInfo, Base64.NO_WRAP);
}
public static byte[] hex2byte(String s) {
byte[] bytes = new byte[s.length() / 2];
for (int i = 0; i < bytes.length; i++) bytes[i] = Integer.valueOf(s.substring(i * 2, i * 2 + 2), 16).byteValue();
return bytes;
}
public static boolean equals(String name, String md5) {
return md5(Path.jar(name)).equalsIgnoreCase(md5);
}
public static String md5(String src) {
try {
if (TextUtils.isEmpty(src)) return "";
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = digest.digest(src.getBytes());
BigInteger no = new BigInteger(1, bytes);
StringBuilder sb = new StringBuilder(no.toString(16));
while (sb.length() < 32) sb.insert(0, "0");
return sb.toString().toLowerCase();
} catch (NoSuchAlgorithmException e) {
return "";
}
}
public static String md5(File file) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[4096];
int count;
while ((count = fis.read(bytes)) != -1) digest.update(bytes, 0, count);
fis.close();
StringBuilder sb = new StringBuilder();
for (byte b : digest.digest()) sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return sb.toString();
} catch (Exception e) {
return "";
}
}
public static boolean containOrMatch(String text, String regex) {
try {
return text.contains(regex) || text.matches(regex);
} catch (Exception e) {
return false;
}
}
public static String substring(String text) {
return substring(text, 1);
}
public static String substring(String text, int num) {
if (text != null && text.length() > num) return text.substring(0, text.length() - num);
return text;
}
public static String getIp() {
try {
String ip = getHostAddress("wlan");
if (!ip.isEmpty()) return ip;
ip = getHostAddress("eth");
if (!ip.isEmpty()) return ip;
ip = getWifiAddress();
if (!ip.isEmpty()) return ip;
return getHostAddress("");
} catch (Exception e) {
return "";
}
}
private static String getWifiAddress() {
WifiManager manager = (WifiManager) Init.context().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
int ip = manager.getConnectionInfo().getIpAddress();
return ip == 0 ? "" : String.format(Locale.getDefault(), "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF);
}
private static String getHostAddress(String keyword) throws SocketException {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface nif = en.nextElement();
if (!keyword.isEmpty() && !nif.getName().startsWith(keyword)) continue;
for (Enumeration<InetAddress> addresses = nif.getInetAddresses(); addresses.hasMoreElements(); ) {
InetAddress addr = addresses.nextElement();
if (!addr.isLoopbackAddress() && addr instanceof Inet4Address) {
return addr.getHostAddress();
}
}
}
return "";
}
public static String digest(String userInfo, String header, Request request) {
Map<String, String> params = parse(header.substring(7));
String[] parts = userInfo.split(":", 2);
String nc = "00000001";
String username = parts[0];
String password = parts.length > 1 ? parts[1] : "";
String qop = params.get("qop");
String realm = params.get("realm");
String nonce = params.get("nonce");
String opaque = params.get("opaque");
String uri = request.url().encodedPath();
String hash1 = Util.md5(username + ":" + realm + ":" + password);
String hash2 = Util.md5(request.method() + ":" + uri);
String cnonce = UUID.randomUUID().toString().replace("-", "");
String response = Util.md5(hash1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + hash2);
StringBuilder sb = new StringBuilder("Digest ");
sb.append("username=\"").append(username).append("\", ");
sb.append("realm=\"").append(realm).append("\", ");
sb.append("nonce=\"").append(nonce).append("\", ");
sb.append("uri=\"").append(uri).append("\", ");
sb.append("cnonce=\"").append(cnonce).append("\", ");
sb.append("nc=").append(nc).append(", ");
sb.append("qop=\"").append(qop).append("\", ");
sb.append("response=\"").append(response).append("\"");
if (opaque != null) sb.append(", opaque=\"").append(opaque).append("\"");
return sb.toString();
}
private static Map<String, String> parse(String header) {
Map<String, String> params = new HashMap<>();
Matcher matcher = Pattern.compile("(\\w+)=\"([^\"]*)\"").matcher(header);
while (matcher.find()) params.put(matcher.group(1), matcher.group(2));
return params;
}
}
@@ -0,0 +1,456 @@
package com.github.catvod.utils;
import java.util.HashMap;
import java.util.Map;
public class ZhuToPin {
private static final Map<String, String> map = new HashMap<>();
static {
map.put("ㄅㄧㄝ", "bie");
map.put("ㄅㄧㄠ", "biao");
map.put("ㄅㄧㄢ", "bian");
map.put("ㄅㄧㄣ", "bin");
map.put("ㄅㄧㄥ", "bing");
map.put("ㄅㄨ", "bu");
map.put("ㄅㄚ", "ba");
map.put("ㄅㄛ", "bo");
map.put("ㄅㄞ", "bai");
map.put("ㄅㄟ", "bei");
map.put("ㄅㄠ", "bao");
map.put("ㄅㄢ", "ban");
map.put("ㄅㄣ", "ben");
map.put("ㄅㄤ", "bang");
map.put("ㄅㄥ", "beng");
map.put("ㄅㄧ", "bi");
map.put("ㄆㄧㄝ", "pie");
map.put("ㄆㄧㄠ", "piao");
map.put("ㄆㄧㄢ", "pian");
map.put("ㄆㄧㄣ", "pin");
map.put("ㄆㄧㄥ", "ping");
map.put("ㄆㄨ", "pu");
map.put("ㄆㄚ", "pa");
map.put("ㄆㄛ", "po");
map.put("ㄆㄞ", "pai");
map.put("ㄆㄟ", "pei");
map.put("ㄆㄠ", "pao");
map.put("ㄆㄡ", "pou");
map.put("ㄆㄢ", "pan");
map.put("ㄆㄣ", "pen");
map.put("ㄆㄤ", "pang");
map.put("ㄆㄥ", "peng");
map.put("ㄆㄧ", "pi");
map.put("ㄇㄧㄝ", "mie");
map.put("ㄇㄧㄠ", "miao");
map.put("ㄇㄧㄡ", "miu");
map.put("ㄇㄧㄢ", "mian");
map.put("ㄇㄧㄣ", "min");
map.put("ㄇㄨ", "mu");
map.put("ㄇㄚ", "ma");
map.put("ㄇㄛ", "mo");
map.put("ㄇㄜ", "me");
map.put("ㄇㄞ", "mai");
map.put("ㄇㄟ", "mei");
map.put("ㄇㄠ", "mao");
map.put("ㄇㄡ", "mou");
map.put("ㄇㄢ", "man");
map.put("ㄇㄣ", "men");
map.put("ㄇㄤ", "mang");
map.put("ㄇㄥ", "meng");
map.put("ㄇㄧ", "mi");
map.put("ㄈㄚ", "fa");
map.put("ㄈㄛ", "fo");
map.put("ㄈㄜ", "fe");
map.put("ㄈㄟ", "fei");
map.put("ㄈㄡ", "fou");
map.put("ㄈㄢ", "fan");
map.put("ㄈㄣ", "fen");
map.put("ㄈㄤ", "fang");
map.put("ㄈㄥ", "feng");
map.put("ㄈㄨ", "fu");
map.put("ㄉㄧㄝ", "die");
map.put("ㄉㄧㄠ", "diao");
map.put("ㄉㄧㄡ", "diu");
map.put("ㄉㄧㄢ", "dian");
map.put("ㄉㄧㄥ", "ding");
map.put("ㄉㄨㄛ", "duo");
map.put("ㄉㄨㄟ", "dui");
map.put("ㄉㄨㄢ", "duan");
map.put("ㄉㄨㄣ", "dun");
map.put("ㄉㄚ", "da");
map.put("ㄉㄜ", "de");
map.put("ㄉㄞ", "dai");
map.put("ㄉㄟ", "dei");
map.put("ㄉㄠ", "dao");
map.put("ㄉㄡ", "dou");
map.put("ㄉㄢ", "dan");
map.put("ㄉㄣ", "den");
map.put("ㄉㄤ", "dang");
map.put("ㄉㄥ", "deng");
map.put("ㄉㄧ", "di");
map.put("ㄉㄨ", "du");
map.put("ㄊㄧㄝ", "tie");
map.put("ㄊㄧㄠ", "tiao");
map.put("ㄊㄧㄢ", "tian");
map.put("ㄊㄧㄥ", "ting");
map.put("ㄊㄨㄛ", "tuo");
map.put("ㄊㄨㄟ", "tui");
map.put("ㄊㄨㄢ", "tuan");
map.put("ㄊㄨㄣ", "tun");
map.put("ㄊㄚ", "ta");
map.put("ㄊㄜ", "te");
map.put("ㄊㄞ", "tai");
map.put("ㄊㄠ", "tao");
map.put("ㄊㄡ", "tou");
map.put("ㄊㄢ", "tan");
map.put("ㄊㄤ", "tang");
map.put("ㄊㄥ", "teng");
map.put("ㄊㄧ", "ti");
map.put("ㄊㄨ", "tu");
map.put("ㄋㄧㄝ", "nie");
map.put("ㄋㄧㄠ", "niao");
map.put("ㄋㄧㄡ", "niu");
map.put("ㄋㄧㄢ", "nian");
map.put("ㄋㄧㄣ", "nin");
map.put("ㄋㄧㄤ", "niang");
map.put("ㄋㄧㄥ", "ning");
map.put("ㄋㄨㄛ", "nuo");
map.put("ㄋㄨㄢ", "nuan");
map.put("ㄋㄨㄣ", "nun");
map.put("ㄋㄨㄥ", "nung");
map.put("ㄋㄚ", "na");
map.put("ㄋㄜ", "ne");
map.put("ㄋㄞ", "nai");
map.put("ㄋㄟ", "nei");
map.put("ㄋㄠ", "nao");
map.put("ㄋㄡ", "nou");
map.put("ㄋㄢ", "nan");
map.put("ㄋㄣ", "nen");
map.put("ㄋㄤ", "nang");
map.put("ㄋㄥ", "neng");
map.put("ㄋㄧ", "ni");
map.put("ㄋㄨ", "nu");
map.put("ㄌㄧㄚ", "lia");
map.put("ㄌㄧㄝ", "lie");
map.put("ㄌㄧㄠ", "liao");
map.put("ㄌㄧㄡ", "liu");
map.put("ㄌㄧㄢ", "lian");
map.put("ㄌㄧㄣ", "lin");
map.put("ㄌㄧㄤ", "liang");
map.put("ㄌㄧㄥ", "ling");
map.put("ㄌㄨㄛ", "luo");
map.put("ㄌㄨㄢ", "luan");
map.put("ㄌㄨㄣ", "lun");
map.put("ㄌㄨㄥ", "lung");
map.put("ㄌㄩ", "lv");
map.put("ㄌㄩㄝ", "lve");
map.put("ㄌㄚ", "la");
map.put("ㄌㄛ", "lo");
map.put("ㄌㄜ", "le");
map.put("ㄌㄞ", "lai");
map.put("ㄌㄟ", "lei");
map.put("ㄌㄠ", "lao");
map.put("ㄌㄡ", "lou");
map.put("ㄌㄢ", "lan");
map.put("ㄌㄣ", "len");
map.put("ㄌㄤ", "lang");
map.put("ㄌㄥ", "leng");
map.put("ㄌㄧ", "li");
map.put("ㄌㄨ", "lu");
map.put("ㄍㄨㄚ", "gua");
map.put("ㄍㄨㄛ", "guo");
map.put("ㄍㄨㄞ", "guai");
map.put("ㄍㄨㄟ", "gui");
map.put("ㄍㄨㄢ", "guan");
map.put("ㄍㄨㄣ", "gun");
map.put("ㄍㄨㄤ", "guang");
map.put("ㄍㄨㄥ", "gong");
map.put("ㄍㄚ", "ga");
map.put("ㄍㄜ", "ge");
map.put("ㄍㄞ", "gai");
map.put("ㄍㄟ", "gei");
map.put("ㄍㄠ", "gao");
map.put("ㄍㄡ", "gou");
map.put("ㄍㄢ", "gan");
map.put("ㄍㄣ", "gen");
map.put("ㄍㄤ", "gang");
map.put("ㄍㄥ", "geng");
map.put("ㄍㄨ", "gu");
map.put("ㄎㄨㄚ", "kua");
map.put("ㄎㄨㄛ", "kuo");
map.put("ㄎㄨㄞ", "kuai");
map.put("ㄎㄨㄟ", "kui");
map.put("ㄎㄨㄢ", "kuan");
map.put("ㄎㄨㄣ", "kun");
map.put("ㄎㄨㄤ", "kuang");
map.put("ㄎㄨㄥ", "kong");
map.put("ㄎㄚ", "ka");
map.put("ㄎㄜ", "ke");
map.put("ㄎㄞ", "kai");
map.put("ㄎㄠ", "kao");
map.put("ㄎㄡ", "kou");
map.put("ㄎㄢ", "kan");
map.put("ㄎㄣ", "ken");
map.put("ㄎㄤ", "kang");
map.put("ㄎㄥ", "keng");
map.put("ㄎㄨ", "ku");
map.put("ㄏㄨㄚ", "hua");
map.put("ㄏㄨㄛ", "huo");
map.put("ㄏㄨㄞ", "huai");
map.put("ㄏㄨㄟ", "huai");
map.put("ㄏㄨㄢ", "huan");
map.put("ㄏㄨㄣ", "hun");
map.put("ㄏㄨㄤ", "huang");
map.put("ㄏㄨㄥ", "hong");
map.put("ㄏㄚ", "ha");
map.put("ㄏㄜ", "he");
map.put("ㄏㄞ", "hai");
map.put("ㄏㄟ", "hei");
map.put("ㄏㄠ", "hao");
map.put("ㄏㄡ", "hou");
map.put("ㄏㄢ", "han");
map.put("ㄏㄣ", "hen");
map.put("ㄏㄤ", "hang");
map.put("ㄏㄥ", "heng");
map.put("ㄏㄨ", "hu");
map.put("ㄐㄧㄚ", "jia");
map.put("ㄐㄧㄝ", "jie");
map.put("ㄐㄧㄠ", "jiao");
map.put("ㄐㄧㄡ", "jiu");
map.put("ㄐㄧㄢ", "jian");
map.put("ㄐㄧㄣ", "jin");
map.put("ㄐㄧㄤ", "jiang");
map.put("ㄐㄧㄥ", "jing");
map.put("ㄐㄩㄝ", "jue");
map.put("ㄐㄩㄢ", "juan");
map.put("ㄐㄩㄣ", "jun");
map.put("ㄐㄩㄥ", "jiong");
map.put("ㄐㄧ", "ji");
map.put("ㄐㄩ", "ju");
map.put("ㄑㄧㄚ", "qia");
map.put("ㄑㄧㄝ", "qie");
map.put("ㄑㄧㄠ", "qiao");
map.put("ㄑㄧㄡ", "qiu");
map.put("ㄑㄧㄢ", "qian");
map.put("ㄑㄧㄣ", "qin");
map.put("ㄑㄧㄤ", "qiang");
map.put("ㄑㄧㄥ", "qing");
map.put("ㄑㄩㄝ", "que");
map.put("ㄑㄩㄢ", "quan");
map.put("ㄑㄩㄣ", "qun");
map.put("ㄑㄩㄥ", "qun");
map.put("ㄑㄧ", "qi");
map.put("ㄑㄩ", "qu");
map.put("ㄒㄧㄚ", "xia");
map.put("ㄒㄧㄝ", "xie");
map.put("ㄒㄧㄠ", "xiao");
map.put("ㄒㄧㄡ", "xiu");
map.put("ㄒㄧㄢ", "xian");
map.put("ㄒㄧㄣ", "xin");
map.put("ㄒㄧㄤ", "xiang");
map.put("ㄒㄧㄥ", "xing");
map.put("ㄒㄩㄝ", "xue");
map.put("ㄒㄩㄢ", "xuan");
map.put("ㄒㄩㄣ", "xun");
map.put("ㄒㄩㄥ", "xiong");
map.put("ㄒㄧ", "xi");
map.put("ㄒㄩ", "xu");
map.put("ㄓㄨㄚ", "zhua");
map.put("ㄓㄨㄛ", "zhuo");
map.put("ㄓㄨㄞ", "zhuai");
map.put("ㄓㄨㄟ", "zhuo");
map.put("ㄓㄨㄢ", "zhuan");
map.put("ㄓㄨㄣ", "zhuan");
map.put("ㄓㄨㄤ", "zhuan");
map.put("ㄓㄨㄥ", "zhong");
map.put("ㄓㄚ", "zha");
map.put("ㄓㄜ", "zhe");
map.put("ㄓㄞ", "zhai");
map.put("ㄓㄟ", "zhei");
map.put("ㄓㄠ", "zhao");
map.put("ㄓㄡ", "zhou");
map.put("ㄓㄢ", "zhan");
map.put("ㄓㄣ", "zhen");
map.put("ㄓㄤ", "zhang");
map.put("ㄓㄥ", "zheng");
map.put("ㄓㄨ", "zhu");
map.put("ㄔㄨㄚ", "chua");
map.put("ㄔㄨㄛ", "chuo");
map.put("ㄔㄨㄞ", "chuai");
map.put("ㄔㄨㄟ", "chui");
map.put("ㄔㄨㄢ", "chuan");
map.put("ㄔㄨㄣ", "chun");
map.put("ㄔㄨㄤ", "chuang");
map.put("ㄔㄨㄥ", "chong");
map.put("ㄔㄚ", "cha");
map.put("ㄔㄜ", "che");
map.put("ㄔㄞ", "chai");
map.put("ㄔㄠ", "chao");
map.put("ㄔㄡ", "chou");
map.put("ㄔㄢ", "chan");
map.put("ㄔㄣ", "chen");
map.put("ㄔㄤ", "chang");
map.put("ㄔㄥ", "cheng");
map.put("ㄔㄨ", "chu");
map.put("ㄕㄨㄚ", "shua");
map.put("ㄕㄨㄛ", "shuo");
map.put("ㄕㄨㄞ", "shuai");
map.put("ㄕㄨㄟ", "shui");
map.put("ㄕㄨㄢ", "shuan");
map.put("ㄕㄨㄣ", "shun");
map.put("ㄕㄨㄤ", "shuang");
map.put("ㄕㄚ", "sha");
map.put("ㄕㄜ", "she");
map.put("ㄕㄞ", "shai");
map.put("ㄕㄟ", "shei");
map.put("ㄕㄠ", "shao");
map.put("ㄕㄡ", "shou");
map.put("ㄕㄢ", "shan");
map.put("ㄕㄣ", "shen");
map.put("ㄕㄤ", "shang");
map.put("ㄕㄥ", "sheng");
map.put("ㄕㄨ", "shu");
map.put("ㄖㄨㄛ", "ruo");
map.put("ㄖㄨㄟ", "rui");
map.put("ㄖㄨㄢ", "ruan");
map.put("ㄖㄨㄣ", "run");
map.put("ㄖㄨㄥ", "rung");
map.put("ㄖㄜ", "re");
map.put("ㄖㄠ", "rao");
map.put("ㄖㄡ", "rou");
map.put("ㄖㄢ", "ran");
map.put("ㄖㄣ", "ren");
map.put("ㄖㄤ", "rang");
map.put("ㄖㄥ", "reng");
map.put("ㄖㄨ", "ru");
map.put("ㄗㄨㄛ", "zuo");
map.put("ㄗㄨㄟ", "zui");
map.put("ㄗㄨㄢ", "zuan");
map.put("ㄗㄨㄣ", "zun");
map.put("ㄗㄨㄥ", "zong");
map.put("ㄗㄚ", "za");
map.put("ㄗㄜ", "ze");
map.put("ㄗㄞ", "zai");
map.put("ㄗㄟ", "zei");
map.put("ㄗㄠ", "zao");
map.put("ㄗㄡ", "zou");
map.put("ㄗㄢ", "zan");
map.put("ㄗㄣ", "zen");
map.put("ㄗㄤ", "zang");
map.put("ㄗㄥ", "zeng");
map.put("ㄗㄨ", "zu");
map.put("ㄘㄨㄛ", "cuo");
map.put("ㄘㄨㄟ", "cui");
map.put("ㄘㄨㄢ", "cuan");
map.put("ㄘㄨㄣ", "cun");
map.put("ㄘㄨㄥ", "cong");
map.put("ㄘㄚ", "ca");
map.put("ㄘㄜ", "ce");
map.put("ㄘㄞ", "cai");
map.put("ㄘㄠ", "cao");
map.put("ㄘㄡ", "cou");
map.put("ㄘㄢ", "can");
map.put("ㄘㄣ", "cen");
map.put("ㄘㄤ", "cang");
map.put("ㄘㄥ", "ceng");
map.put("ㄘㄨ", "cu");
map.put("ㄙㄨㄛ", "suo");
map.put("ㄙㄨㄟ", "sui");
map.put("ㄙㄨㄢ", "suan");
map.put("ㄙㄨㄣ", "sun");
map.put("ㄙㄨㄥ", "song");
map.put("ㄙㄚ", "sa");
map.put("ㄙㄜ", "se");
map.put("ㄙㄞ", "sai");
map.put("ㄙㄟ", "sei");
map.put("ㄙㄠ", "sao");
map.put("ㄙㄡ", "sou");
map.put("ㄙㄢ", "san");
map.put("ㄙㄣ", "sen");
map.put("ㄙㄤ", "sang");
map.put("ㄙㄥ", "seng");
map.put("ㄙㄨ", "su");
map.put("ㄧㄚ", "ya");
map.put("ㄧㄛ", "yo");
map.put("ㄧㄝ", "ye");
map.put("ㄧㄞ", "yai");
map.put("ㄧㄠ", "yao");
map.put("ㄧㄡ", "you");
map.put("ㄧㄢ", "yan");
map.put("ㄧㄣ", "yin");
map.put("ㄧㄤ", "yang");
map.put("ㄧㄥ", "ying");
map.put("ㄨㄚ", "wa");
map.put("ㄨㄛ", "wo");
map.put("ㄨㄞ", "wai");
map.put("ㄨㄟ", "wei");
map.put("ㄨㄢ", "wan");
map.put("ㄨㄣ", "wen");
map.put("ㄨㄤ", "wang");
map.put("ㄨㄥ", "weng");
map.put("ㄩㄝ", "yue");
map.put("ㄩㄢ", "yuan");
map.put("ㄩㄣ", "yun");
map.put("ㄩㄥ", "yong");
map.put("", "b");
map.put("", "p");
map.put("", "m");
map.put("", "f");
map.put("", "d");
map.put("", "t");
map.put("", "n");
map.put("", "l");
map.put("", "g");
map.put("", "k");
map.put("", "h");
map.put("", "j");
map.put("", "q");
map.put("", "x");
map.put("", "zh");
map.put("", "ch");
map.put("", "sh");
map.put("", "r");
map.put("", "z");
map.put("", "c");
map.put("", "s");
map.put("", "yi");
map.put("", "wu");
map.put("", "yu");
map.put("", "a");
map.put("", "o");
map.put("", "e");
map.put("", "eh");
map.put("", "ai");
map.put("", "ei");
map.put("", "ao");
map.put("", "ou");
map.put("", "an");
map.put("", "en");
map.put("", "ang");
map.put("", "eng");
map.put("", "er");
}
public static String get(String text) {
StringBuilder sb = new StringBuilder();
String[] splits = text.split("");
if (splits.length > 1) findSplit(sb, splits);
else findSingle(sb, text);
return sb.toString();
}
private static void findSplit(StringBuilder sb, String[] splits) {
for (String split : splits) {
String pinyin = map.get(split);
sb.append(pinyin != null ? pinyin : split);
}
}
private static void findSingle(StringBuilder sb, String text) {
for (char chars : text.toCharArray()) {
String pinyin = map.get(String.valueOf(chars));
sb.append(pinyin != null ? pinyin : chars);
}
}
}
@@ -0,0 +1,17 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string-array name="doh_name">
<item>系统</item>
<item>腾讯</item>
<item>阿里</item>
<item>360</item>
</string-array>
<string-array name="doh_url">
<item />
<item>https://doh.pub/dns-query</item>
<item>https://dns.alidns.com/dns-query</item>
<item>https://doh.360.cn/dns-query</item>
</string-array>
</resources>
@@ -0,0 +1,17 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string-array name="doh_name">
<item>系統</item>
<item>騰訊</item>
<item>阿里</item>
<item>360</item>
</string-array>
<string-array name="doh_url">
<item />
<item>https://doh.pub/dns-query</item>
<item>https://dns.alidns.com/dns-query</item>
<item>https://doh.360.cn/dns-query</item>
</string-array>
</resources>
+17
View File
@@ -0,0 +1,17 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string-array name="doh_name">
<item>System</item>
<item>Tencent</item>
<item>Alibaba</item>
<item>360</item>
</string-array>
<string-array name="doh_url">
<item />
<item>https://doh.pub/dns-query</item>
<item>https://dns.alidns.com/dns-query</item>
<item>https://doh.360.cn/dns-query</item>
</string-array>
</resources>