various tweaks

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/27/head
androidacy-user 3 years ago
parent 30d77941ac
commit 01214cf7f2

@ -54,7 +54,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001 private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001
private static final Shell.Builder shellBuilder; private static final Shell.Builder shellBuilder;
private static final long secret; private static final long secret;
@SuppressLint("RestrictedApi") // Use FoxProcess wrapper helper. @SuppressLint("RestrictedApi")
// Use FoxProcess wrapper helper.
private static final boolean wrapped = !FoxProcessExt.isRootLoader(); private static final boolean wrapped = !FoxProcessExt.isRootLoader();
private static Locale timeFormatLocale = Resources.getSystem().getConfiguration().locale; private static Locale timeFormatLocale = Resources.getSystem().getConfiguration().locale;
private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale); private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale);
@ -63,7 +64,6 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
private static MainApplication INSTANCE; private static MainApplication INSTANCE;
private static boolean firstBoot; private static boolean firstBoot;
private static boolean loadSentryInitialized;
static { static {
Shell.setDefaultBuilder(shellBuilder = Shell.Builder.create().setFlags(Shell.FLAG_REDIRECT_STDERR).setTimeout(10).setInitializers(InstallerInitializer.class)); Shell.setDefaultBuilder(shellBuilder = Shell.Builder.create().setFlags(Shell.FLAG_REDIRECT_STDERR).setTimeout(10).setInitializers(InstallerInitializer.class));
@ -142,7 +142,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
} }
public static boolean isDeveloper() { public static boolean isDeveloper() {
if (BuildConfig.DEBUG) return true; if (BuildConfig.DEBUG)
return true;
return getSharedPreferences().getBoolean("developer", false); return getSharedPreferences().getBoolean("developer", false);
} }
@ -171,9 +172,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
} }
public static boolean isCrashReportingEnabled() { public static boolean isCrashReportingEnabled() {
return SentryMain.IS_SENTRY_INSTALLED && return SentryMain.IS_SENTRY_INSTALLED && getSharedPreferences().getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING);
getSharedPreferences().getBoolean("pref_crash_reporting",
BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING);
} }
public static SharedPreferences getBootSharedPreferences() { public static SharedPreferences getBootSharedPreferences() {
@ -194,7 +193,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
} }
public Markwon getMarkwon() { public Markwon getMarkwon() {
if (this.markwon != null) return this.markwon; if (this.markwon != null)
return this.markwon;
FoxThemeWrapper contextThemeWrapper = this.markwonThemeContext; FoxThemeWrapper contextThemeWrapper = this.markwonThemeContext;
if (contextThemeWrapper == null) { if (contextThemeWrapper == null) {
contextThemeWrapper = this.markwonThemeContext = new FoxThemeWrapper(this, this.managerThemeResId); contextThemeWrapper = this.markwonThemeContext = new FoxThemeWrapper(this, this.managerThemeResId);
@ -276,7 +276,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@Override @Override
public void onCreate() { public void onCreate() {
if (INSTANCE == null) INSTANCE = this; if (INSTANCE == null)
INSTANCE = this;
relPackageName = this.getPackageName(); relPackageName = this.getPackageName();
super.onCreate(); super.onCreate();
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
@ -362,24 +363,30 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
String[] children = cacheDir.list(); String[] children = cacheDir.list();
if (children != null) { if (children != null) {
for (String s : children) { for (String s : children) {
if (BuildConfig.DEBUG) Log.w("MainApplication", "Deleting " + s); if (BuildConfig.DEBUG)
Log.w("MainApplication", "Deleting " + s);
if (!s.equals("lib")) { if (!s.equals("lib")) {
if (!new File(cacheDir, s).delete()) { if (!new File(cacheDir, s).delete()) {
if (BuildConfig.DEBUG) Log.w("MainApplication", "Failed to delete " + s); if (BuildConfig.DEBUG)
Log.w("MainApplication", "Failed to delete " + s);
} }
} }
} }
} }
} }
if (BuildConfig.DEBUG) Log.w("MainApplication", "Deleting cache dir"); if (BuildConfig.DEBUG)
Log.w("MainApplication", "Deleting cache dir");
this.deleteSharedPreferences("mmm_boot"); this.deleteSharedPreferences("mmm_boot");
this.deleteSharedPreferences("mmm"); this.deleteSharedPreferences("mmm");
this.deleteSharedPreferences("sentry"); this.deleteSharedPreferences("sentry");
this.deleteSharedPreferences("androidacy"); this.deleteSharedPreferences("androidacy");
if (BuildConfig.DEBUG) Log.w("MainApplication", "Deleting shared prefs"); if (BuildConfig.DEBUG)
Log.w("MainApplication", "Deleting shared prefs");
this.getPackageManager().clearPackagePreferredActivities(this.getPackageName()); this.getPackageManager().clearPackagePreferredActivities(this.getPackageName());
if (BuildConfig.DEBUG) Log.w("MainApplication", "Done clearing app data"); if (BuildConfig.DEBUG)
} catch (Exception e) { Log.w("MainApplication", "Done clearing app data");
} catch (
Exception e) {
Log.e("MainApplication", "Failed to clear app data", e); Log.e("MainApplication", "Failed to clear app data", e);
} }
} }

