Clean code (#2335)
This commit is contained in:
parent
7826b68645
commit
10804dfa7f
|
|
@ -13,6 +13,7 @@ import java.util.jar.JarFile;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
import sun.net.www.ParseUtil;
|
import sun.net.www.ParseUtil;
|
||||||
|
import sun.net.www.protocol.jar.Handler;
|
||||||
|
|
||||||
final class ClassPathURLStreamHandler extends Handler {
|
final class ClassPathURLStreamHandler extends Handler {
|
||||||
private final String fileUri;
|
private final String fileUri;
|
||||||
|
|
@ -41,7 +42,7 @@ final class ClassPathURLStreamHandler extends Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws IOException {
|
||||||
jarFile.close();
|
jarFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -23,10 +23,10 @@ import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
import hidden.ByteBufferDexClassLoader;
|
import hidden.ByteBufferDexClassLoader;
|
||||||
|
import sun.misc.CompoundEnumeration;
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
|
public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
|
||||||
|
|
@ -135,7 +135,12 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
|
||||||
protected URL findResource(String name) {
|
protected URL findResource(String name) {
|
||||||
try {
|
try {
|
||||||
var urlHandler = new ClassPathURLStreamHandler(apk);
|
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) {
|
} catch (IOException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -171,16 +176,8 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (apk == null) {
|
if (apk == null) return "LspModuleClassLoader[instantiating]";
|
||||||
return "LspModuleClassLoader[instantiating]";
|
return "LspModuleClassLoader[module=" + apk + ", " + super.toString() + "]";
|
||||||
}
|
|
||||||
var nativeLibraryDirsString = nativeLibraryDirs.stream()
|
|
||||||
.map(File::getPath)
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
return "LspModuleClassLoader[" +
|
|
||||||
"module=" + apk + ", " +
|
|
||||||
"nativeLibraryDirs=" + nativeLibraryDirsString + ", " +
|
|
||||||
super.toString() + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClassLoader loadApk(String apk,
|
public static ClassLoader loadApk(String apk,
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,8 @@
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package android.os;
|
package android.os;
|
||||||
|
|
||||||
public class ShellCallback implements Parcelable {
|
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
|
@Override
|
||||||
public ShellCallback createFromParcel(Parcel source) {
|
public ShellCallback createFromParcel(Parcel source) {
|
||||||
throw new IllegalArgumentException("STUB");
|
throw new IllegalArgumentException("STUB");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package org.lsposed.lspd.util;
|
package sun.misc;
|
||||||
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package sun.net.www.protocol.jar;
|
||||||
|
|
||||||
|
public abstract class Handler extends java.net.URLStreamHandler {
|
||||||
|
}
|
||||||
|
|
@ -89,6 +89,18 @@ public class ParasiticManagerHooker {
|
||||||
return managerPkgInfo;
|
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) {
|
private static void hookForManager(ILSPManagerService managerService) {
|
||||||
var managerApkHooker = new XC_MethodHook() {
|
var managerApkHooker = new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -111,7 +123,7 @@ public class ParasiticManagerHooker {
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam param) {
|
||||||
var pkgInfo = getManagerPkgInfo(null);
|
var pkgInfo = getManagerPkgInfo(null);
|
||||||
if (pkgInfo != null && XposedHelpers.getObjectField(param.thisObject, "mApplicationInfo") == pkgInfo.applicationInfo) {
|
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();
|
unhooks[0].unhook();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue