pull/144/head
jun 1 year ago
parent 3f6d787c00
commit c6e37a6f04
  1. 70
      app/src/main/java/com/github/catvod/crawler/JarLoader.java
  2. 4
      app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java
  3. 71
      app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java
  4. 2
      gradle.properties

@ -25,6 +25,7 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
@ -36,9 +37,9 @@ import dalvik.system.DexClassLoader;
import okhttp3.Response;
public class JarLoader {
private ConcurrentHashMap<String, DexClassLoader> classLoaders = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Method> proxyMethods = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Spider> spiders = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, DexClassLoader> classLoaders = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Method> proxyMethods = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Spider> spiders = new ConcurrentHashMap<>();
private volatile String recentJarKey = "";
/**
@ -54,53 +55,12 @@ public class JarLoader {
return loadClassLoader(cache, "main");
}
// private boolean loadClassLoader1(String jar, String key) {
// boolean success = false;
// try {
// File cacheDir = new File(App.getInstance().getCacheDir().getAbsolutePath() + "/catvod_csp");
// if (!cacheDir.exists())
// cacheDir.mkdirs();
// DexClassLoader classLoader = new DexClassLoader(jar, cacheDir.getAbsolutePath(), null, App.getInstance().getClassLoader());
// // make force wait here, some device async dex load
// int count = 0;
// do {
// try {
// Class classInit = classLoader.loadClass("com.github.catvod.spider.Init");
// if (classInit != null) {
// Method method = classInit.getMethod("init", Context.class);
// method.invoke(null, App.getInstance());
// System.out.println("自定义爬虫代码加载成功!");
// success = true;
// try {
// Class proxy = classLoader.loadClass("com.github.catvod.spider.Proxy");
// Method mth = proxy.getMethod("proxy", Map.class);
// proxyMethods.put(key, mth);
// } catch (Throwable th) {
//
// }
// break;
// }
// Thread.sleep(200);
// } catch (Throwable th) {
// th.printStackTrace();
// }
// count++;
// } while (count < 5);
//
// if (success) {
// classLoaders.put(key, classLoader);
// }
// } catch (Throwable th) {
// th.printStackTrace();
// }
// return success;
// }
private boolean loadClassLoader(String jar, String key) {
if (classLoaders.contains(key)) return true;
if (classLoaders.containsKey(key)) return true;
final String TAG = "JarLoader";
final File jarFile = new File(jar);
final AtomicBoolean success = new AtomicBoolean(false);
DexClassLoader classLoader = null;
DexClassLoader classLoader;
// 1. 前置校验
if (!validateJarFile(jarFile, TAG)) return false;
// 2. 准备缓存目录
@ -241,9 +201,10 @@ public class JarLoader {
private void cleanupResources(DexClassLoader loader, String tag) {
if (loader != null) {
try {
Field pathList = loader.getClass().getSuperclass().getDeclaredField("pathList");
Field pathList = Objects.requireNonNull(loader.getClass().getSuperclass()).getDeclaredField("pathList");
pathList.setAccessible(true);
Object dexPathList = pathList.get(loader);
assert dexPathList != null;
Field dexElements = dexPathList.getClass().getDeclaredField("dexElements");
dexElements.setAccessible(true);
dexElements.set(dexPathList, new Object[0]);
@ -261,8 +222,9 @@ public class JarLoader {
}
private DexClassLoader loadJarInternal(String jar, String md5, String key) {
if (classLoaders.contains(key))
if (classLoaders.containsKey(key)){
return classLoaders.get(key);
}
File cache = new File(App.getInstance().getFilesDir().getAbsolutePath() + "/" + key + ".jar");
if (!md5.isEmpty()) {
if (cache.exists() && MD5.getFileMd5(cache).equalsIgnoreCase(md5)) {
@ -272,6 +234,7 @@ public class JarLoader {
}
try {
Response response = OkGo.<File>get(jar).execute();
assert response.body() != null;
InputStream is = response.body().byteStream();
OutputStream os = new FileOutputStream(cache);
try {
@ -313,6 +276,7 @@ public class JarLoader {
if (spiders.containsKey(key))
return spiders.get(key);
DexClassLoader classLoader = null;
assert jarKey != null;
if (jarKey.equals("main"))
classLoader = classLoaders.get("main");
else {
@ -339,7 +303,8 @@ public class JarLoader {
DexClassLoader classLoader = classLoaders.get("main");
String clsKey = "Json" + key;
String hotClass = "com.github.catvod.parser." + clsKey;
Class jsonParserCls = classLoader.loadClass(hotClass);
assert classLoader != null;
Class<?> jsonParserCls = classLoader.loadClass(hotClass);
Method mth = jsonParserCls.getMethod("parse", LinkedHashMap.class, String.class);
return (JSONObject) mth.invoke(null, jxs, url);
} catch (Throwable th) {
@ -353,7 +318,8 @@ public class JarLoader {
DexClassLoader classLoader = classLoaders.get("main");
String clsKey = "Mix" + key;
String hotClass = "com.github.catvod.parser." + clsKey;
Class jsonParserCls = classLoader.loadClass(hotClass);
assert classLoader != null;
Class<?> jsonParserCls = classLoader.loadClass(hotClass);
Method mth = jsonParserCls.getMethod("parse", LinkedHashMap.class, String.class, String.class, String.class);
return (JSONObject) mth.invoke(null, jxs, name, flag, url);
} catch (Throwable th) {
@ -362,14 +328,14 @@ public class JarLoader {
return null;
}
public Object[] proxyInvoke(Map params) {
public Object[] proxyInvoke(Map<String,String> params) {
try {
Method proxyFun = proxyMethods.get(recentJarKey);
if (proxyFun != null) {
return (Object[]) proxyFun.invoke(null, params);
}
} catch (Throwable th) {
th.printStackTrace();
}
return null;
}

@ -414,7 +414,7 @@ public class ApiConfig {
SourceBean sb = new SourceBean();
String siteKey = obj.get("key").getAsString().trim();
sb.setKey(siteKey);
sb.setName(obj.get("name").getAsString().trim());
sb.setName(obj.has("name")?obj.get("name").getAsString().trim():siteKey);
sb.setType(obj.get("type").getAsInt());
sb.setApi(obj.get("api").getAsString().trim());
sb.setSearchable(DefaultConfig.safeJsonInt(obj, "searchable", 1));
@ -838,7 +838,7 @@ public class ApiConfig {
return jarLoader.getSpider(sourceBean.getKey(), sourceBean.getApi(), sourceBean.getExt(), sourceBean.getJar());
}
public Object[] proxyLocal(Map param) {
public Object[] proxyLocal(Map<String,String> param) {
return jarLoader.proxyInvoke(param);
}

@ -97,6 +97,32 @@ public class RemoteServer extends NanoHTTPD {
isStarted = false;
}
private Response getProxy(Object[] rs){
try {
int code = (int) rs[0];
String mime = (String) rs[1];
InputStream stream = rs[2] != null ? (InputStream) rs[2] : null;
Response response = NanoHTTPD.newChunkedResponse(
Response.Status.lookup(code),
mime,
stream
);
// 添加头部信息
if (rs.length >= 4 && rs[3] instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, String> mapHeader = (Map<String, String>) rs[3];
if(!mapHeader.isEmpty()){
for (String key : mapHeader.keySet()) {
response.addHeader(key, mapHeader.get(key));
}
}
}
return response;
} catch (Throwable th) {
return NanoHTTPD.newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "500");
}
}
@Override
public Response serve(IHTTPSession session) {
EventBus.getDefault().post(new ServerEvent(ServerEvent.SERVER_CONNECTION));
@ -115,52 +141,11 @@ public class RemoteServer extends NanoHTTPD {
Map<String, String> params = session.getParms();
if (params.containsKey("do")) {
Object[] rs = ApiConfig.get().proxyLocal(params);
try {
int code = (int) rs[0];
String mime = (String) rs[1];
InputStream stream = rs[2] != null ? (InputStream) rs[2] : null;
Response response = NanoHTTPD.newChunkedResponse(
NanoHTTPD.Response.Status.lookup(code),
mime,
stream
);
if(rs.length>=4){
HashMap<String, String> mapHeader = (HashMap<String, String>) rs[3];
if(!mapHeader.isEmpty()){
for (String key : mapHeader.keySet()) {
response.addHeader(key, mapHeader.get(key));
}
}
}
return response;
} catch (Throwable th) {
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "500");
}
return getProxy(rs);
}
if (params.containsKey("go")) {
Object[] rs = Proxy.proxy(params);
try {
assert rs != null;
int code = (int) rs[0];
String mime = (String) rs[1];
InputStream stream = rs[2] != null ? (InputStream) rs[2] : null;
Response response = NanoHTTPD.newChunkedResponse(
NanoHTTPD.Response.Status.lookup(code),
mime,
stream
);
if(rs.length>=4){
HashMap<String, String> mapHeader = (HashMap<String, String>) rs[3];
if(!mapHeader.isEmpty()){
for (String key : mapHeader.keySet()) {
response.addHeader(key, mapHeader.get(key));
}
}
}
return response;
} catch (Throwable th) {
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "500");
}
return getProxy(rs);
}
} else if (fileName.startsWith("/file/")) {
try {

@ -17,4 +17,4 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
IsDebug=true
org.gradle.jvmargs=-Xmx2048m --add-opens java.base/java.io=ALL-UNNAMED
#org.gradle.jvmargs=-Xmx2048m --add-opens java.base/java.io=ALL-UNNAMED

Loading…
Cancel
Save