Clean code (#2335)

This commit is contained in:
南宫雪珊 2023-01-16 22:04:00 +08:00 committed by GitHub
parent 7826b68645
commit 10804dfa7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 35 additions and 300 deletions

View File

@ -13,6 +13,7 @@ import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import sun.net.www.ParseUtil;
import sun.net.www.protocol.jar.Handler;
final class ClassPathURLStreamHandler extends Handler {
private final String fileUri;
@ -41,7 +42,7 @@ final class ClassPathURLStreamHandler extends Handler {
}
@Override
protected void finalize() throws Throwable {
protected void finalize() throws IOException {
jarFile.close();
}

View File

@ -1,192 +0,0 @@
package org.lsposed.lspd.util;
import java.net.MalformedURLException;
import java.net.URL;
public abstract class Handler extends java.net.URLStreamHandler {
private static final String separator = "!/";
private static int indexOfBangSlash(String spec) {
int indexOfBang = spec.length();
while ((indexOfBang = spec.lastIndexOf('!', indexOfBang)) != -1) {
if ((indexOfBang != (spec.length() - 1)) &&
(spec.charAt(indexOfBang + 1) == '/')) {
return indexOfBang + 1;
} else {
indexOfBang--;
}
}
return -1;
}
@Override
protected boolean sameFile(URL u1, URL u2) {
if (!u1.getProtocol().equals("jar") || !u2.getProtocol().equals("jar"))
return false;
String file1 = u1.getFile();
String file2 = u2.getFile();
int sep1 = file1.indexOf(separator);
int sep2 = file2.indexOf(separator);
if (sep1 == -1 || sep2 == -1) {
return super.sameFile(u1, u2);
}
String entry1 = file1.substring(sep1 + 2);
String entry2 = file2.substring(sep2 + 2);
if (!entry1.equals(entry2))
return false;
URL enclosedURL1, enclosedURL2;
try {
enclosedURL1 = new URL(file1.substring(0, sep1));
enclosedURL2 = new URL(file2.substring(0, sep2));
} catch (MalformedURLException unused) {
return super.sameFile(u1, u2);
}
return super.sameFile(enclosedURL1, enclosedURL2);
}
@Override
protected int hashCode(URL u) {
int h = 0;
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
String file = u.getFile();
int sep = file.indexOf(separator);
if (sep == -1)
return h + file.hashCode();
URL enclosedURL;
String fileWithoutEntry = file.substring(0, sep);
try {
enclosedURL = new URL(fileWithoutEntry);
h += enclosedURL.hashCode();
} catch (MalformedURLException unused) {
h += fileWithoutEntry.hashCode();
}
String entry = file.substring(sep + 2);
h += entry.hashCode();
return h;
}
@Override
@SuppressWarnings("deprecation")
protected void parseURL(URL url, String spec, int start, int limit) {
String file = null;
String ref = null;
// first figure out if there is an anchor
int refPos = spec.indexOf('#', limit);
boolean refOnly = refPos == start;
if (refPos > -1) {
ref = spec.substring(refPos + 1);
if (refOnly) {
file = url.getFile();
}
}
// then figure out if the spec is
// 1. absolute (jar:)
// 2. relative (i.e. url + foo/bar/baz.ext)
// 3. anchor-only (i.e. url + #foo), which we already did (refOnly)
boolean absoluteSpec = false;
if (spec.length() >= 4) {
absoluteSpec = spec.substring(0, 4).equalsIgnoreCase("jar:");
}
spec = spec.substring(start, limit);
if (absoluteSpec) {
file = parseAbsoluteSpec(spec);
} else if (!refOnly) {
file = parseContextSpec(url, spec);
// Canonize the result after the bangslash
int bangSlash = indexOfBangSlash(file);
String toBangSlash = file.substring(0, bangSlash);
String afterBangSlash = file.substring(bangSlash);
afterBangSlash = canonizeString(afterBangSlash);
file = toBangSlash + afterBangSlash;
}
setURL(url, "jar", "", -1, file, ref);
}
private String canonizeString(String file) {
int i;
int lim;
// Remove embedded /../
while ((i = file.indexOf("/../")) >= 0) {
if ((lim = file.lastIndexOf('/', i - 1)) >= 0) {
file = file.substring(0, lim) + file.substring(i + 3);
} else {
file = file.substring(i + 3);
}
}
// Remove embedded /./
while ((i = file.indexOf("/./")) >= 0) {
file = file.substring(0, i) + file.substring(i + 2);
}
// Remove trailing ..
while (file.endsWith("/..")) {
i = file.indexOf("/..");
if ((lim = file.lastIndexOf('/', i - 1)) >= 0) {
file = file.substring(0, lim + 1);
} else {
file = file.substring(0, i);
}
}
// Remove trailing .
if (file.endsWith("/."))
file = file.substring(0, file.length() - 1);
return file;
}
private String parseAbsoluteSpec(String spec) {
int index;
// check for !/
if ((index = indexOfBangSlash(spec)) == -1) {
throw new NullPointerException("no !/ in spec");
}
// test the inner URL
try {
String innerSpec = spec.substring(0, index - 1);
new URL(innerSpec);
} catch (MalformedURLException e) {
throw new NullPointerException("invalid url: " +
spec + " (" + e + ")");
}
return spec;
}
private String parseContextSpec(URL url, String spec) {
String ctxFile = url.getFile();
// if the spec begins with /, chop up the jar back !/
if (spec.startsWith("/")) {
int bangSlash = indexOfBangSlash(ctxFile);
if (bangSlash == -1) {
throw new NullPointerException("malformed " + "context url:" + url + ": no !/");
}
ctxFile = ctxFile.substring(0, bangSlash);
}
if (!ctxFile.endsWith("/") && (!spec.startsWith("/"))) {
// chop up the last component
int lastSlash = ctxFile.lastIndexOf('/');
if (lastSlash == -1) {
throw new NullPointerException("malformed " + "context url:" + url);
}
ctxFile = ctxFile.substring(0, lastSlash + 1);
}
return (ctxFile + spec);
}
}

View File

@ -1,40 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package org.lsposed.lspd.util;
import android.os.IBinder;
import de.robv.android.xposed.XposedHelpers;
public class InstallerVerifier {
public static void sendBinderToManager(final ClassLoader classLoader, IBinder binder) {
try {
var clazz = XposedHelpers.findClass("org.lsposed.manager.Constants", classLoader);
var ok = (boolean) XposedHelpers.callStaticMethod(clazz, "setBinder",
new Class[]{IBinder.class}, binder);
if (ok) return;
throw new RuntimeException("setBinder: " + false);
} catch (Throwable t) {
Utils.logW("Could not send binder to LSPosed Manager", t);
}
}
}

View File

@ -23,10 +23,10 @@ import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import hidden.ByteBufferDexClassLoader;
import sun.misc.CompoundEnumeration;
@SuppressWarnings("ConstantConditions")
public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
@ -135,7 +135,12 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
protected URL findResource(String name) {
try {
var urlHandler = new ClassPathURLStreamHandler(apk);
return urlHandler.getEntryUrlOrNull(name);
var url = urlHandler.getEntryUrlOrNull(name);
if (url == null) {
// noinspection FinalizeCalledExplicitly
urlHandler.finalize();
}
return url;
} catch (IOException e) {
return null;
}
@ -171,16 +176,8 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
@NonNull
@Override
public String toString() {
if (apk == null) {
return "LspModuleClassLoader[instantiating]";
}
var nativeLibraryDirsString = nativeLibraryDirs.stream()
.map(File::getPath)
.collect(Collectors.joining(", "));
return "LspModuleClassLoader[" +
"module=" + apk + ", " +
"nativeLibraryDirs=" + nativeLibraryDirsString + ", " +
super.toString() + "]";
if (apk == null) return "LspModuleClassLoader[instantiating]";
return "LspModuleClassLoader[module=" + apk + ", " + super.toString() + "]";
}
public static ClassLoader loadApk(String apk,

View File

@ -20,3 +20,8 @@
plugins {
`java-library`
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@ -1,24 +0,0 @@
package android.content.pm;
import android.content.IntentSender;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
public interface IShortcutService extends IInterface {
boolean isRequestPinItemSupported(int user, int requestType) throws RemoteException;
ParceledListSlice<ShortcutInfo> getShortcuts(String packageName, int matchFlags, int userId) throws RemoteException;
ParceledListSlice<ShortcutInfo> getPinnedShortcuts(String packageName, int userId) throws RemoteException;
boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) throws RemoteException;
boolean updateShortcuts(String packageName, ParceledListSlice<ShortcutInfo> shortcuts, int userId) throws RemoteException;
abstract class Stub extends Binder implements IShortcutService {
public static IShortcutService asInterface(IBinder obj) {
throw new RuntimeException("STUB");
}
}
}

View File

@ -1,28 +0,0 @@
package android.content.pm;
import android.os.Parcel;
import android.os.Parcelable;
public class ShortcutInfo implements Parcelable {
public static final Creator<ShortcutInfo> CREATOR = new Creator<>() {
@Override
public ShortcutInfo createFromParcel(Parcel in) {
throw new IllegalArgumentException("STUB");
}
@Override
public ShortcutInfo[] newArray(int size) {
throw new IllegalArgumentException("STUB");
}
};
@Override
public void writeToParcel(Parcel dest, int flags) {
throw new IllegalArgumentException("STUB");
}
@Override
public int describeContents() {
throw new IllegalArgumentException("STUB");
}
}

View File

@ -1,7 +1,7 @@
package android.os;
public class ShellCallback implements Parcelable {
public static final Parcelable.Creator<ShellCallback> CREATOR = new Creator<>() {
public static final Parcelable.Creator<ShellCallback> CREATOR = new Creator<ShellCallback>() {
@Override
public ShellCallback createFromParcel(Parcel source) {
throw new IllegalArgumentException("STUB");

View File

@ -1,4 +1,4 @@
package org.lsposed.lspd.util;
package sun.misc;
import java.util.Enumeration;
import java.util.NoSuchElementException;

View File

@ -0,0 +1,4 @@
package sun.net.www.protocol.jar;
public abstract class Handler extends java.net.URLStreamHandler {
}

View File

@ -89,6 +89,18 @@ public class ParasiticManagerHooker {
return managerPkgInfo;
}
private static void sendBinderToManager(final ClassLoader classLoader, IBinder binder) {
try {
var clazz = XposedHelpers.findClass("org.lsposed.manager.Constants", classLoader);
var ok = (boolean) XposedHelpers.callStaticMethod(clazz, "setBinder",
new Class[]{IBinder.class}, binder);
if (ok) return;
throw new RuntimeException("setBinder: " + false);
} catch (Throwable t) {
Utils.logW("Could not send binder to LSPosed Manager", t);
}
}
private static void hookForManager(ILSPManagerService managerService) {
var managerApkHooker = new XC_MethodHook() {
@Override
@ -111,7 +123,7 @@ public class ParasiticManagerHooker {
protected void afterHookedMethod(MethodHookParam param) {
var pkgInfo = getManagerPkgInfo(null);
if (pkgInfo != null && XposedHelpers.getObjectField(param.thisObject, "mApplicationInfo") == pkgInfo.applicationInfo) {
InstallerVerifier.sendBinderToManager((ClassLoader) param.getResult(), managerService.asBinder());
sendBinderToManager((ClassLoader) param.getResult(), managerService.asBinder());
unhooks[0].unhook();
}
}