Merge branch 'Fox2Code:master' into master

pull/145/head
Der_Googler 2 years ago committed by GitHub
commit a9a329f1bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,82 @@
## AnyKernel3 (AK3), and AnyKernel2/AnyKernel 2.0 (AK2) Scripts License:
#
# AnyKernel (versions 2.0/2 and later) Android image modifying scripts.
# Copyright (c) 2019 Chris Renshaw (osm0sis @ xda-developers),
# and additional contributors per readily available commit history/credits.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted (subject to the limitations in the disclaimer
# below) provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
if [ -z "$AK3TMPFS" ]; then
echo "AK3TMPFS is not defined? Are you running FoxMMM?"
exit 1
fi
if [ ! -e "$AK3TMPFS" ]; then
mkdir $AK3TMPFS
chmod 755 $AK3TMPFS
fi
ZIPFILE=$3;
# Mount tmpfs early
mount -t tmpfs -o size=400M,noatime tmpfs $AK3TMPFS;
mount | grep -q " $AK3TMPFS " || exit 1;
unzip -p $Z tools*/busybox > $AK3TMPFS/busybox;
unzip -p $Z META-INF/com/google/android/update-binary > $AK3TMPFS/update-binary;
##
chmod 755 $AK3TMPFS/busybox;
$AK3TMPFS/busybox chmod 755 $AK3TMPFS/update-binary;
$AK3TMPFS/busybox chown root:root $AK3TMPFS/busybox $AK3TMPFS/update-binary;
# work around Android passing the app what is actually a non-absolute path
AK3TMPFS=$($AK3TMPFS/busybox readlink -f $AK3TMPFS);
# AK3 allows the zip to be flashed from anywhere so avoids any need to remount /
if $AK3TMPFS/busybox grep -q AnyKernel3 $AK3TMPFS/update-binary; then
# work around more restrictive upstream SELinux policies for Magisk <19306
magiskpolicy --live "allow kernel app_data_file file write" || true;
TMP=$AK3TMPFS/tmp;
else
echo "Module is not an AnyKernel3 module!"
exit 1
fi;
# update-binary <RECOVERY_API_VERSION> <OUTFD> <ZIPFILE>
ASH_STANDALONE=1 AKHOME=$AK3TMPFS/anykernel $AK3TMPFS/busybox ash $AK3TMPFS/update-binary 3 1 "$Z";
RC=$?;
# Original script delete all generated files,
# But we just need to unmount as we store everything inside tmpfs
umount $TMP;
return $RC;

