Try fixing staging Androidacy. (And fail)

pull/186/head
Fox2Code 2 years ago
parent c63f0b75a2
commit ded15c0194

@ -16,7 +16,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.cardview.widget.CardView;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

@ -17,16 +17,10 @@ import androidx.annotation.StyleRes;
import androidx.emoji2.text.DefaultEmojiCompatConfig;
import androidx.emoji2.text.EmojiCompat;
import androidx.emoji2.text.FontRequestEmojiCompatConfig;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import com.fox2code.foxcompat.FoxActivity;
import com.fox2code.foxcompat.FoxApplication;
import com.fox2code.foxcompat.FoxThemeWrapper;
import com.fox2code.mmm.background.BackgroundUpdateChecker;
import com.fox2code.mmm.installer.InstallerInitializer;
import com.fox2code.mmm.utils.GMSProviderInstaller;
import com.fox2code.mmm.utils.Http;
@ -37,7 +31,6 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import io.noties.markwon.Markwon;
import io.noties.markwon.html.HtmlPlugin;

@ -8,7 +8,6 @@ import android.webkit.WebView;
import androidx.annotation.Keep;
import com.fox2code.mmm.manager.ModuleManager;
import com.fox2code.mmm.repo.RepoData;
import com.fox2code.mmm.repo.RepoManager;
/**

@ -31,9 +31,14 @@ import com.fox2code.mmm.Constants;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.XHooks;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.IntentHelper;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.HashMap;
/**
@ -134,6 +139,8 @@ public class AndroidacyActivity extends FoxActivity {
// Don't open non Androidacy urls inside WebView
if (request.isForMainFrame() &&
!AndroidacyUtil.isAndroidacyLink(request.getUrl())) {
Log.i(TAG, "Exiting WebView " + // hideToken in case isAndroidacyLink fail.
AndroidacyUtil.hideToken(request.getUrl().toString()));
IntentHelper.openUri(view.getContext(), request.getUrl().toString());
return true;
}
@ -152,6 +159,7 @@ public class AndroidacyActivity extends FoxActivity {
private void onReceivedError(String url, int errorCode) {
if ((url.startsWith("https://api.androidacy.com/magisk/") ||
url.startsWith("https://staging-api.androidacy.com/magisk/") ||
url.equals(pageUrl)) && (errorCode == 419 || errorCode == 429 || errorCode == 503)) {
Toast.makeText(AndroidacyActivity.this,
"Too many requests!", Toast.LENGTH_LONG).show();
@ -188,38 +196,89 @@ public class AndroidacyActivity extends FoxActivity {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
switch (consoleMessage.messageLevel()) {
case TIP:
Log.v(TAG, consoleMessage.message());
break;
case LOG:
Log.i(TAG, consoleMessage.message());
break;
case WARNING:
Log.w(TAG, consoleMessage.message());
break;
case ERROR:
Log.e(TAG, consoleMessage.message());
break;
case DEBUG:
Log.d(TAG, consoleMessage.message());
break;
if (BuildConfig.DEBUG) {
switch (consoleMessage.messageLevel()) {
case TIP:
Log.v(TAG, consoleMessage.message());
break;
case LOG:
Log.i(TAG, consoleMessage.message());
break;
case WARNING:
Log.w(TAG, consoleMessage.message());
break;
case ERROR:
Log.e(TAG, consoleMessage.message());
break;
case DEBUG:
Log.d(TAG, consoleMessage.message());
break;
}
}
return super.onConsoleMessage(consoleMessage);
}
});
this.webView.setDownloadListener((
downloadUrl, userAgent, contentDisposition, mimetype, contentLength) -> {
if (AndroidacyUtil.isAndroidacyLink(downloadUrl)) {
if (AndroidacyUtil.isAndroidacyLink(downloadUrl) && !this.backOnResume) {
AndroidacyWebAPI androidacyWebAPI = this.androidacyWebAPI;
if (androidacyWebAPI != null) {
if (androidacyWebAPI.consumedAction && !androidacyWebAPI.downloadMode) {
return; // Native module popup may cause download after consumed action
if (!androidacyWebAPI.downloadMode) {
if (androidacyWebAPI.consumedAction)
return; // Native module popup may cause download after consumed action
int lenPrefix = 0;
// Workaround WebView/Chromium bug
for (String prefix : new String[]{
"https://api.androidacy.com/magisk/download/",
"https://staging-api.androidacy.com/magisk/download/"
}) { // Make both staging and non staging act the same
if (downloadUrl.startsWith(prefix)) lenPrefix = prefix.length();
}
if (lenPrefix != 0) {
final String moduleId = downloadUrl.substring(lenPrefix);
webView.evaluateJavascript("document.querySelector(" +
"\"#download-form input[name=_token]\").value",
result -> new Thread("Androidacy popup workaround thread") {
@Override
public void run() {
if (androidacyWebAPI.consumedAction) return;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("moduleId", moduleId);
jsonObject.put("token", RepoManager.getINSTANCE()
.getAndroidacyRepoData().getToken());
jsonObject.put("_token", result);
String realUrl = Http.doHttpPostRedirect(downloadUrl,
jsonObject.toString(), true);
if (downloadUrl.equals(realUrl)) {
Log.e(TAG, "Failed to resolve URL");
return;
}
Log.i(TAG, "Got url: " + realUrl);
androidacyWebAPI.openNativeModuleDialogRaw(realUrl,
moduleId, "", androidacyWebAPI.canInstall());
} catch (IOException | JSONException e) {
Log.e(TAG, "Failed redirect intercept", e);
}
}
}.start());
return;
}
}
androidacyWebAPI.consumedAction = true;
androidacyWebAPI.downloadMode = false;
} else if (this.backOnResume) return;
}
this.backOnResume = true;
Log.i(TAG, "Exiting WebView " +
AndroidacyUtil.hideToken(downloadUrl));
for (String prefix : new String[]{
"https://api.androidacy.com/magisk/download/",
"https://staging-api.androidacy.com/magisk/download/"
}) {
if (downloadUrl.startsWith(prefix)) {
return;
}
}
IntentHelper.openCustomTab(this, downloadUrl);
}
});

@ -29,7 +29,7 @@ import okhttp3.Cookie;
import okhttp3.HttpUrl;
@SuppressWarnings("KotlinInternalInJava")
public class AndroidacyRepoData extends RepoData {
public final class AndroidacyRepoData extends RepoData {
private static final String TAG = "AndroidacyRepoData";
private static final HttpUrl OK_HTTP_URL;
static {
@ -284,6 +284,10 @@ public class AndroidacyRepoData extends RepoData {
// Do not inject token for non Androidacy urls
if (!AndroidacyUtil.isAndroidacyLink(url))
return url;
if (this.testMode && url.startsWith("https://api.androidacy.com/")) {
Log.e(TAG, "Got non test mode url: " + AndroidacyUtil.hideToken(url));
url = "https://staging-api.androidacy.com/" + url.substring(27);
}
String token = "token=" + this.token;
if (!url.contains(token)) {
if (url.lastIndexOf('/') < url.lastIndexOf('?')) {
@ -300,4 +304,8 @@ public class AndroidacyRepoData extends RepoData {
public String getName() {
return this.testMode ? super.getName() + " (Test Mode)" : super.getName();
}
String getToken() {
return this.token;
}
}

@ -23,4 +23,18 @@ public class AndroidacyUtil {
url.substring(8, i).endsWith(".androidacy.com") &&
uri.getHost().endsWith(".androidacy.com");
}
// Avoid logging token
public static String hideToken(@NonNull String url) {
int i = url.lastIndexOf("token=");
if (i == -1) return url;
int i2 = url.indexOf('&', i);
if (i2 == -1) {
return url.substring(0, i + 6) +
"<token>";
} else {
return url.substring(0, i + 6) +
"<token>" + url.substring(i2);
}
}
}

@ -37,6 +37,8 @@ import java.nio.charset.StandardCharsets;
@Keep
public class AndroidacyWebAPI {
public static final int COMPAT_UNSUPPORTED = 0;
public static final int COMPAT_DOWNLOAD = 1;
private static final String TAG = "AndroidacyWebAPI";
private static final int MAX_COMPAT_MODE = 1;
private final AndroidacyActivity activity;
@ -46,6 +48,8 @@ public class AndroidacyWebAPI {
boolean downloadMode;
int effectiveCompatMode;
int notifiedCompatMode;
String nonceToken;
Runnable nonceTask;
public AndroidacyWebAPI(AndroidacyActivity activity, boolean allowInstall) {
this.activity = activity;
@ -505,15 +509,25 @@ public class AndroidacyWebAPI {
}
}
@JavascriptInterface
public void setNonceToken(String nonceToken) {
this.nonceToken = nonceToken;
Runnable nonceTask = this.nonceTask;
if (nonceTask != null) {
this.nonceTask = null;
nonceTask.run();
}
}
// Androidacy feature level declaration method
@JavascriptInterface
public void notifyCompatUnsupported() {
this.notifyCompatModeRaw(0);
this.notifyCompatModeRaw(COMPAT_UNSUPPORTED);
}
@JavascriptInterface
public void notifyCompatDownloadButton() {
this.notifyCompatModeRaw(1);
this.notifyCompatModeRaw(COMPAT_DOWNLOAD);
}
}

@ -10,7 +10,6 @@ import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
public final class CustomRepoData extends RepoData {
boolean loadedExternal;

@ -47,10 +47,9 @@ public class RepoData extends XRepo {
this.cachedPreferences = cachedPreferences;
this.metaDataCache = new File(cacheRoot, "modules.json");
this.moduleHashMap = new HashMap<>();
this.name = this.url; // Set url as default name
this.defaultName = url; // Set url as default name
this.enabled = !this.isLimited() && MainApplication.getSharedPreferences()
.getBoolean("pref_" + this.id + "_enabled", this.isEnabledByDefault());
this.defaultName = url;
this.defaultWebsite = "https://" + Uri.parse(url).getHost() + "/";
if (!this.cacheRoot.isDirectory()) {
this.cacheRoot.mkdirs();

@ -4,7 +4,6 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.XHooks;
import com.fox2code.mmm.androidacy.AndroidacyRepoData;
@ -92,7 +91,11 @@ public final class RepoManager {
this.androidacyRepoData = this.addAndroidacyRepoData();
this.customRepoManager = new CustomRepoManager(mainApplication, this);
// Populate default cache
boolean x = false;
for (RepoData repoData:this.repoData.values()) {
if (repoData == this.androidacyRepoData) {
if (x) return; x = true;
}
this.populateDefaultCache(repoData);
}
this.initialized = true;
@ -319,12 +322,12 @@ public final class RepoManager {
new CustomRepoData(url, cacheRoot, sharedPreferences) :
new RepoData(url, cacheRoot, sharedPreferences);
if (fallBackName != null && !fallBackName.isEmpty()) {
repoData.defaultName = fallBackName;
if (repoData instanceof CustomRepoData) {
((CustomRepoData) repoData).loadedExternal = true;
this.customRepoManager.dirty = true;
repoData.updateEnabledState();
}
repoData.defaultName = fallBackName;
}
switch (url) {
case MAGISK_REPO:

@ -13,7 +13,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class RepoUpdater {
private static final String TAG = "RepoUpdater";

@ -2,7 +2,6 @@ package com.fox2code.mmm.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
@ -55,6 +54,8 @@ public class Http {
private static final OkHttpClient httpClientDoH;
private static final OkHttpClient httpClientWithCache;
private static final OkHttpClient httpClientWithCacheDoH;
private static final OkHttpClient httpClientNoRedirect;
private static final OkHttpClient httpClientNoRedirectDoH;
private static final FallBackDNS fallbackDNS;
private static final CookieJar cookieJar;
private static final String androidacyUA;
@ -152,24 +153,36 @@ public class Http {
hasWebView = cookieManager != null;
httpclientBuilder.cookieJar(cookieJar = new CDNCookieJar(cookieManager));
httpclientBuilder.dns(Dns.SYSTEM);
httpClient = httpclientBuilder.build();
httpClient = followRedirects(httpclientBuilder, true).build();
httpClientNoRedirect = followRedirects(httpclientBuilder, false).build();
httpclientBuilder.dns(fallbackDNS);
httpClientDoH = httpclientBuilder.build();
httpClientDoH = followRedirects(httpclientBuilder, true).build();
httpClientNoRedirectDoH = followRedirects(httpclientBuilder, false).build();
httpclientBuilder.cache(new Cache(
new File(mainApplication.getCacheDir(), "http_cache"),
16L * 1024L * 1024L)); // 16Mib of cache
httpclientBuilder.dns(Dns.SYSTEM);
httpClientWithCache = httpclientBuilder.build();
httpClientWithCache = followRedirects(httpclientBuilder, true).build();
httpclientBuilder.dns(fallbackDNS);
httpClientWithCacheDoH = httpclientBuilder.build();
httpClientWithCacheDoH = followRedirects(httpclientBuilder, true).build();
Log.i(TAG, "Initialized Http successfully!");
doh = MainApplication.isDohEnabled();
}
private static OkHttpClient.Builder followRedirects(
OkHttpClient.Builder builder, boolean followRedirects) {
return builder.followRedirects(followRedirects)
.followSslRedirects(followRedirects);
}
public static OkHttpClient getHttpClient() {
return doh ? httpClientDoH : httpClient;
}
public static OkHttpClient getHttpClientNoRedirect() {
return doh ? httpClientNoRedirectDoH : httpClientNoRedirect;
}
public static OkHttpClient getHttpClientWithCache() {
return doh ? httpClientWithCacheDoH : httpClientWithCache;
}
@ -194,15 +207,29 @@ public class Http {
}
public static byte[] doHttpPost(String url,String data,boolean allowCache) throws IOException {
Response response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(
return (byte[]) doHttpPostRaw(url, data, allowCache, false);
}
public static String doHttpPostRedirect(String url, String data, boolean allowCache) throws IOException {
return (String) doHttpPostRaw(url, data, allowCache, true);
}
private static Object doHttpPostRaw(String url,String data, boolean allowCache,
boolean isRedirect) throws IOException {
Response response = (isRedirect ? getHttpClientNoRedirect() :
allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(
new Request.Builder().url(url).post(JsonRequestBody.from(data))
.header("Content-Type", "application/json").build()
).execute();
if (isRedirect && response.isRedirect()) {
return response.request().url().uri().toString();
}
// 200/204 == success, 304 == cache valid
if (response.code() != 200 && response.code() != 204 &&
(response.code() != 304 || !allowCache)) {
throw new IOException("Received error code: "+ response.code());
}
if (isRedirect) return url;
ResponseBody responseBody = response.body();
// Use cache api if used cached response
if (responseBody == null && response.code() == 304) {

Loading…
Cancel
Save