@ -1,7 +1,9 @@
package com.fox2code.mmm.androidacy; package com.fox2code.mmm.androidacy;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Looper; import android.net.Uri;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -26,6 +28,8 @@ import org.json.JSONObject;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
@ -64,7 +68,8 @@ public final class AndroidacyRepoData extends RepoData {
if (!modulesJson.createNewFile()) { if (!modulesJson.createNewFile()) {
throw new IOException("Failed to create modules.json"); throw new IOException("Failed to create modules.json");
} }
} catch (IOException e) { } catch (
IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -144,7 +149,8 @@ public final class AndroidacyRepoData extends RepoData {
String deviceId = generateDeviceId(); String deviceId = generateDeviceId();
try { try {
Http.doHttpGet("https://" + this.host + "/auth/me?token=" + token + "&device_id=" + deviceId, false); Http.doHttpGet("https://" + this.host + "/auth/me?token=" + token + "&device_id=" + deviceId, false);
} catch (HttpException e) { } catch (
HttpException e) {
if (e.getErrorCode() == 401) { if (e.getErrorCode() == 401) {
Log.w(TAG, "Invalid token, resetting..."); Log.w(TAG, "Invalid token, resetting...");
// Remove saved preference // Remove saved preference
@ -159,6 +165,7 @@ public final class AndroidacyRepoData extends RepoData {
return true; return true;
} }
@SuppressLint("RestrictedApi")
@Override @Override
protected boolean prepare() throws NoSuchAlgorithmException { protected boolean prepare() throws NoSuchAlgorithmException {
// If ANDROIDACY_CLIENT_ID is not set or is empty, disable this repo and return // If ANDROIDACY_CLIENT_ID is not set or is empty, disable this repo and return
@ -168,28 +175,44 @@ public final class AndroidacyRepoData extends RepoData {
editor.apply(); editor.apply();
return false; return false;
} }
if (Http.needCaptchaAndroidacy()) return false; if (Http.needCaptchaAndroidacy())
return false;
// Implementation details discussed on telegram // Implementation details discussed on telegram
// First, ping the server to check if it's alive // First, ping the server to check if it's alive
try { try {
Http.doHttpGet("https://" + this.host + "/ping", false); HttpURLConnection connection = (HttpURLConnection) new URL("https://" + this.host + "/ping").openConnection();
} catch (Exception e) { connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
if (connection.getResponseCode() != 200 && connection.getResponseCode() != 204) {
// If it's a 400, the app is probably outdated. Show a snackbar suggesting user update app and webview
if (connection.getResponseCode() == 400) {
// Show a dialog using androidacy_update_needed string
new MaterialAlertDialogBuilder(MainApplication.getINSTANCE())
.setTitle(R.string.androidacy_update_needed)
.setMessage(R.string.androidacy_update_needed_message)
.setPositiveButton(R.string.update, (dialog, which) -> {
// Open the app's page on the Play Store
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Fox2Code/FoxMagiskModuleManager/releases/latest"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApplication.getINSTANCE().startActivity(intent);
})
.setNegativeButton(R.string.cancel, null)
.show();
}
return false;
}
} catch (
Exception e) {
Log.e(TAG, "Failed to ping server", e); Log.e(TAG, "Failed to ping server", e);
// Inform user
Looper.prepare();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(MainApplication.getINSTANCE().getBaseContext());
builder.setTitle("Androidacy Server Down");
builder.setMessage("The Androidacy server is down. Unfortunately, this means that you" +
" will not be able to download or view modules from the Androidacy repository" +
". Please try again later.");
builder.setPositiveButton("OK", (dialog, which) -> dialog.dismiss());
builder.show();
Looper.loop();
return false; return false;
} }
String deviceId = generateDeviceId(); String deviceId = generateDeviceId();
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (this.androidacyBlockade > time) return true; // fake it till you make it. Basically, if (this.androidacyBlockade > time)
return true; // fake it till you make it. Basically,
// don'e fail just becaue we're rate limited. API and web rate limits are different. // don'e fail just becaue we're rate limited. API and web rate limits are different.
this.androidacyBlockade = time + 30_000L; this.androidacyBlockade = time + 30_000L;
try { try {
@ -206,7 +229,8 @@ public final class AndroidacyRepoData extends RepoData {
} }
this.token = null; this.token = null;
} }
} catch (IOException e) { } catch (
IOException e) {
if (HttpException.shouldTimeout(e)) { if (HttpException.shouldTimeout(e)) {
Log.e(TAG, "We are being rate limited!", e); Log.e(TAG, "We are being rate limited!", e);
this.androidacyBlockade = time + 3_600_000L; this.androidacyBlockade = time + 3_600_000L;
@ -222,7 +246,8 @@ public final class AndroidacyRepoData extends RepoData {
try { try {
JSONObject jsonObject = new JSONObject(token); JSONObject jsonObject = new JSONObject(token);
token = jsonObject.getString("token"); token = jsonObject.getString("token");
} catch (JSONException e) { } catch (
JSONException e) {
Log.e(TAG, "Failed to parse token", e); Log.e(TAG, "Failed to parse token", e);
// Show a toast // Show a toast
Toast.makeText(MainApplication.getINSTANCE(), R.string.androidacy_failed_to_parse_token, Toast.LENGTH_LONG).show(); Toast.makeText(MainApplication.getINSTANCE(), R.string.androidacy_failed_to_parse_token, Toast.LENGTH_LONG).show();
@ -239,7 +264,8 @@ public final class AndroidacyRepoData extends RepoData {
SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0).edit(); SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0).edit();
editor.putString("pref_androidacy_api_token", token); editor.putString("pref_androidacy_api_token", token);
editor.apply(); editor.apply();
} catch (Exception e) { } catch (
Exception e) {
if (HttpException.shouldTimeout(e)) { if (HttpException.shouldTimeout(e)) {
Log.e(TAG, "We are being rate limited!", e); Log.e(TAG, "We are being rate limited!", e);
this.androidacyBlockade = time + 3_600_000L; this.androidacyBlockade = time + 3_600_000L;
@ -324,7 +350,8 @@ public final class AndroidacyRepoData extends RepoData {
moduleInfo.minMagisk = // Allow 24.1 to mean 24100 moduleInfo.minMagisk = // Allow 24.1 to mean 24100
(Integer.parseInt(minMagisk.substring(0, c)) * 1000) + (Integer.parseInt(minMagisk.substring(c + 1)) * 100); (Integer.parseInt(minMagisk.substring(0, c)) * 1000) + (Integer.parseInt(minMagisk.substring(c + 1)) * 100);
} }
} catch (Exception e) { } catch (
Exception e) {
moduleInfo.minMagisk = 0; moduleInfo.minMagisk = 0;
} }
moduleInfo.needRamdisk = jsonObject.optBoolean("needRamdisk", false); moduleInfo.needRamdisk = jsonObject.optBoolean("needRamdisk", false);
@ -370,13 +397,13 @@ public final class AndroidacyRepoData extends RepoData {
@Override @Override
public String getUrl() throws NoSuchAlgorithmException { public String getUrl() throws NoSuchAlgorithmException {
return this.token == null ? this.url : return this.token == null ? this.url : this.url + "?token=" + this.token + "&v=" + BuildConfig.VERSION_CODE + "&c=" + BuildConfig.VERSION_NAME + "&device_id=" + generateDeviceId();
this.url + "?token=" + this.token + "&v=" + BuildConfig.VERSION_CODE + "&c=" + BuildConfig.VERSION_NAME + "&device_id=" + generateDeviceId();
} }
private String injectToken(String url) throws NoSuchAlgorithmException { private String injectToken(String url) throws NoSuchAlgorithmException {
// Do not inject token for non Androidacy urls // Do not inject token for non Androidacy urls
if (!AndroidacyUtil.isAndroidacyLink(url)) return url; if (!AndroidacyUtil.isAndroidacyLink(url))
return url;
if (this.testMode) { if (this.testMode) {
if (url.startsWith("https://production-api.androidacy.com/")) { if (url.startsWith("https://production-api.androidacy.com/")) {
Log.e(TAG, "Got non test mode url: " + AndroidacyUtil.hideToken(url)); Log.e(TAG, "Got non test mode url: " + AndroidacyUtil.hideToken(url));

@ -19,7 +19,6 @@ import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication; import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.androidacy.AndroidacyUtil; import com.fox2code.mmm.androidacy.AndroidacyUtil;
import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.installer.InstallerInitializer;
import com.fox2code.mmm.repo.RepoManager;
import com.google.net.cronet.okhttptransport.CronetInterceptor; import com.google.net.cronet.okhttptransport.CronetInterceptor;
import org.chromium.net.CronetEngine; import org.chromium.net.CronetEngine;
@ -78,7 +77,8 @@ public class Http {
System.err.flush(); System.err.flush();
try { try {
Os.kill(Os.getpid(), 9); Os.kill(Os.getpid(), 9);
} catch (ErrnoException e) { } catch (
ErrnoException e) {
System.exit(9); System.exit(9);
} }
throw error; throw error;
@ -88,7 +88,8 @@ public class Http {
cookieManager = CookieManager.getInstance(); cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true); cookieManager.setAcceptCookie(true);
cookieManager.flush(); // Make sure the instance work cookieManager.flush(); // Make sure the instance work
} catch (Throwable t) { } catch (
Throwable t) {
cookieManager = null; cookieManager = null;
Log.e(TAG, "No WebView support!", t); Log.e(TAG, "No WebView support!", t);
} }
@ -111,7 +112,9 @@ public class Http {
httpclientBuilder.dns(dns); httpclientBuilder.dns(dns);
httpclientBuilder.cookieJar(new CDNCookieJar()); httpclientBuilder.cookieJar(new CDNCookieJar());
dns = new DnsOverHttps.Builder().client(httpclientBuilder.build()).url(Objects.requireNonNull(HttpUrl.parse("https://cloudflare-dns.com/dns-query"))).bootstrapDnsHosts(cloudflareBootstrap).resolvePrivateAddresses(true).build(); dns = new DnsOverHttps.Builder().client(httpclientBuilder.build()).url(Objects.requireNonNull(HttpUrl.parse("https://cloudflare-dns.com/dns-query"))).bootstrapDnsHosts(cloudflareBootstrap).resolvePrivateAddresses(true).build();
} catch (UnknownHostException | RuntimeException e) { } catch (
UnknownHostException |
RuntimeException e) {
Log.e(TAG, "Failed to init DoH", e); Log.e(TAG, "Failed to init DoH", e);
} }
httpclientBuilder.cookieJar(CookieJar.NO_COOKIES); httpclientBuilder.cookieJar(CookieJar.NO_COOKIES);
@ -165,7 +168,8 @@ public class Http {
builder.addQuicHint("sentry.io", 443, 443); builder.addQuicHint("sentry.io", 443, 443);
CronetEngine engine = builder.build(); CronetEngine engine = builder.build();
httpclientBuilder.addInterceptor(CronetInterceptor.newBuilder(engine).build()); httpclientBuilder.addInterceptor(CronetInterceptor.newBuilder(engine).build());
} catch (Exception e) { } catch (
Exception e) {
Log.e(TAG, "Failed to init cronet", e); Log.e(TAG, "Failed to init cronet", e);
// Gracefully fallback to okhttp // Gracefully fallback to okhttp
} }
@ -205,16 +209,6 @@ public class Http {
} }
} }
private static void checkNeedBlockAndroidacyRequest(String url) throws IOException {
if (!RepoManager.isAndroidacyRepoEnabled()) {
if (AndroidacyUtil.isAndroidacyLink(url)) {
throw new IOException("Androidacy repo is disabled, blocking url: " + url);
}
} else if (needCaptchaAndroidacy() && AndroidacyUtil.isAndroidacyLink(url)) {
throw new HttpException("Androidacy require the user to solve a captcha", 403);
}
}
public static boolean needCaptchaAndroidacy() { public static boolean needCaptchaAndroidacy() {
return needCaptchaAndroidacyHost != null; return needCaptchaAndroidacyHost != null;
} }
@ -246,7 +240,8 @@ public class Http {
// Use cache api if used cached response // Use cache api if used cached response
if (response.code() == 304) { if (response.code() == 304) {
response = response.cacheResponse(); response = response.cacheResponse();
if (response != null) responseBody = response.body(); if (response != null)
responseBody = response.body();
} }
return responseBody.bytes(); return responseBody.bytes();
} }
@ -257,7 +252,8 @@ public class Http {
@SuppressWarnings("resource") @SuppressWarnings("resource")
private static Object doHttpPostRaw(String url, String data, boolean allowCache) throws IOException { private static Object doHttpPostRaw(String url, String data, boolean allowCache) throws IOException {
if (BuildConfig.DEBUG) Log.i(TAG, "POST " + url + " " + data); if (BuildConfig.DEBUG)
Log.i(TAG, "POST " + url + " " + data);
Response response; Response response;
response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).post(JsonRequestBody.from(data)).header("Content-Type", "application/json").build()).execute(); response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).post(JsonRequestBody.from(data)).header("Content-Type", "application/json").build()).execute();
if (response.isRedirect()) { if (response.isRedirect()) {
@ -274,13 +270,15 @@ public class Http {
// Use cache api if used cached response // Use cache api if used cached response
if (response.code() == 304) { if (response.code() == 304) {
response = response.cacheResponse(); response = response.cacheResponse();
if (response != null) responseBody = response.body(); if (response != null)
responseBody = response.body();
} }
return responseBody.bytes(); return responseBody.bytes();
} }
public static byte[] doHttpGet(String url, ProgressListener progressListener) throws IOException { public static byte[] doHttpGet(String url, ProgressListener progressListener) throws IOException {
if (BuildConfig.DEBUG) Log.i("Http", "GET " + url.split("\\?")[0]); if (BuildConfig.DEBUG)
Log.i("Http", "GET " + url.split("\\?")[0]);
Response response = getHttpClient().newCall(new Request.Builder().url(url).get().build()).execute(); Response response = getHttpClient().newCall(new Request.Builder().url(url).get().build()).execute();
if (response.code() != 200 && response.code() != 204) { if (response.code() != 200 && response.code() != 204) {
Log.e(TAG, "Failed to fetch " + url + ", code: " + response.code()); Log.e(TAG, "Failed to fetch " + url + ", code: " + response.code());
@ -304,7 +302,8 @@ public class Http {
progressListener.onUpdate(0, (int) (target / divider), false); progressListener.onUpdate(0, (int) (target / divider), false);
while (true) { while (true) {
int read = inputStream.read(buff); int read = inputStream.read(buff);
if (read == -1) break; if (read == -1)
break;
byteArrayOutputStream.write(buff, 0, read); byteArrayOutputStream.write(buff, 0, read);
downloaded += read; downloaded += read;
currentUpdate = System.currentTimeMillis(); currentUpdate = System.currentTimeMillis();
@ -420,11 +419,14 @@ public class Http {
@NonNull @NonNull
@Override @Override
public List<Cookie> loadForRequest(@NonNull HttpUrl httpUrl) { public List<Cookie> loadForRequest(@NonNull HttpUrl httpUrl) {
if (!httpUrl.isHttps()) return Collections.emptyList(); if (!httpUrl.isHttps())
return Collections.emptyList();
if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) { if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) {
if (this.cookieManager == null) return this.androidacyCookies; if (this.cookieManager == null)
return this.androidacyCookies;
String cookies = this.cookieManager.getCookie(httpUrl.uri().toString()); String cookies = this.cookieManager.getCookie(httpUrl.uri().toString());
if (cookies == null || cookies.isEmpty()) return Collections.emptyList(); if (cookies == null || cookies.isEmpty())
return Collections.emptyList();
String[] splitCookies = cookies.split(";"); String[] splitCookies = cookies.split(";");
ArrayList<Cookie> cookieList = new ArrayList<>(splitCookies.length); ArrayList<Cookie> cookieList = new ArrayList<>(splitCookies.length);
for (String cookie : splitCookies) { for (String cookie : splitCookies) {
@ -438,7 +440,8 @@ public class Http {
@Override @Override
public void saveFromResponse(@NonNull HttpUrl httpUrl, @NonNull List<Cookie> cookies) { public void saveFromResponse(@NonNull HttpUrl httpUrl, @NonNull List<Cookie> cookies) {
if (!httpUrl.isHttps()) return; if (!httpUrl.isHttps())
return;
if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) { if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) {
if (this.cookieManager == null) { if (this.cookieManager == null) {
if (httpUrl.host().equals(".androidacy.com") || !cookies.isEmpty()) if (httpUrl.host().equals(".androidacy.com") || !cookies.isEmpty())
@ -496,19 +499,22 @@ public class Http {
@NonNull @NonNull
private static String toString(@NonNull List<InetAddress> inetAddresses) { private static String toString(@NonNull List<InetAddress> inetAddresses) {
if (inetAddresses.isEmpty()) return ""; if (inetAddresses.isEmpty())
return "";
Iterator<InetAddress> inetAddressIterator = inetAddresses.iterator(); Iterator<InetAddress> inetAddressIterator = inetAddresses.iterator();
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
while (true) { while (true) {
stringBuilder.append(inetAddressIterator.next().getHostAddress()); stringBuilder.append(inetAddressIterator.next().getHostAddress());
if (!inetAddressIterator.hasNext()) return stringBuilder.toString(); if (!inetAddressIterator.hasNext())
return stringBuilder.toString();
stringBuilder.append("|"); stringBuilder.append("|");
} }
} }
@NonNull @NonNull
private static List<InetAddress> fromString(@NonNull String string) throws UnknownHostException { private static List<InetAddress> fromString(@NonNull String string) throws UnknownHostException {
if (string.isEmpty()) return Collections.emptyList(); if (string.isEmpty())
return Collections.emptyList();
String[] strings = string.split("\\|"); String[] strings = string.split("\\|");
ArrayList<InetAddress> inetAddresses = new ArrayList<>(strings.length); ArrayList<InetAddress> inetAddresses = new ArrayList<>(strings.length);
for (String address : strings) { for (String address : strings) {
@ -524,20 +530,24 @@ public class Http {
List<InetAddress> addresses; List<InetAddress> addresses;
synchronized (this.fallbackCache) { synchronized (this.fallbackCache) {
addresses = this.fallbackCache.get(s); addresses = this.fallbackCache.get(s);
if (addresses != null) return addresses; if (addresses != null)
return addresses;
try { try {
addresses = this.parent.lookup(s); addresses = this.parent.lookup(s);
if (addresses.isEmpty() || addresses.get(0).isLoopbackAddress()) if (addresses.isEmpty() || addresses.get(0).isLoopbackAddress())
throw new UnknownHostException(s); throw new UnknownHostException(s);
this.fallbackCache.put(s, addresses); this.fallbackCache.put(s, addresses);
this.sharedPreferences.edit().putString(s.replace('.', '_'), toString(addresses)).apply(); this.sharedPreferences.edit().putString(s.replace('.', '_'), toString(addresses)).apply();
} catch (UnknownHostException e) { } catch (
UnknownHostException e) {
String key = this.sharedPreferences.getString(s.replace('.', '_'), ""); String key = this.sharedPreferences.getString(s.replace('.', '_'), "");
if (key.isEmpty()) throw e; if (key.isEmpty())
throw e;
try { try {
addresses = fromString(key); addresses = fromString(key);
this.fallbackCache.put(s, addresses); this.fallbackCache.put(s, addresses);
} catch (UnknownHostException e2) { } catch (
UnknownHostException e2) {
this.sharedPreferences.edit().remove(s.replace('.', '_')).apply(); this.sharedPreferences.edit().remove(s.replace('.', '_')).apply();
throw e; throw e;
} }

@ -248,5 +248,12 @@
<string name="debug_build">This is a debug build. Expect some bugs and worse performance.</string> <string name="debug_build">This is a debug build. Expect some bugs and worse performance.</string>
<string name="androidacy_repo_name">Androidacy Repo</string> <string name="androidacy_repo_name">Androidacy Repo</string>
<string name="magisk_alt_repo_name">Magisk Alt Repo</string> <string name="magisk_alt_repo_name">Magisk Alt Repo</string>
<string name="repo_enabled_changed">You\'ve enabled or disabled a repo. Please refresh the module list or restart the app.</string><string name="finish">Finish</string><string name="setup_theme">Choose a theme</string><string name="setup_theme_header">Choose a theme</string><string name="setup_theme_system">System theme</string><string name="setup_theme_light">Light theme</string><string name="setup_theme_dark">Dark theme</string><string name="setup_theme_black">AMOLED Black theme</string><string name="setup_theme_transparent_light">Transparent light theme - will disable monet and blur!</string><string name="setup_theme_button">Choose a theme</string><string name="theme">Theme</string><string name="theme_system">System</string><string name="theme_dark">Dark</string><string name="theme_black">AMOLED Black</string><string name="theme_transparent_light">Light (transparency)</string><string name="theme_light">Light</string> <string name="repo_enabled_changed">You\'ve enabled or disabled a repo. Please refresh the module list or restart the app.</string><string name="finish">Finish</string><string name="setup_theme">Choose a theme</string><string name="setup_theme_header">Choose a theme</string><string name="setup_theme_system">System theme</string><string name="setup_theme_light">Light theme</string><string name="setup_theme_dark">Dark theme</string><string name="setup_theme_black">AMOLED Black theme</string><string name="setup_theme_transparent_light">Transparent light theme - will disable monet and blur!</string><string name="setup_theme_button">Choose a theme</string><string name="theme">Theme</string><string name="theme_system">System</string>
<string name="theme_dark">Dark</string>
<string name="theme_black">AMOLED Black</string>
<string name="theme_transparent_light">Light (transparency)</string>
<string name="theme_light">Light</string>
<string name="androidacy_update_needed">This app is outdated.</string>
<string name="androidacy_update_needed_message">Please update the app to the latest version.</string>
<string name="androidacy_webview_update_required">Your webview is outdated! Please update it.</string>
</resources> </resources>

Loading…
Cancel
Save