@ -70,7 +70,7 @@ public class AndroidacyRepoData extends RepoData {
// Implementation details discussed on telegram
long time = System.currentTimeMillis();
if (this.androidacyBlockade > time) return false;
this.androidacyBlockade = time + 5_000L;
this.androidacyBlockade = time + 30_000L;
String cookies = AndroidacyRepoData.getCookies();
int start = cookies == null ? -1 : cookies.indexOf("USER=");
String token = null;
@ -150,8 +150,9 @@ public class AndroidacyRepoData extends RepoData {
for (int i = 0; i < len; i++) {
jsonObject = jsonArray.getJSONObject(i);
String moduleId = jsonObject.getString("codename");
// Deny remote modules ids shorter than 3 chars
if (moduleId.length() < 3) continue;
// Deny remote modules ids shorter than 3 chars or containing null char or space
if (moduleId.length() < 3 || moduleId.indexOf('\0') != -1 ||
moduleId.indexOf(' ') != -1 || "ak3-helper".equals(moduleId)) continue;
long lastUpdate = jsonObject.getLong("updated_at") * 1000;
lastLastUpdate = Math.max(lastLastUpdate, lastUpdate);
RepoModule repoModule = this.moduleHashMap.get(moduleId);

@ -44,7 +44,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
@ -168,31 +167,31 @@ public class InstallerActivity extends CompatActivity {
Files.fixJavaZipHax(rawModule);
boolean noPatch = false;
boolean isModule = false;
boolean isAnyKernel = false;
boolean isAnyKernel3 = false;
errMessage = "File is not a valid zip file";
try (ZipInputStream zipInputStream = new ZipInputStream(
new ByteArrayInputStream(rawModule))) {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
String entryName = zipEntry.getName();
if (entryName.equals("anykernel.sh")) {
if (entryName.equals("tools/ak3-core.sh")) {
noPatch = true;
isAnyKernel = true;
isAnyKernel3 = true;
break;
} else if (entryName.equals("module.prop")) {
noPatch = true;
isModule = true;
break;
} else if (entryName.endsWith("/anykernel.sh")) {
isAnyKernel = true;
} else if (entryName.endsWith("/tools/ak3-core.sh")) {
isAnyKernel3 = true;
} else if (entryName.endsWith("/module.prop")) {
isModule = true;
}
}
}
if (!isModule && !isAnyKernel) {
if (!isModule && !isAnyKernel3) {
this.setInstallStateFinished(false,
"! File is not a valid magisk module", "");
"! File is not a valid Magisk or AnyKernel3 module", "");
return;
}
if (noPatch) {
@ -254,36 +253,37 @@ public class InstallerActivity extends CompatActivity {
installJob = Shell.cmd("export MMM_EXT_SUPPORT=1",
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
"sh \"" + installScript.getAbsolutePath() + "\"" +
" /dev/null 1 \"" + file.getAbsolutePath() + "\"")
" 3 0 \"" + file.getAbsolutePath() + "\"")
.to(installerController, installerMonitor);
} else {
String arch32 = "true"; // Do nothing by default
boolean needs32bit = false;
String moduleId = null;
boolean anyKernel = false;
boolean anyKernel3 = false;
boolean magiskModule = false;
File anyKernelInstallScript = new File(this.moduleCache, "update-binary");
String MAGISK_PATH = InstallerInitializer.peekMagiskPath();
if (MAGISK_PATH == null) {
this.setInstallStateFinished(false, "! Unable to resolve magisk path", "");
return;
}
String ASH = MAGISK_PATH + "/.magisk/busybox/busybox ash";
try (ZipFile zipFile = new ZipFile(file)) {
// Check if module is AnyKernel module
if (zipFile.getEntry("anykernel.sh") != null) {
if (zipFile.getEntry("tools/ak3-core.sh") != null) {
ZipEntry updateBinary = zipFile.getEntry(
"META-INF/com/google/android/update-binary");
if (updateBinary != null) {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(zipFile.getInputStream(updateBinary)));
PrintStream printStream = new PrintStream(
new FileOutputStream(anyKernelInstallScript));
String line;
while ((line = bufferedReader.readLine()) != null) {
line = line.replace("/sbin/sh", "/system/bin/sh");
line = line.replace("/data/adb/modules/ak3-helper",
"/data/adb/modules-update/ak3-helper");
printStream.println(line);
if (line.contains("AnyKernel3")) {
anyKernel3 = true;
break;
}
}
printStream.close();
bufferedReader.close();
}
anyKernel = true;
}
if (zipFile.getEntry( // Check if module hard require 32bit support
"common/addon/Volume-Key-Selector/tools/arm64/keycheck") == null &&
@ -310,13 +310,15 @@ public class InstallerActivity extends CompatActivity {
null);
return;
}
if (magiskModule && moduleId == null && !anyKernel) {
if (magiskModule && moduleId == null && !anyKernel3) {
// Modules without module Ids are module installed by 3rd party software
this.setInstallStateFinished(false,
"! Magisk modules require a moduleId", null);
return;
}
if (Build.SUPPORTED_32_BIT_ABIS.length == 0) {
if (anyKernel3) {
installerController.useRecoveryExt();
} else if (Build.SUPPORTED_32_BIT_ABIS.length == 0) {
if (needs32bit) {
this.setInstallStateFinished(false,
"! This module can't be installed on a 64bit only system",
@ -332,47 +334,45 @@ public class InstallerActivity extends CompatActivity {
}
String installCommand;
File installExecutable;
if (anyKernel && moduleId == null) { // AnyKernel modules don't have a moduleId
if (anyKernel3 && moduleId == null) { // AnyKernel modules don't have a moduleId
this.warnReboot = true; // We should probably re-flash magisk...
installExecutable = anyKernelInstallScript;
installExecutable = this.extractInstallScript("module_installer_anykernel3.sh");
if (installExecutable == null) {
this.setInstallStateFinished(false,
"! Failed to extract AnyKernel3 module install script", null);
return;
}
// "unshare -m" is needed to force mount namespace isolation.
// This allow AnyKernel to mess-up with mounts point without crashing the system!
installCommand = "unshare -m sh \"" + installExecutable.getAbsolutePath() + "\"" +
" /dev/null 1 \"" + file.getAbsolutePath() + "\"";
installCommand = "unshare -m " + ASH + " \"" +
installExecutable.getAbsolutePath() + "\"" +
" 3 1 \"" + file.getAbsolutePath() + "\"";
} else if (InstallerInitializer.peekMagiskVersion() >=
Constants.MAGISK_VER_CODE_INSTALL_COMMAND &&
((compatFlags & AppUpdateManager.FLAG_COMPAT_MAGISK_CMD) != 0 ||
noExtensions || MainApplication.isUsingMagiskCommand())) {
installCommand = "magisk --install-module \"" + file.getAbsolutePath() + "\"";
installExecutable = new File(InstallerInitializer.peekMagiskPath()
.equals("/sbin") ? "/sbin/magisk" : "/system/bin/magisk");
installExecutable = new File(MAGISK_PATH.equals("/sbin") ?
"/sbin/magisk" : "/system/bin/magisk");
} else if (moduleId != null) {
installExecutable = this.extractInstallScript("module_installer_compat.sh");
if (installExecutable == null) {
this.setInstallStateFinished(false,
"! Failed to extract module install script", null);
"! Failed to extract Magisk module install script", null);
return;
}
installCommand = "sh \"" + installExecutable.getAbsolutePath() + "\"" +
" /dev/null 1 \"" + file.getAbsolutePath() + "\"";
installCommand = ASH + " \"" +
installExecutable.getAbsolutePath() + "\"" +
" 3 1 \"" + file.getAbsolutePath() + "\"";
} else {
this.setInstallStateFinished(false,
"! Zip file is not a valid Magisk or a AnyKernel module!", null);
"! Zip file is not a valid Magisk or AnyKernel3 module!", null);
return;
}
installerMonitor = new InstallerMonitor(installExecutable);
if (moduleId != null) installerMonitor.setForCleanUp(moduleId);
if (anyKernel) {
final String adbTmp = "data/adb/tmp";
final String anyKernelHome = // Mirror mounts do not contain nosuid
InstallerInitializer.peekMirrorPath() +
"/" + adbTmp + "/anykernel";
installJob = Shell.cmd(arch32, "export MMM_EXT_SUPPORT=1",
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
"mkdir " + adbTmp, "export AKHOME=" + anyKernelHome,
installCommand).to(installerController, installerMonitor);
} else if (noExtensions) {
installJob = Shell.cmd(arch32, // No Extensions
if (noExtensions) {
installJob = Shell.cmd(arch32, "export BOOTMODE=true", // No Extensions
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
installCommand).to(installerController, installerMonitor);
} else {
@ -381,7 +381,9 @@ public class InstallerActivity extends CompatActivity {
Resources.getSystem().getConfiguration().locale.toLanguageTag()),
"export MMM_APP_VERSION=" + BuildConfig.VERSION_NAME,
"export MMM_TEXT_WRAP=" + (this.textWrap ? "1" : "0"),
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
"export BOOTMODE=true", anyKernel3 ? "export AK3TMPFS=" +
InstallerInitializer.peekMagiskPath() + "/ak3tmpfs" :
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
installCommand).to(installerController, installerMonitor);
}
}
@ -408,7 +410,8 @@ public class InstallerActivity extends CompatActivity {
private final InstallerTerminal terminal;
private final File moduleFile;
private final boolean noExtension;
private boolean enabled, useExt;
private boolean enabled, useExt,
useRecovery, isRecoveryBar;
private String supportLink = "";
private InstallerController(LinearProgressIndicator progressIndicator,
@ -431,7 +434,25 @@ public class InstallerActivity extends CompatActivity {
return;
}
if (this.useExt && s.startsWith("#!")) {
this.processCommand(s);
this.processCommand(s.substring(2));
} else if (this.useRecovery && s.startsWith("progress ")) {
String[] tokens = s.split(" ");
try {
float progress = Float.parseFloat(tokens[1]);
float max = Float.parseFloat(tokens[2]);
int progressInt;
if (max <= 0F) {
return;
} else if (progress >= max) {
progressInt = 256;
} else {
if (progress <= 0F) progress = 0F;
progressInt = (int) ((256D * progress) / max);
}
this.processCommand("showLoading 256");
this.processCommand("setLoading " + progressInt);
this.isRecoveryBar = true;
} catch (Exception ignored) {}
} else {
this.terminal.addLine(s.replace(
this.moduleFile.getAbsolutePath(),
@ -445,12 +466,15 @@ public class InstallerActivity extends CompatActivity {
int i = rawCommand.indexOf(' ');
if (i != -1) {
arg = rawCommand.substring(i + 1).trim();
command = rawCommand.substring(2, i);
command = rawCommand.substring(0, i);
} else {
arg = "";
command = rawCommand.substring(2);
command = rawCommand;
}
switch (command) {
case "useRecovery":
this.useRecovery = true;
break;
case "addLine":
this.terminal.addLine(arg);
break;
@ -467,6 +491,7 @@ public class InstallerActivity extends CompatActivity {
this.terminal.scrollDown();
break;
case "showLoading":
this.isRecoveryBar = false;
if (!arg.isEmpty()) {
try {
short s = Short.parseShort(arg);
@ -481,7 +506,7 @@ public class InstallerActivity extends CompatActivity {
}
this.progressIndicator.setIndeterminate(true);
}
} else if (!rawCommand.trim().equals("#!showLoading")) {
} else {
this.progressIndicator.setProgressCompat(0, true);
this.progressIndicator.setMax(100);
if (this.progressIndicator.getVisibility() == View.VISIBLE) {
@ -492,6 +517,7 @@ public class InstallerActivity extends CompatActivity {
this.progressIndicator.setVisibility(View.VISIBLE);
break;
case "setLoading":
this.isRecoveryBar = false;
try {
this.progressIndicator.setProgressCompat(
Short.parseShort(arg), true);
@ -499,6 +525,7 @@ public class InstallerActivity extends CompatActivity {
}
break;
case "hideLoading":
this.isRecoveryBar = false;
this.progressIndicator.setVisibility(View.GONE);
break;
case "setSupportLink":
@ -510,8 +537,16 @@ public class InstallerActivity extends CompatActivity {
}
}
public void useRecoveryExt() {
this.useRecovery = true;
}
public void disable() {
this.enabled = false;
if (this.isRecoveryBar) {
UiThreadHandler.runAndWait(() ->
this.processCommand("setLoading 256"));
}
}
public String getSupportLink() {

@ -36,6 +36,7 @@ public class InstallerInitializer extends Shell.Initializer {
public static String peekMagiskPath() {
return InstallerInitializer.MAGISK_PATH;
}
public static String peekMirrorPath() {
return InstallerInitializer.MAGISK_PATH == null ? null :
InstallerInitializer.MAGISK_PATH + "/.magisk/mirror";
@ -131,23 +132,6 @@ public class InstallerInitializer extends Shell.Initializer {
public boolean onInit(@NonNull Context context, @NonNull Shell shell) {
if (!shell.isRoot())
return true;
Shell.Job newJob = shell.newJob();
String MAGISK_PATH = InstallerInitializer.MAGISK_PATH;
if (MAGISK_PATH == null) {
Log.w(TAG, "Unable to detect magisk path!");
} else {
newJob.add("export ASH_STANDALONE=1");
if (!MAGISK_PATH.equals("/sbin") && !MAGISK_SYSTEM.exists()) {
newJob.add("export PATH=" + MAGISK_PATH + ";$PATH;" +
MAGISK_PATH + "/.magisk/busybox");
} else {
newJob.add("export PATH=$PATH;" +
MAGISK_PATH + "/.magisk/busybox");
}
newJob.add("export MAGISKTMP=\"" + MAGISK_PATH + "/.magisk\"");
newJob.add("export BOOTMODE=true");
newJob.add("$(which busybox 2> /dev/null) sh");
}
return newJob.exec().isSuccess();
return shell.newJob().add("export ASH_STANDALONE=1").exec().isSuccess();
}
}

@ -86,8 +86,9 @@ public class RepoData {
for (int i = 0; i < len; i++) {
JSONObject module = array.getJSONObject(i);
String moduleId = module.getString("id");
// Deny remote modules ids shorter than 3 chars
if (moduleId.length() < 3) continue;
// Deny remote modules ids shorter than 3 chars or containing null char or space
if (moduleId.length() < 3 || moduleId.indexOf('\0') != -1 ||
moduleId.indexOf(' ') != -1 || "ak3-helper".equals(moduleId)) continue;
long moduleLastUpdate = module.getLong("last_update");
String moduleNotesUrl = module.getString("notes_url");
String modulePropsUrl = module.getString("prop_url");

@ -9,6 +9,7 @@ import org.json.JSONObject;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -19,7 +20,7 @@ public class RepoUpdater {
public final RepoData repoData;
public byte[] indexRaw;
private List<RepoModule> toUpdate;
private Set<RepoModule> toApply;
private Collection<RepoModule> toApply;
public RepoUpdater(RepoData repoData) {
this.repoData = repoData;
@ -36,7 +37,7 @@ public class RepoUpdater {
if (!this.repoData.prepare()) {
this.indexRaw = null;
this.toUpdate = Collections.emptyList();
this.toApply = Collections.emptySet();
this.toApply = this.repoData.moduleHashMap.values();
return 0;
}
this.indexRaw = Http.doHttpGet(this.repoData.url, false);
@ -60,7 +61,7 @@ public class RepoUpdater {
return this.toUpdate;
}
public Set<RepoModule> toApply() {
public Collection<RepoModule> toApply() {
return this.toApply;
}

@ -187,6 +187,9 @@ public class PropUtils {
moduleInfo.description = value;
readDescription = true;
break;
case "updateJsonAk3":
// Only allow AnyKernel3 helper to use "updateJsonAk3"
if (!"ak3-helper".equals(moduleInfo.id)) break;
case "updateJson":
if (isInvalidURL(value)) break;
moduleInfo.updateJson = value;

Loading…
Cancel
Save