mirror of
https://github.com/ispointer/RePairip.git
synced 2026-09-28 20:05:09 +02:00
🍺
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
@@ -0,0 +1,31 @@
|
||||
plugins {
|
||||
java
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
archiveFileName.set("RePairip.jar")
|
||||
manifest {
|
||||
attributes["Main-Class"] = "com.antik.Main"
|
||||
}
|
||||
}
|
||||
|
||||
// Make the 'build' and 'assemble' tasks produce the shadow jar
|
||||
tasks.assemble {
|
||||
dependsOn(tasks.shadowJar)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.dexlib2)
|
||||
implementation(libs.reandroid.arsclib)
|
||||
implementation(libs.guava)
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.antik;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class AntikUtils {
|
||||
public static String get_out(File i, String n) {
|
||||
File p = i.getParentFile();
|
||||
if (p == null) {
|
||||
return n;
|
||||
}
|
||||
return new File(p, n).getPath();
|
||||
}
|
||||
|
||||
public static void ex_apks(File zf, File dd) throws Exception {
|
||||
try (ZipFile z = new ZipFile(zf)) {
|
||||
Enumeration<? extends ZipEntry> es = z.entries();
|
||||
while (es.hasMoreElements()) {
|
||||
ZipEntry e = es.nextElement();
|
||||
if (e.getName().endsWith(".apk")) {
|
||||
File of = new File(dd, new File(e.getName()).getName());
|
||||
try (InputStream i = z.getInputStream(e);
|
||||
FileOutputStream fo = new FileOutputStream(of)) {
|
||||
byte[] b = new byte[8192];
|
||||
int l;
|
||||
while ((l = i.read(b)) > 0) {
|
||||
fo.write(b, 0, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void del_dir(File d) {
|
||||
File[] fs = d.listFiles();
|
||||
if (fs != null) {
|
||||
for (File f : fs) {
|
||||
if (f.isDirectory()) {
|
||||
del_dir(f);
|
||||
} else {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
d.delete();
|
||||
}
|
||||
|
||||
public static void banner() {
|
||||
System.out.println("░░░░░█▀▄░█▀▀░█░█░█▀▄░█▀▀░█░█░░░░░");
|
||||
System.out.println("░░░░░█▀▄░█▀▀░▀▄▀░█░█░█▀▀░▄▀▄░░░░░");
|
||||
System.out.println("░░░░░▀░▀░▀▀▀░░▀░░▀▀░░▀▀▀░▀░▀░░░░░");
|
||||
System.out.println("░█▀▄░█▀▀░█▀█░█▀█░▀█▀░█▀▄░▀█▀░█▀█░");
|
||||
System.out.println("░█▀▄░█▀▀░█▀▀░█▀█░░█░░█▀▄░░█░░█▀▀░");
|
||||
System.out.println("░▀░▀░▀▀▀░▀░░░▀░▀░▀▀▀░▀░▀░▀▀▀░▀░░░");
|
||||
System.out.println("Version : 1.3.10");
|
||||
System.out.println("--------------------------------------");
|
||||
System.out.println("Dev : Antik (Fox)");
|
||||
System.out.println("Channel : https://t.me/RevDex");
|
||||
System.out.println("GitHub : https://github.com/ispointer/RePairip");
|
||||
System.out.println("--------------------------------------");
|
||||
}
|
||||
|
||||
public static void help() {
|
||||
System.out.println("java -jar antik.jar -i <input.apks>");
|
||||
}
|
||||
|
||||
public static void progress(int c, int t) {
|
||||
if (t <= 0) t = 1;
|
||||
int w = 30;
|
||||
float p = (float) c / t;
|
||||
if (p > 1.0f) p = 1.0f;
|
||||
int f = (int) (p * w);
|
||||
|
||||
StringBuilder s = new StringBuilder("\r[");
|
||||
for (int i = 0; i < f; i++) {
|
||||
s.append("#");
|
||||
}
|
||||
for (int i = f; i < w; i++) {
|
||||
s.append("-");
|
||||
}
|
||||
s.append("] ");
|
||||
s.append(String.format("%d%%", (int) (p * 100)));
|
||||
System.out.print(s.toString());
|
||||
System.out.flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.antik;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CrcPatcher {
|
||||
public static void patch(File s_a, File t_a) throws IOException {
|
||||
|
||||
Map<String, long[]> s_es = new LinkedHashMap<String, long[]>();
|
||||
Map<String, long[]> t_es = new LinkedHashMap<String, long[]>();
|
||||
|
||||
File[] f_ls = {s_a, t_a};
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
File f = f_ls[i];
|
||||
Map<String, long[]> cur = (i == 0) ? s_es : t_es;
|
||||
|
||||
try (RandomAccessFile rf = new RandomAccessFile(f, "r")) {
|
||||
FileChannel ch = rf.getChannel();
|
||||
long sz = ch.size();
|
||||
int t_sz = (int) Math.min(65558L, sz);
|
||||
ByteBuffer t_bf = ByteBuffer.allocate(t_sz).order(ByteOrder.LITTLE_ENDIAN);
|
||||
ch.read(t_bf, sz - t_sz);
|
||||
t_bf.flip();
|
||||
|
||||
Long eo = null;
|
||||
for (int j = t_bf.limit() - 4; j >= 0; j--) {
|
||||
if (t_bf.getInt(j) == 0x06054b50) {
|
||||
eo = (sz - t_sz) + (long)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eo != null) {
|
||||
ByteBuffer eb = ByteBuffer.allocate(22).order(ByteOrder.LITTLE_ENDIAN);
|
||||
ch.read(eb, eo);
|
||||
eb.flip();
|
||||
long cds = eb.getInt(12) & 0xFFFFFFFFL;
|
||||
long cdo = eb.getInt(16) & 0xFFFFFFFFL;
|
||||
|
||||
ByteBuffer hb = ByteBuffer.allocate(46).order(ByteOrder.LITTLE_ENDIAN);
|
||||
long co = cdo;
|
||||
long e_o = cdo + cds;
|
||||
while (co < e_o) {
|
||||
hb.clear();
|
||||
ch.read(hb, co);
|
||||
hb.flip();
|
||||
if (hb.remaining() < 46 || hb.getInt() != 0x02014b50) {
|
||||
break;
|
||||
}
|
||||
|
||||
long co_c = co + 16;
|
||||
hb.position(16);
|
||||
int c = hb.getInt();
|
||||
|
||||
hb.position(28);
|
||||
int nl = hb.getShort() & 0xFFFF;
|
||||
int el = hb.getShort() & 0xFFFF;
|
||||
int cl = hb.getShort() & 0xFFFF;
|
||||
|
||||
hb.position(42);
|
||||
long lho = hb.getInt() & 0xFFFFFFFFL;
|
||||
|
||||
byte[] nb = new byte[nl];
|
||||
ByteBuffer nbf = ByteBuffer.wrap(nb);
|
||||
ch.read(nbf, co + 46);
|
||||
String n = new String(nb, StandardCharsets.UTF_8);
|
||||
|
||||
if (n.startsWith("classes") && n.endsWith(".dex")) {
|
||||
ByteBuffer lhb = ByteBuffer.allocate(30).order(ByteOrder.LITTLE_ENDIAN);
|
||||
ch.read(lhb, lho);
|
||||
lhb.flip();
|
||||
if (lhb.remaining() >= 30 && lhb.getInt() == 0x04034b50) {
|
||||
cur.put(n, new long[]{co_c, lho + 14, (long) c});
|
||||
}
|
||||
}
|
||||
|
||||
co += 46L + nl + el + cl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_es.isEmpty() || t_es.isEmpty()) {
|
||||
System.out.println("[CRC] No dex files found in apk");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean mod = false;
|
||||
try (RandomAccessFile rf = new RandomAccessFile(t_a, "rw");
|
||||
FileChannel ch = rf.getChannel()) {
|
||||
|
||||
ByteBuffer b = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
Iterator<Map.Entry<String, long[]>> it = s_es.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, long[]> e = it.next();
|
||||
|
||||
long[] se = e.getValue();
|
||||
long[] te = t_es.get(e.getKey());
|
||||
if (te != null && te[2] != se[2]) {
|
||||
int n_c = (int) se[2];
|
||||
b.clear();
|
||||
b.putInt(n_c);
|
||||
b.flip();
|
||||
ch.write(b, te[0]);
|
||||
b.clear();
|
||||
b.putInt(n_c);
|
||||
b.flip();
|
||||
ch.write(b, te[1]);
|
||||
|
||||
mod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
ch.force(true);
|
||||
System.out.println("[CRC] Patched dex CRC values from merged APK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
package com.antik;
|
||||
|
||||
import com.reandroid.apk.ApkModule;
|
||||
import com.reandroid.archive.ByteInputSource;
|
||||
import com.reandroid.archive.InputSource;
|
||||
import org.jf.dexlib2.DexFileFactory;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.dexlib2.iface.Method;
|
||||
import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.immutable.ImmutableClassDef;
|
||||
import org.jf.dexlib2.immutable.ImmutableMethod;
|
||||
import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction11n;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction11x;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction21c;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
|
||||
import org.jf.dexlib2.writer.io.MemoryDataStore;
|
||||
import org.jf.dexlib2.writer.pool.DexPool;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
|
||||
public class DexPatcher {
|
||||
public static void patch(ApkModule m) throws Exception {
|
||||
List<String> dx_ns = new ArrayList<String>();
|
||||
for (InputSource s : m.getInputSources()) {
|
||||
if (s.getName().endsWith(".dex")) {
|
||||
dx_ns.add(s.getName());
|
||||
}
|
||||
}
|
||||
|
||||
List<ClassDef> l_cds = new ArrayList<ClassDef>();
|
||||
Set<String> a_ts = new HashSet<String>();
|
||||
String pkg = "unknown";
|
||||
try {
|
||||
pkg = m.getPackageName();
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
try (InputStream i = Main.class.getResourceAsStream("/log.dex")) {
|
||||
if (i != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
while ((len = i.read(buf)) != -1) {
|
||||
baos.write(buf, 0, len);
|
||||
}
|
||||
byte[] l_bs = baos.toByteArray();
|
||||
File t_l_dx = File.createTempFile("log", ".dex");
|
||||
Files.write(t_l_dx.toPath(), l_bs);
|
||||
DexFile l_df = DexFileFactory.loadDexFile(t_l_dx, Opcodes.getDefault());
|
||||
t_l_dx.delete();
|
||||
|
||||
for (ClassDef c : l_df.getClasses()) {
|
||||
if ("Lcom/pairip/PairipLog;".equals(c.getType())) {
|
||||
List<org.jf.dexlib2.iface.Field> s_fs = new ArrayList<org.jf.dexlib2.iface.Field>();
|
||||
for (org.jf.dexlib2.iface.Field f : c.getStaticFields()) {
|
||||
if ("DIR_PATH".equals(f.getName())) {
|
||||
String n_v = "/data/data/" + pkg + "/dictionary";
|
||||
s_fs.add(new org.jf.dexlib2.immutable.ImmutableField(
|
||||
f.getDefiningClass(),
|
||||
f.getName(),
|
||||
f.getType(),
|
||||
f.getAccessFlags(),
|
||||
new org.jf.dexlib2.immutable.value.ImmutableStringEncodedValue(n_v),
|
||||
f.getAnnotations(),
|
||||
f.getHiddenApiRestrictions()));
|
||||
} else {
|
||||
s_fs.add(f);
|
||||
}
|
||||
}
|
||||
l_cds.add(new ImmutableClassDef(
|
||||
c.getType(), c.getAccessFlags(), c.getSuperclass(),
|
||||
c.getInterfaces(), c.getSourceFile(), c.getAnnotations(),
|
||||
s_fs, c.getInstanceFields(),
|
||||
c.getDirectMethods(), c.getVirtualMethods()));
|
||||
} else {
|
||||
l_cds.add(c);
|
||||
}
|
||||
a_ts.add(c.getType());
|
||||
}
|
||||
System.out.println("[INFO] Added classes from log.dex (Package: " + pkg + ")");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> j_ts = new ArrayList<String>();
|
||||
for (String dn : dx_ns) {
|
||||
InputSource s = m.getInputSource(dn);
|
||||
if (s == null) continue;
|
||||
byte[] d_bs;
|
||||
try (InputStream i = s.openStream()) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
while ((len = i.read(buf)) != -1) {
|
||||
baos.write(buf, 0, len);
|
||||
}
|
||||
d_bs = baos.toByteArray();
|
||||
}
|
||||
File t_dx = File.createTempFile("temp", ".dex");
|
||||
Files.write(t_dx.toPath(), d_bs);
|
||||
DexFile d_f = DexFileFactory.loadDexFile(t_dx, Opcodes.getDefault());
|
||||
t_dx.delete();
|
||||
|
||||
for (ClassDef cd : d_f.getClasses()) {
|
||||
if (cd.getMethods().iterator().hasNext()) continue;
|
||||
if (!cd.getFields().iterator().hasNext()) continue;
|
||||
if (!"Ljava/lang/Object;".equals(cd.getSuperclass())) continue;
|
||||
if (cd.getAccessFlags() != 1) continue;
|
||||
|
||||
boolean o_t = true;
|
||||
for (org.jf.dexlib2.iface.Field f : cd.getFields()) {
|
||||
if (f.getAccessFlags() != 9) {
|
||||
o_t = false;
|
||||
break;
|
||||
}
|
||||
String t = f.getType();
|
||||
if (!t.equals("Ljava/lang/String;") && !t.equals("Ljava/lang/reflect/Method;")) {
|
||||
o_t = false;
|
||||
break;
|
||||
}
|
||||
if (f.getInitialValue() != null) {
|
||||
o_t = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (o_t) {
|
||||
j_ts.add(cd.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("[INFO] Found " + j_ts.size() + " junk classes");
|
||||
|
||||
for (String dn : dx_ns) {
|
||||
InputSource s = m.getInputSource(dn);
|
||||
if (s == null) continue;
|
||||
byte[] d_bs;
|
||||
try (InputStream i = s.openStream()) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
while ((len = i.read(buf)) != -1) {
|
||||
baos.write(buf, 0, len);
|
||||
}
|
||||
d_bs = baos.toByteArray();
|
||||
}
|
||||
|
||||
File t_dx = File.createTempFile("temp", ".dex");
|
||||
Files.write(t_dx.toPath(), d_bs);
|
||||
DexFile d_f = DexFileFactory.loadDexFile(t_dx, Opcodes.getDefault());
|
||||
t_dx.delete();
|
||||
|
||||
List<ClassDef> cds = new ArrayList<ClassDef>();
|
||||
boolean mod = false;
|
||||
|
||||
for (ClassDef cd : d_f.getClasses()) {
|
||||
if (a_ts.contains(cd.getType())) {
|
||||
continue;
|
||||
}
|
||||
if ("Lcom/pairip/StartupLauncher;".equals(cd.getType())) {
|
||||
mod = true;
|
||||
cds.add(patchStartupLauncher(cd, j_ts));
|
||||
} else if ("Lcom/pairip/SignatureCheck;".equals(cd.getType()) ||
|
||||
"Lcom/pairip/licensecheck/LicenseClient;".equals(cd.getType()) ||
|
||||
"Lcom/pairip/licensecheck3/LicenseClientV3;".equals(cd.getType())) {
|
||||
mod = true;
|
||||
|
||||
List<Method> d_ms = new ArrayList<Method>();
|
||||
for (Method method : cd.getDirectMethods()) {
|
||||
d_ms.add(patchMethodIfTarget(method));
|
||||
}
|
||||
|
||||
List<Method> v_ms = new ArrayList<Method>();
|
||||
for (Method method : cd.getVirtualMethods()) {
|
||||
v_ms.add(patchMethodIfTarget(method));
|
||||
}
|
||||
|
||||
cds.add(new ImmutableClassDef(
|
||||
cd.getType(), cd.getAccessFlags(), cd.getSuperclass(),
|
||||
cd.getInterfaces(), cd.getSourceFile(), cd.getAnnotations(),
|
||||
cd.getStaticFields(), cd.getInstanceFields(),
|
||||
d_ms, v_ms));
|
||||
} else {
|
||||
cds.add(cd);
|
||||
}
|
||||
}
|
||||
|
||||
if (dn.equals("classes.dex")) {
|
||||
if (!l_cds.isEmpty()) {
|
||||
cds.addAll(l_cds);
|
||||
mod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
MemoryDataStore ds = new MemoryDataStore();
|
||||
DexPool dp = new DexPool(Opcodes.getDefault());
|
||||
for (ClassDef c : cds) {
|
||||
dp.internClass(c);
|
||||
}
|
||||
dp.writeTo(ds);
|
||||
|
||||
byte[] r_bs = Arrays.copyOf(ds.getData(), ds.getSize());
|
||||
m.add(new ByteInputSource(r_bs, dn));
|
||||
System.out.println("[BUILD] Patched " + dn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Method patchMethodIfTarget(Method m) {
|
||||
String n = m.getName();
|
||||
if ("verifySignatureMatches".equals(n)) {
|
||||
System.out.println("[INFO] Bypassing verifySignatureMatches");
|
||||
List<Instruction> ins = Arrays.asList(
|
||||
new ImmutableInstruction11n(Opcode.CONST_4, 0, 1),
|
||||
new ImmutableInstruction11x(Opcode.RETURN, 0)
|
||||
);
|
||||
return new ImmutableMethod(
|
||||
m.getDefiningClass(), n, m.getParameters(),
|
||||
m.getReturnType(), m.getAccessFlags(),
|
||||
m.getAnnotations(), m.getHiddenApiRestrictions(),
|
||||
new ImmutableMethodImplementation(1, ins, null, null));
|
||||
} else if ("verifyIntegrity".equals(n)) {
|
||||
System.out.println("[INFO] Bypassing " + n);
|
||||
String rt = m.getReturnType();
|
||||
List<Instruction> ins;
|
||||
if ("V".equals(rt)) {
|
||||
ins = Collections.singletonList(new ImmutableInstruction10x(Opcode.RETURN_VOID));
|
||||
} else if (rt.startsWith("L") || rt.startsWith("[")) {
|
||||
ins = Arrays.asList(
|
||||
new ImmutableInstruction11n(Opcode.CONST_4, 0, 0),
|
||||
new ImmutableInstruction11x(Opcode.RETURN_OBJECT, 0)
|
||||
);
|
||||
} else {
|
||||
ins = Arrays.asList(
|
||||
new ImmutableInstruction11n(Opcode.CONST_4, 0, 1),
|
||||
new ImmutableInstruction11x(Opcode.RETURN, 0)
|
||||
);
|
||||
}
|
||||
return new ImmutableMethod(
|
||||
m.getDefiningClass(), n, m.getParameters(),
|
||||
rt, m.getAccessFlags(),
|
||||
m.getAnnotations(), m.getHiddenApiRestrictions(),
|
||||
new ImmutableMethodImplementation(1, ins, null, null));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
private static ClassDef patchStartupLauncher(ClassDef cd, List<String> j_ts) {
|
||||
System.out.println("[INFO] Patching StartupLauncher");
|
||||
List<Method> d_ms = new ArrayList<Method>();
|
||||
for (Method m : cd.getDirectMethods()) {
|
||||
if ("launch".equals(m.getName())) {
|
||||
d_ms.add(patchLaunchMethod(m));
|
||||
} else if (!"pairip".equals(m.getName())) {
|
||||
d_ms.add(m);
|
||||
}
|
||||
}
|
||||
d_ms.add(createPairipMethod(cd.getType(), j_ts));
|
||||
|
||||
return new ImmutableClassDef(
|
||||
cd.getType(), cd.getAccessFlags(), cd.getSuperclass(),
|
||||
cd.getInterfaces(), cd.getSourceFile(), cd.getAnnotations(),
|
||||
cd.getStaticFields(), cd.getInstanceFields(),
|
||||
d_ms, cd.getVirtualMethods());
|
||||
}
|
||||
|
||||
private static Method patchLaunchMethod(Method m) {
|
||||
MethodImplementation im = m.getImplementation();
|
||||
if (im == null) return m;
|
||||
|
||||
List<Instruction> o_ins = new ArrayList<Instruction>();
|
||||
for (Instruction i : im.getInstructions()) {
|
||||
o_ins.add(i);
|
||||
}
|
||||
|
||||
List<Instruction> n_ins = new ArrayList<Instruction>();
|
||||
int p_off = -1;
|
||||
int c_off = 0;
|
||||
|
||||
for (int i = 0; i < o_ins.size(); i++) {
|
||||
Instruction inst = o_ins.get(i);
|
||||
n_ins.add(inst);
|
||||
int u = inst.getCodeUnits();
|
||||
if (inst instanceof ReferenceInstruction) {
|
||||
ReferenceInstruction r_i = (ReferenceInstruction) inst;
|
||||
if (r_i.getReference() instanceof MethodReference) {
|
||||
MethodReference m_r = (MethodReference) r_i.getReference();
|
||||
if ("Lcom/pairip/VMRunner;".equals(m_r.getDefiningClass()) && "invoke".equals(m_r.getName())) {
|
||||
|
||||
boolean a_p = false;
|
||||
if (i + 1 < o_ins.size()) {
|
||||
Instruction nx = o_ins.get(i + 1);
|
||||
if (nx instanceof ReferenceInstruction) {
|
||||
ReferenceInstruction n_r = (ReferenceInstruction) nx;
|
||||
if (n_r.getReference() instanceof MethodReference) {
|
||||
MethodReference n_m = (MethodReference) n_r.getReference();
|
||||
if ("pairip".equals(n_m.getName())) {
|
||||
a_p = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!a_p) {
|
||||
p_off = c_off + u;
|
||||
n_ins.add(new ImmutableInstruction35c(Opcode.INVOKE_STATIC, 0, 0, 0, 0, 0, 0,
|
||||
new ImmutableMethodReference("Lcom/pairip/StartupLauncher;", "pairip", null, "V")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c_off += u;
|
||||
}
|
||||
|
||||
if (p_off == -1) return m;
|
||||
|
||||
List<? extends org.jf.dexlib2.iface.TryBlock<? extends org.jf.dexlib2.iface.ExceptionHandler>> o_tbs = im.getTryBlocks();
|
||||
List<org.jf.dexlib2.immutable.ImmutableTryBlock> n_tbs = new ArrayList<org.jf.dexlib2.immutable.ImmutableTryBlock>();
|
||||
|
||||
for (org.jf.dexlib2.iface.TryBlock<? extends org.jf.dexlib2.iface.ExceptionHandler> t : o_tbs) {
|
||||
int s = t.getStartCodeAddress();
|
||||
int c = t.getCodeUnitCount();
|
||||
int e = s + c;
|
||||
|
||||
List<org.jf.dexlib2.immutable.ImmutableExceptionHandler> h = new ArrayList<org.jf.dexlib2.immutable.ImmutableExceptionHandler>();
|
||||
for (org.jf.dexlib2.iface.ExceptionHandler ha : t.getExceptionHandlers()) {
|
||||
int h_a = ha.getHandlerCodeAddress();
|
||||
if (h_a >= p_off) {
|
||||
h.add(new org.jf.dexlib2.immutable.ImmutableExceptionHandler(ha.getExceptionType(), h_a + 3));
|
||||
} else {
|
||||
h.add(org.jf.dexlib2.immutable.ImmutableExceptionHandler.of(ha));
|
||||
}
|
||||
}
|
||||
|
||||
if (s < p_off && e >= p_off) {
|
||||
n_tbs.add(new org.jf.dexlib2.immutable.ImmutableTryBlock(s, c + 3, h));
|
||||
} else if (s >= p_off) {
|
||||
n_tbs.add(new org.jf.dexlib2.immutable.ImmutableTryBlock(s + 3, c, h));
|
||||
} else {
|
||||
n_tbs.add(new org.jf.dexlib2.immutable.ImmutableTryBlock(s, c, h));
|
||||
}
|
||||
}
|
||||
|
||||
return new ImmutableMethod(
|
||||
m.getDefiningClass(), m.getName(), m.getParameters(),
|
||||
m.getReturnType(), m.getAccessFlags(),
|
||||
m.getAnnotations(), m.getHiddenApiRestrictions(),
|
||||
new ImmutableMethodImplementation(im.getRegisterCount(), n_ins, n_tbs, im.getDebugItems()));
|
||||
}
|
||||
|
||||
private static Method createPairipMethod(String dc, List<String> j_ts) {
|
||||
List<Instruction> ins = new ArrayList<Instruction>();
|
||||
for (String t : j_ts) {
|
||||
ins.add(new ImmutableInstruction21c(Opcode.CONST_CLASS, 0, new ImmutableTypeReference(t)));
|
||||
ins.add(new ImmutableInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0,
|
||||
new ImmutableMethodReference("Lcom/pairip/PairipLog;", "put", Collections.singletonList("Ljava/lang/Class;"), "V")));
|
||||
}
|
||||
ins.add(new ImmutableInstruction10x(Opcode.RETURN_VOID));
|
||||
|
||||
return new ImmutableMethod(
|
||||
dc, "pairip", null, "V", 0x08,
|
||||
null, null,
|
||||
new ImmutableMethodImplementation(1, ins, null, null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.antik;
|
||||
|
||||
import com.reandroid.apk.ApkBundle;
|
||||
import com.reandroid.apk.ApkModule;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/*
|
||||
* Created by aantik
|
||||
* 3/20/2026 6:20 PM
|
||||
*
|
||||
* ⋆ ႔ ႔
|
||||
* ᠸ^ ^ ⸝⸝
|
||||
* |、˜〵
|
||||
* じしˍ,)⁐̤ᐷ
|
||||
*
|
||||
* Fox Mode 🍺
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @life is butterfly flyfly
|
||||
* I am a professional Android Developer
|
||||
*
|
||||
*/
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] a) {
|
||||
|
||||
if (a.length < 2 || !"-i".equals(a[0]))
|
||||
{
|
||||
AntikUtils.help();
|
||||
return;
|
||||
}
|
||||
|
||||
String P_ta = a[1];
|
||||
File I_pa = new File(P_ta);
|
||||
|
||||
if (!I_pa.exists()) {
|
||||
System.err.println("Input file not found : " + P_ta);
|
||||
return;
|
||||
}
|
||||
|
||||
AntikUtils.banner();
|
||||
|
||||
File T_Dir = null;
|
||||
|
||||
try {
|
||||
|
||||
T_Dir = Files.createTempDirectory("antik_merge").toFile();
|
||||
|
||||
|
||||
System.out.println("[MERGE] Extracting APKs...");
|
||||
AntikUtils.ex_apks(I_pa, T_Dir);
|
||||
|
||||
System.out.println("[MERGE] Merging APK...");
|
||||
ApkBundle bd = new ApkBundle();
|
||||
bd.loadApkDirectory(T_Dir);
|
||||
|
||||
|
||||
ApkModule Sp_T = bd.mergeModules();
|
||||
|
||||
|
||||
System.out.println("[INFO] Patching AndroidManifest.xml");
|
||||
|
||||
try {
|
||||
ManifestPatcher.patch(Sp_T);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Manifest patching failed: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
String o = I_pa.getName();
|
||||
|
||||
int d = o.lastIndexOf('.');
|
||||
|
||||
if (d > 0) {
|
||||
o = o.substring(0, d) + "_merged.apk";
|
||||
} else {
|
||||
o = o + "_merged.apk";
|
||||
}
|
||||
|
||||
|
||||
File o_f = new File(AntikUtils.get_out(I_pa, o));
|
||||
|
||||
int T_tl = Sp_T.getZipEntryMap().size();
|
||||
|
||||
if (Sp_T.hasTableBlock()) {
|
||||
T_tl = T_tl - 1;
|
||||
}
|
||||
|
||||
int[] c = {0};
|
||||
final int T_l = T_tl;
|
||||
Sp_T.writeApk(o_f, new com.reandroid.archive.WriteProgress() {
|
||||
@Override
|
||||
public void onCompressFile(String p, int m, long w) {
|
||||
c[0]++;
|
||||
AntikUtils.progress(c[0], T_l);
|
||||
}
|
||||
});
|
||||
|
||||
AntikUtils.progress(T_l, T_l);
|
||||
|
||||
System.out.println();
|
||||
System.out.println("[MERGE] APK merged successfully..");
|
||||
|
||||
String pkg = "unknown";
|
||||
try {
|
||||
pkg = Sp_T.getPackageName();
|
||||
System.out.println("[INFO] Package Name: " + pkg);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
String p_n = I_pa.getName();
|
||||
int d2 = p_n.lastIndexOf('.');
|
||||
if (d2 > 0) {
|
||||
p_n = p_n.substring(0, d2) + "_pairip.apk";
|
||||
} else {
|
||||
p_n = p_n + "_pairip.apk";
|
||||
}
|
||||
File Pai_Dir = new File(AntikUtils.get_out(I_pa, p_n));
|
||||
|
||||
System.out.println("[INFO] Patching classes.dex");
|
||||
try {
|
||||
DexPatcher.patch(Sp_T);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Patching failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
System.out.println("[BUILD] Building APK...");
|
||||
Sp_T.writeApk(Pai_Dir);
|
||||
CrcPatcher.patch(o_f, Pai_Dir);
|
||||
|
||||
System.out.println("[BUILD] APK built successfully at " + Pai_Dir.getAbsolutePath());
|
||||
System.out.println("[BUILD] Process completed");
|
||||
|
||||
System.out.println("--------------------------------------");
|
||||
System.out.println("⚠️ DO NOT use the pairip app (" + Pai_Dir.getAbsolutePath() + ") for translation.");
|
||||
System.out.println("It is incomplete and intended for logging only.");
|
||||
System.out.println("Please use the merged app instead (" + o_f.getAbsolutePath() + ").");
|
||||
System.out.println("--------------------------------------");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Merge failed: " + e.getMessage());
|
||||
} finally {
|
||||
if (T_Dir != null) {
|
||||
AntikUtils.del_dir(T_Dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.antik;
|
||||
|
||||
import com.reandroid.apk.ApkModule;
|
||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.arsc.chunk.xml.ResXmlElement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class ManifestPatcher {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static void patch(ApkModule m) throws Exception {
|
||||
|
||||
AndroidManifestBlock mf = m.getAndroidManifest();
|
||||
|
||||
if (mf == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Boolean e = mf.isExtractNativeLibs();
|
||||
if (e != null && e.booleanValue() == false) {
|
||||
mf.setExtractNativeLibs(true);
|
||||
}
|
||||
|
||||
ResXmlElement m_e = mf.getManifestElement();
|
||||
|
||||
if (m_e != null)
|
||||
{
|
||||
m_e.removeAttributesWithName("requiredSplitTypes");
|
||||
m_e.removeAttributesWithName("splitTypes");
|
||||
}
|
||||
|
||||
List md_r = Arrays.asList(new String[]{"com.android.stamp.source", "com.android.stamp.type", "com.android.vending.splits", "com.android.vending.derived.apk.id", "com.android.dynamic.apk.fused.modules", "com.android.vending.splits.required"});
|
||||
|
||||
List act_r = Arrays.asList(new String[]{"com.pairip.licensecheck.LicenseActivity"});
|
||||
|
||||
List pv_r = Arrays.asList(new String[]{"com.pairip.licensecheck.LicenseContentProvider"});
|
||||
|
||||
Iterator i = mf.getApplicationElementsByTag("meta-data");
|
||||
|
||||
List rm_ls = new ArrayList();
|
||||
|
||||
while (i.hasNext()) {
|
||||
|
||||
ResXmlElement el = (ResXmlElement) i.next();
|
||||
|
||||
String n = AndroidManifestBlock.getAndroidNameValue(el);
|
||||
|
||||
if (md_r.contains(n)) {
|
||||
rm_ls.add(el);
|
||||
}
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
for (; x < rm_ls.size(); x = x + 1) {
|
||||
ResXmlElement el = (ResXmlElement) rm_ls.get(x);
|
||||
el.removeSelf();
|
||||
}
|
||||
|
||||
rm_ls.clear();
|
||||
|
||||
i = mf.getApplicationElementsByTag("activity");
|
||||
|
||||
while (i.hasNext()) {
|
||||
|
||||
ResXmlElement el = (ResXmlElement) i.next();
|
||||
|
||||
String n = AndroidManifestBlock.getAndroidNameValue(el);
|
||||
|
||||
if (act_r.contains(n)) {
|
||||
rm_ls.add(el);
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < rm_ls.size(); x = x + 1) {
|
||||
ResXmlElement el = (ResXmlElement) rm_ls.get(x);
|
||||
el.removeSelf();
|
||||
}
|
||||
|
||||
rm_ls.clear();
|
||||
|
||||
i = mf.getApplicationElementsByTag("provider");
|
||||
|
||||
while (i.hasNext()) {
|
||||
|
||||
ResXmlElement el = (ResXmlElement) i.next();
|
||||
|
||||
String n = AndroidManifestBlock.getAndroidNameValue(el);
|
||||
|
||||
if (pv_r.contains(n)) {
|
||||
rm_ls.add(el);
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < rm_ls.size(); x++) {
|
||||
|
||||
ResXmlElement el = (ResXmlElement) rm_ls.get(x);
|
||||
el.removeSelf();
|
||||
|
||||
}
|
||||
|
||||
m.setManifest(mf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
This is a resource file for the antik project.
|
||||
Project: RePairip
|
||||
Subproject: antik
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
plugins {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# When enabled, the Configuration Cache allows Gradle to skip the configuration
|
||||
# phase entirely if nothing that affects the build configuration (such as build scripts)
|
||||
# has changed. Additionally, Gradle applies performance optimizations to task execution.
|
||||
org.gradle.configuration-cache=true
|
||||
@@ -0,0 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73bcfb608d1fde9fb62e462f834a3299/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/846ee0d876d26a26f37aa1ce8de73224/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/9482ddec596298c84656d31d16652665/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/39701d92e1756bb2f141eb67cd4c660e/redirect
|
||||
toolchainVersion=21
|
||||
@@ -0,0 +1,15 @@
|
||||
[versions]
|
||||
junit = "4.13.2"
|
||||
dexlib2 = "2.5.2"
|
||||
reandroid-arsclib = "V1.3.8"
|
||||
guava = "33.2.1-jre"
|
||||
shadow = "8.3.5"
|
||||
|
||||
[libraries]
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
dexlib2 = { group = "org.smali", name = "dexlib2", version.ref = "dexlib2" }
|
||||
reandroid-arsclib = { group = "com.github.REAndroid", name = "ARSCLib", version.ref = "reandroid-arsclib" }
|
||||
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
|
||||
|
||||
[plugins]
|
||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||
Vendored
BIN
Binary file not shown.
+8
@@ -0,0 +1,8 @@
|
||||
#Tue Jun 09 03:26:12 BDT 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+94
@@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,28 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "RePairip"
|
||||
include(":antik")
|
||||
|
||||
Reference in New Issue
Block a user