From 8c50808dc3c30e7966d4e892ccfd11130a44b50d Mon Sep 17 00:00:00 2001 From: FongMi Date: Thu, 26 Mar 2026 23:24:33 +0800 Subject: [PATCH] Clean catvod code --- .../main/java/com/github/catvod/bean/Doh.java | 15 +++- .../github/catvod/net/OkAuthenticator.java | 4 +- .../java/com/github/catvod/net/OkDns.java | 2 - .../java/com/github/catvod/net/OkHttp.java | 4 +- .../net/interceptor/AuthInterceptor.java | 6 +- .../java/com/github/catvod/utils/Auth.java | 83 +++++++++++++++++++ .../java/com/github/catvod/utils/Json.java | 4 +- .../java/com/github/catvod/utils/Prefers.java | 27 +++--- .../java/com/github/catvod/utils/Util.java | 47 ----------- 9 files changed, 117 insertions(+), 75 deletions(-) create mode 100644 catvod/src/main/java/com/github/catvod/utils/Auth.java diff --git a/catvod/src/main/java/com/github/catvod/bean/Doh.java b/catvod/src/main/java/com/github/catvod/bean/Doh.java index 8e8eb3bc7..dc30a9235 100644 --- a/catvod/src/main/java/com/github/catvod/bean/Doh.java +++ b/catvod/src/main/java/com/github/catvod/bean/Doh.java @@ -41,9 +41,13 @@ public class Doh { } public static List arrayFrom(JsonElement element) { - Type listType = new TypeToken>() {}.getType(); - List items = new Gson().fromJson(element, listType); - return items == null ? new ArrayList<>() : items; + try { + Type listType = new TypeToken>() {}.getType(); + List items = new Gson().fromJson(element, listType); + return items == null ? new ArrayList<>() : items; + } catch (Exception e) { + return new ArrayList<>(); + } } public Doh name(String name) { @@ -85,6 +89,11 @@ public class Doh { return getUrl().equals(it.getUrl()); } + @Override + public int hashCode() { + return getUrl().hashCode(); + } + @NonNull @Override public String toString() { diff --git a/catvod/src/main/java/com/github/catvod/net/OkAuthenticator.java b/catvod/src/main/java/com/github/catvod/net/OkAuthenticator.java index 567540ea0..ffaae20f2 100644 --- a/catvod/src/main/java/com/github/catvod/net/OkAuthenticator.java +++ b/catvod/src/main/java/com/github/catvod/net/OkAuthenticator.java @@ -6,7 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.github.catvod.bean.Proxy; -import com.github.catvod.utils.Util; +import com.github.catvod.utils.Auth; import com.google.common.net.HttpHeaders; import java.net.InetSocketAddress; @@ -49,7 +49,7 @@ public class OkAuthenticator implements Authenticator { if (url.contains(proxyHost)) { String userInfo = Uri.parse(url).getUserInfo(); if (userInfo != null) { - return response.request().newBuilder().header(HttpHeaders.PROXY_AUTHORIZATION, Util.basic(userInfo)).build(); + return response.request().newBuilder().header(HttpHeaders.PROXY_AUTHORIZATION, Auth.basic(userInfo)).build(); } } } diff --git a/catvod/src/main/java/com/github/catvod/net/OkDns.java b/catvod/src/main/java/com/github/catvod/net/OkDns.java index 5c4a3ad13..7163270df 100644 --- a/catvod/src/main/java/com/github/catvod/net/OkDns.java +++ b/catvod/src/main/java/com/github/catvod/net/OkDns.java @@ -7,14 +7,12 @@ import com.github.catvod.utils.Util; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import kotlin._Assertions; import okhttp3.Dns; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; diff --git a/catvod/src/main/java/com/github/catvod/net/OkHttp.java b/catvod/src/main/java/com/github/catvod/net/OkHttp.java index b8569c1f4..71f19b196 100644 --- a/catvod/src/main/java/com/github/catvod/net/OkHttp.java +++ b/catvod/src/main/java/com/github/catvod/net/OkHttp.java @@ -89,12 +89,12 @@ public class OkHttp { return get().selector = new OkProxySelector(); } - public static OkHttpClient client() { + public static synchronized OkHttpClient client() { if (get().client != null) return get().client; return get().client = getBuilder().build(); } - public static OkHttpClient player() { + public static synchronized OkHttpClient player() { if (get().player != null) return get().player; return get().player = getBuilder().build(); } diff --git a/catvod/src/main/java/com/github/catvod/net/interceptor/AuthInterceptor.java b/catvod/src/main/java/com/github/catvod/net/interceptor/AuthInterceptor.java index 5602e355b..c2a902e3f 100644 --- a/catvod/src/main/java/com/github/catvod/net/interceptor/AuthInterceptor.java +++ b/catvod/src/main/java/com/github/catvod/net/interceptor/AuthInterceptor.java @@ -2,7 +2,7 @@ package com.github.catvod.net.interceptor; import androidx.annotation.NonNull; -import com.github.catvod.utils.Util; +import com.github.catvod.utils.Auth; import com.google.common.net.HttpHeaders; import java.io.IOException; @@ -37,7 +37,7 @@ public class AuthInterceptor implements Interceptor { if (user == null) return response; response.close(); String header = response.header(HttpHeaders.WWW_AUTHENTICATE); - String auth = digest(header) ? Util.digest(user, header, request) : Util.basic(user); + String auth = digest(header) ? Auth.digest(user, header, request) : Auth.basic(user); return chain.proceed(request.newBuilder().header(HttpHeaders.AUTHORIZATION, auth).build()); } @@ -49,6 +49,6 @@ public class AuthInterceptor implements Interceptor { 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(); + return request.newBuilder().header(HttpHeaders.AUTHORIZATION, Auth.basic(uri.getUserInfo())).build(); } } diff --git a/catvod/src/main/java/com/github/catvod/utils/Auth.java b/catvod/src/main/java/com/github/catvod/utils/Auth.java new file mode 100644 index 000000000..969ecc815 --- /dev/null +++ b/catvod/src/main/java/com/github/catvod/utils/Auth.java @@ -0,0 +1,83 @@ +package com.github.catvod.utils; + +import android.util.Base64; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Request; + +public class Auth { + + private static final Pattern DIGEST = Pattern.compile("(\\w+)=\\s*([^,]+)\\s*"); + + public static String basic(String userInfo) { + if (!userInfo.contains(":")) userInfo += ":"; + return "Basic " + Base64.encodeToString(userInfo.getBytes(), Base64.NO_WRAP); + } + + public static String digest(String userInfo, String header, Request request) { + Map params = parseDigest(header.substring(7)); + String[] credentials = userInfo.split(":", 2); + String username = credentials[0]; + String password = credentials.length > 1 ? credentials[1] : ""; + String realm = params.getOrDefault("realm", ""); + String nonce = params.getOrDefault("nonce", ""); + String opaque = params.get("opaque"); + String uri = digestUri(request); + String qop = selectQop(params.get("qop")); + String nc = "00000001"; + String cnonce = newCnonce(); + String ha1 = Util.md5(username + ":" + realm + ":" + password); + String ha2 = Util.md5(request.method() + ":" + uri); + String response = digestResponse(ha1, ha2, nonce, nc, cnonce, qop); + return buildHeader(username, realm, nonce, uri, nc, cnonce, qop, response, opaque); + } + + private static String digestUri(Request request) { + String query = request.url().encodedQuery(); + String path = request.url().encodedPath(); + return query != null ? path + "?" + query : path; + } + + private static String digestResponse(String ha1, String ha2, String nonce, String nc, String cnonce, String qop) { + return qop.isEmpty() ? Util.md5(ha1 + ":" + nonce + ":" + ha2) : Util.md5(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2); + } + + private static String buildHeader(String username, String realm, String nonce, String uri, String nc, String cnonce, String qop, String response, String opaque) { + List fields = new ArrayList<>(); + fields.add("username=\"" + username + "\""); + fields.add("realm=\"" + realm + "\""); + fields.add("nonce=\"" + nonce + "\""); + fields.add("uri=\"" + uri + "\""); + boolean hasQop = !qop.isEmpty(); + if (hasQop) fields.add("cnonce=\"" + cnonce + "\""); + if (hasQop) fields.add("nc=" + nc); + if (hasQop) fields.add("qop=" + qop); + fields.add("response=\"" + response + "\""); + if (opaque != null) fields.add("opaque=\"" + opaque + "\""); + return "Digest " + String.join(", ", fields); + } + + private static String newCnonce() { + return UUID.randomUUID().toString().replace("-", ""); + } + + private static String selectQop(String qop) { + if (qop == null || qop.isEmpty()) return ""; + for (String option : qop.split(",")) if ("auth".equalsIgnoreCase(option.trim())) return "auth"; + return ""; + } + + private static Map parseDigest(String header) { + Map params = new HashMap<>(); + Matcher matcher = DIGEST.matcher(header.trim()); + while (matcher.find()) params.put(matcher.group(1), matcher.group(2).replaceAll("\"", "").trim()); + return params; + } +} diff --git a/catvod/src/main/java/com/github/catvod/utils/Json.java b/catvod/src/main/java/com/github/catvod/utils/Json.java index 9f246cb3c..780de22e7 100644 --- a/catvod/src/main/java/com/github/catvod/utils/Json.java +++ b/catvod/src/main/java/com/github/catvod/utils/Json.java @@ -20,7 +20,7 @@ public class Json { try { return JsonParser.parseString(json); } catch (Throwable e) { - return new JsonParser().parse(json); + return new JsonObject(); } } @@ -73,7 +73,7 @@ public class Json { List 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()); + else for (JsonElement opt : obj.getAsJsonArray(key)) result.add(opt.getAsJsonObject()); return result; } diff --git a/catvod/src/main/java/com/github/catvod/utils/Prefers.java b/catvod/src/main/java/com/github/catvod/utils/Prefers.java index 3927090f8..ff958f7fb 100644 --- a/catvod/src/main/java/com/github/catvod/utils/Prefers.java +++ b/catvod/src/main/java/com/github/catvod/utils/Prefers.java @@ -5,7 +5,6 @@ import android.content.SharedPreferences; import androidx.preference.PreferenceManager; import com.github.catvod.Init; -import com.google.gson.internal.LazilyParsedNumber; public class Prefers { @@ -63,19 +62,19 @@ public class Prefers { 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 number) { - if (number.toString().contains(".")) put(key, number.floatValue()); - else put(key, number.intValue()); + if (obj instanceof String val) { + getPrefers().edit().putString(key, val).apply(); + } else if (obj instanceof Boolean val) { + getPrefers().edit().putBoolean(key, val).apply(); + } else if (obj instanceof Float val) { + getPrefers().edit().putFloat(key, val).apply(); + } else if (obj instanceof Integer val) { + getPrefers().edit().putInt(key, val).apply(); + } else if (obj instanceof Long val) { + getPrefers().edit().putLong(key, val).apply(); + } else if (obj instanceof Number val) { + if (val.toString().contains(".")) put(key, val.floatValue()); + else put(key, val.intValue()); } } diff --git a/catvod/src/main/java/com/github/catvod/utils/Util.java b/catvod/src/main/java/com/github/catvod/utils/Util.java index 4a7566354..aec1b68ec 100644 --- a/catvod/src/main/java/com/github/catvod/utils/Util.java +++ b/catvod/src/main/java/com/github/catvod/utils/Util.java @@ -17,22 +17,15 @@ 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/138.0.0.0 Safari/537.36"; public static final int URL_SAFE = Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP; - public static final Pattern DIGEST = Pattern.compile("(\\w+)=\\s*([^,]+)\\s*"); public static String base64(String s) { return base64(s.getBytes()); @@ -58,11 +51,6 @@ public class Util { 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(); @@ -153,39 +141,4 @@ public class Util { } return ""; } - - public static String digest(String userInfo, String header, Request request) { - Map 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 parse(String header) { - Map params = new HashMap<>(); - Matcher matcher = DIGEST.matcher(header.trim()); - while (matcher.find()) params.put(matcher.group(1), matcher.group(2).replaceAll("\"", "").trim()); - return params; - } }