Fix: certificate change

Also (hopefully) better handling for user captchas

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/27/head
androidacy-user 3 years ago
parent e3a7420bea
commit b6ce2a62f0

@ -29,8 +29,6 @@ import com.fox2code.mmm.utils.Http;
import com.fox2code.rosettax.LanguageSwitcher; import com.fox2code.rosettax.LanguageSwitcher;
import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.Shell;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
@ -206,6 +204,10 @@ public class MainApplication extends FoxApplication
private FoxThemeWrapper markwonThemeContext; private FoxThemeWrapper markwonThemeContext;
private Markwon markwon; private Markwon markwon;
public static MainApplication getInstance() {
return INSTANCE;
}
public Markwon getMarkwon() { public Markwon getMarkwon() {
if (this.markwon != null) if (this.markwon != null)
return this.markwon; return this.markwon;

@ -103,7 +103,7 @@ public final class AndroidacyRepoData extends RepoData {
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Failed to ping server", e); Log.e(TAG, "Failed to ping server", e);
// Inform user // Inform user
Toast.makeText(MainApplication.getINSTANCE(), R.string.androidacy_server_down, Toast.LENGTH_LONG).show(); new Thread(() -> Toast.makeText(MainApplication.getINSTANCE(), R.string.androidacy_server_down, Toast.LENGTH_LONG).show()).start();
return false; return false;
} }
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();

@ -1,13 +1,18 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils;
import static com.fox2code.mmm.MainApplication.getInstance;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.system.Os; import android.system.Os;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -52,6 +57,7 @@ import okhttp3.dnsoverhttps.DnsOverHttps;
import okio.BufferedSink; import okio.BufferedSink;
public class Http { public class Http {
private static final MainApplication mainApplication = getInstance();
private static final String TAG = "Http"; private static final String TAG = "Http";
private static final OkHttpClient httpClient; private static final OkHttpClient httpClient;
private static final OkHttpClient httpClientDoH; private static final OkHttpClient httpClientDoH;
@ -99,17 +105,7 @@ public class Http {
httpclientBuilder.proxy(Proxy.NO_PROXY); // Do not use system proxy httpclientBuilder.proxy(Proxy.NO_PROXY); // Do not use system proxy
Dns dns = Dns.SYSTEM; Dns dns = Dns.SYSTEM;
try { try {
InetAddress[] cloudflareBootstrap = new InetAddress[]{ InetAddress[] cloudflareBootstrap = new InetAddress[]{InetAddress.getByName("162.159.36.1"), InetAddress.getByName("162.159.46.1"), InetAddress.getByName("1.1.1.1"), InetAddress.getByName("1.0.0.1"), InetAddress.getByName("162.159.132.53"), InetAddress.getByName("2606:4700:4700::1111"), InetAddress.getByName("2606:4700:4700::1001"), InetAddress.getByName("2606:4700:4700::0064"), InetAddress.getByName("2606:4700:4700::6400")};
InetAddress.getByName("162.159.36.1"),
InetAddress.getByName("162.159.46.1"),
InetAddress.getByName("1.1.1.1"),
InetAddress.getByName("1.0.0.1"),
InetAddress.getByName("162.159.132.53"),
InetAddress.getByName("2606:4700:4700::1111"),
InetAddress.getByName("2606:4700:4700::1001"),
InetAddress.getByName("2606:4700:4700::0064"),
InetAddress.getByName("2606:4700:4700::6400")
};
dns = s -> { dns = s -> {
if ("cloudflare-dns.com".equals(s)) { if ("cloudflare-dns.com".equals(s)) {
return Arrays.asList(cloudflareBootstrap); return Arrays.asList(cloudflareBootstrap);
@ -118,21 +114,16 @@ 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( dns = new DnsOverHttps.Builder().client(httpclientBuilder.build()).url(Objects.requireNonNull(HttpUrl.parse("https://cloudflare-dns.com/dns-query"))).bootstrapDnsHosts(cloudflareBootstrap).resolvePrivateAddresses(true).build();
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);
// User-Agent format was agreed on telegram // User-Agent format was agreed on telegram
if (hasWebView) { if (hasWebView) {
androidacyUA = WebSettings.getDefaultUserAgent(mainApplication).replace("wv", "FoxMmm" + androidacyUA = WebSettings.getDefaultUserAgent(mainApplication).replace("wv", "FoxMmm" + "/" + BuildConfig.VERSION_CODE);
"/" + BuildConfig.VERSION_CODE);
} else { } else {
androidacyUA = "Mozilla/5.0 (Linux; Android " + Build.VERSION.RELEASE + "; " + Build.DEVICE + ")" + androidacyUA = "Mozilla/5.0 (Linux; Android " + Build.VERSION.RELEASE + "; " + Build.DEVICE + ")" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36" + " FoxMmm/" + BuildConfig.VERSION_CODE;
" AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36"
+ " FoxMmm/" + BuildConfig.VERSION_CODE;
} }
httpclientBuilder.addInterceptor(chain -> { httpclientBuilder.addInterceptor(chain -> {
Request.Builder request = chain.request().newBuilder(); Request.Builder request = chain.request().newBuilder();
@ -140,8 +131,7 @@ public class Http {
String host = chain.request().url().host(); String host = chain.request().url().host();
if (host.endsWith(".androidacy.com")) { if (host.endsWith(".androidacy.com")) {
request.header("User-Agent", androidacyUA); request.header("User-Agent", androidacyUA);
} else if (!(host.equals("github.com") || host.endsWith(".github.com") || } else if (!(host.equals("github.com") || host.endsWith(".github.com") || host.endsWith(".jsdelivr.net") || host.endsWith(".githubusercontent.com"))) {
host.endsWith(".jsdelivr.net") || host.endsWith(".githubusercontent.com"))) {
if (InstallerInitializer.peekMagiskPath() != null) { if (InstallerInitializer.peekMagiskPath() != null) {
request.header("User-Agent", // Declare Magisk version to the server request.header("User-Agent", // Declare Magisk version to the server
"Magisk/" + InstallerInitializer.peekMagiskVersion()); "Magisk/" + InstallerInitializer.peekMagiskVersion());
@ -154,11 +144,7 @@ public class Http {
return chain.proceed(request.build()); return chain.proceed(request.build());
}); });
// Fallback DNS cache responses in case request fail but already succeeded once in the past // Fallback DNS cache responses in case request fail but already succeeded once in the past
fallbackDNS = new FallBackDNS(mainApplication, dns, fallbackDNS = new FallBackDNS(mainApplication, dns, "github.com", "api.github.com", "raw.githubusercontent.com", "camo.githubusercontent.com", "user-images.githubusercontent.com", "cdn.jsdelivr.net", "img.shields.io", "magisk-modules-repo.github.io", "www.androidacy.com", "api.androidacy.com");
"github.com", "api.github.com", "raw.githubusercontent.com",
"camo.githubusercontent.com", "user-images.githubusercontent.com",
"cdn.jsdelivr.net", "img.shields.io", "magisk-modules-repo.github.io",
"www.androidacy.com", "api.androidacy.com");
httpclientBuilder.cookieJar(cookieJar = new CDNCookieJar(cookieManager)); httpclientBuilder.cookieJar(cookieJar = new CDNCookieJar(cookieManager));
httpclientBuilder.dns(Dns.SYSTEM); httpclientBuilder.dns(Dns.SYSTEM);
httpClient = followRedirects(httpclientBuilder, true).build(); httpClient = followRedirects(httpclientBuilder, true).build();
@ -166,9 +152,7 @@ public class Http {
httpclientBuilder.dns(fallbackDNS); httpclientBuilder.dns(fallbackDNS);
httpClientDoH = followRedirects(httpclientBuilder, true).build(); httpClientDoH = followRedirects(httpclientBuilder, true).build();
httpClientNoRedirectDoH = followRedirects(httpclientBuilder, false).build(); httpClientNoRedirectDoH = followRedirects(httpclientBuilder, false).build();
httpclientBuilder.cache(new Cache( httpclientBuilder.cache(new Cache(new File(mainApplication.getCacheDir(), "http_cache"), 16L * 1024L * 1024L)); // 16Mib of cache
new File(mainApplication.getCacheDir(), "http_cache"),
16L * 1024L * 1024L)); // 16Mib of cache
httpclientBuilder.dns(Dns.SYSTEM); httpclientBuilder.dns(Dns.SYSTEM);
httpClientWithCache = followRedirects(httpclientBuilder, true).build(); httpClientWithCache = followRedirects(httpclientBuilder, true).build();
httpclientBuilder.dns(fallbackDNS); httpclientBuilder.dns(fallbackDNS);
@ -177,10 +161,8 @@ public class Http {
doh = MainApplication.isDohEnabled(); doh = MainApplication.isDohEnabled();
} }
private static OkHttpClient.Builder followRedirects( private static OkHttpClient.Builder followRedirects(OkHttpClient.Builder builder, boolean followRedirects) {
OkHttpClient.Builder builder, boolean followRedirects) { return builder.followRedirects(followRedirects).followSslRedirects(followRedirects);
return builder.followRedirects(followRedirects)
.followSslRedirects(followRedirects);
} }
public static OkHttpClient getHttpClient() { public static OkHttpClient getHttpClient() {
@ -195,26 +177,46 @@ public class Http {
return doh ? httpClientWithCacheDoH : httpClientWithCache; return doh ? httpClientWithCacheDoH : httpClientWithCache;
} }
@SuppressLint("SetJavaScriptEnabled")
public static void captchaWebview(String url) {
if (hasWebView) {
// Open the specified url in a webview
WebView webView = new WebView(mainApplication);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setUserAgentString(androidacyUA);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
// Open the url in the webview
webView.loadUrl(url);
// Show the webview
webView.setVisibility(View.VISIBLE);
} else {
// Throw an exception if the webview is not available
throw new IllegalStateException("Webview is not available");
}
}
@SuppressWarnings("resource") @SuppressWarnings("resource")
public static byte[] doHttpGet(String url, boolean allowCache) throws IOException { public static byte[] doHttpGet(String url, boolean allowCache) throws IOException {
if (!RepoManager.isAndroidacyRepoEnabled() && if (!RepoManager.isAndroidacyRepoEnabled() && AndroidacyUtil.isAndroidacyLink(url)) {
AndroidacyUtil.isAndroidacyLink(url)) {
throw new IOException("Androidacy repo is disabled, blocking url: " + url); throw new IOException("Androidacy repo is disabled, blocking url: " + url);
} }
Response response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall( Response response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).get().build()).execute();
new Request.Builder().url(url).get().build()
).execute();
// 200/204 == success, 304 == cache valid // 200/204 == success, 304 == cache valid
if (response.code() != 200 && response.code() != 204 && if (response.code() != 200 && response.code() != 204 && (response.code() != 304 || !allowCache)) {
(response.code() != 304 || !allowCache)) { // If error is 403 and it's an Androidacy link, it's probably a 403 from Cloudflare
// and we should open a webview to solve the captcha
if (response.code() == 403 && AndroidacyUtil.isAndroidacyLink(url)) {
// Open webview to solve captcha
captchaWebview(url);
}
throw new IOException("Received error code: " + response.code()); throw new IOException("Received error code: " + response.code());
} }
ResponseBody responseBody = response.body(); ResponseBody responseBody = response.body();
// 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) if (response != null) responseBody = response.body();
responseBody = response.body();
} }
return responseBody.bytes(); return responseBody.bytes();
} }
@ -228,44 +230,39 @@ public class Http {
} }
@SuppressWarnings("resource") @SuppressWarnings("resource")
private static Object doHttpPostRaw(String url, String data, boolean allowCache, private static Object doHttpPostRaw(String url, String data, boolean allowCache, boolean isRedirect) throws IOException {
boolean isRedirect) throws IOException { if (!RepoManager.isAndroidacyRepoEnabled() && AndroidacyUtil.isAndroidacyLink(url)) {
if (!RepoManager.isAndroidacyRepoEnabled() &&
AndroidacyUtil.isAndroidacyLink(url)) {
throw new IOException("Androidacy repo is disabled, blocking url: " + url); throw new IOException("Androidacy repo is disabled, blocking url: " + url);
} }
Response response = (isRedirect ? getHttpClientNoRedirect() : Response response = (isRedirect ? getHttpClientNoRedirect() : allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).post(JsonRequestBody.from(data)).header("Content-Type", "application/json").build()).execute();
allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(
new Request.Builder().url(url).post(JsonRequestBody.from(data))
.header("Content-Type", "application/json").build()
).execute();
if (isRedirect && response.isRedirect()) { if (isRedirect && response.isRedirect()) {
return response.request().url().uri().toString(); return response.request().url().uri().toString();
} }
// 200/204 == success, 304 == cache valid // 200/204 == success, 304 == cache valid
if (response.code() != 200 && response.code() != 204 && if (response.code() == 403 && AndroidacyUtil.isAndroidacyLink(url)) {
(response.code() != 304 || !allowCache)) { // Open webview to solve captcha
Log.e(TAG, "Received 403 error code, opening webview to solve captcha");
captchaWebview(url);
} else if (isRedirect) {
return url;
} else if (response.code() != 200 && response.code() != 204 && (response.code() != 304 || !allowCache)) {
throw new IOException("Received error code: " + response.code()); throw new IOException("Received error code: " + response.code());
} }
if (isRedirect) return url;
ResponseBody responseBody = response.body(); ResponseBody responseBody = response.body();
// 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) if (response != null) responseBody = response.body();
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 {
Log.d("Http", "Progress URL: " + url); Log.d("Http", "Progress URL: " + url);
if (!RepoManager.isAndroidacyRepoEnabled() && if (!RepoManager.isAndroidacyRepoEnabled() && AndroidacyUtil.isAndroidacyLink(url)) {
AndroidacyUtil.isAndroidacyLink(url)) {
throw new IOException("Androidacy repo is disabled, blocking url: " + url); throw new IOException("Androidacy repo is disabled, blocking url: " + url);
} }
Response response = getHttpClient().newCall( Response response = getHttpClient().newCall(new Request.Builder().url(url).get().build()).execute();
new Request.Builder().url(url).get().build()).execute();
if (response.code() != 200 && response.code() != 204) { if (response.code() != 200 && response.code() != 204) {
throw new IOException("Received error code: " + response.code()); throw new IOException("Received error code: " + response.code());
} }
@ -334,11 +331,9 @@ public class Http {
public static String updateLink(String string) { public static String updateLink(String string) {
if (string.startsWith("https://cdn.jsdelivr.net/gh/Magisk-Modules-Repo/")) { if (string.startsWith("https://cdn.jsdelivr.net/gh/Magisk-Modules-Repo/")) {
String tmp = string.substring(48); String tmp = string.substring(48);
int start = tmp.lastIndexOf('@'), int start = tmp.lastIndexOf('@'), end = tmp.lastIndexOf('/');
end = tmp.lastIndexOf('/');
if ((end - 8) <= start) return string; // Skip if not a commit id if ((end - 8) <= start) return string; // Skip if not a commit id
return "https://raw.githubusercontent.com/" + return "https://raw.githubusercontent.com/" + tmp.substring(0, start) + "/master" + string.substring(end);
tmp.substring(0, start) + "/master" + string.substring(end);
} }
if (string.startsWith("https://github.com/Magisk-Modules-Repo/")) { if (string.startsWith("https://github.com/Magisk-Modules-Repo/")) {
int i = string.lastIndexOf("/archive/"); int i = string.lastIndexOf("/archive/");
@ -356,16 +351,13 @@ public class Http {
if (string.startsWith("https://raw.githubusercontent.com/")) { if (string.startsWith("https://raw.githubusercontent.com/")) {
String[] tokens = string.substring(34).split("/", 4); String[] tokens = string.substring(34).split("/", 4);
if (tokens.length != 4) return string; if (tokens.length != 4) return string;
return "https://cdn.jsdelivr.net/gh/" + return "https://cdn.jsdelivr.net/gh/" + tokens[0] + "/" + tokens[1] + "@" + tokens[2] + "/" + tokens[3];
tokens[0] + "/" + tokens[1] + "@" + tokens[2] + "/" + tokens[3];
} }
if (string.startsWith("https://github.com/")) { if (string.startsWith("https://github.com/")) {
int i = string.lastIndexOf("/archive/"); int i = string.lastIndexOf("/archive/");
if (i == -1 || string.indexOf('/', i + 9) != -1) if (i == -1 || string.indexOf('/', i + 9) != -1) return string; // Not an archive link
return string; // Not an archive link
String[] tokens = string.substring(19).split("/", 4); String[] tokens = string.substring(19).split("/", 4);
return "https://cdn.jsdelivr.net/gh/" + return "https://cdn.jsdelivr.net/gh/" + tokens[0] + "/" + tokens[1] + "@" + tokens[2] + "/" + tokens[3];
tokens[0] + "/" + tokens[1] + "@" + tokens[2] + "/" + tokens[3];
} }
return string; return string;
} }
@ -418,8 +410,7 @@ public class Http {
return cookieList; return cookieList;
} }
Cookie cookies = cookieMap.get(httpUrl.url().getHost()); Cookie cookies = cookieMap.get(httpUrl.url().getHost());
return cookies == null || cookies.expiresAt() < System.currentTimeMillis() ? return cookies == null || cookies.expiresAt() < System.currentTimeMillis() ? Collections.emptyList() : Collections.singletonList(cookies);
Collections.emptyList() : Collections.singletonList(cookies);
} }
@Override @Override
@ -432,8 +423,7 @@ public class Http {
return; return;
} }
for (Cookie cookie : cookies) { for (Cookie cookie : cookies) {
this.cookieManager.setCookie( this.cookieManager.setCookie(httpUrl.uri().toString(), cookie.toString());
httpUrl.uri().toString(), cookie.toString());
} }
return; return;
} }
@ -442,10 +432,8 @@ public class Http {
Cookie cdnCookie = cookieMap.get(host); Cookie cdnCookie = cookieMap.get(host);
while (cookieIterator.hasNext()) { while (cookieIterator.hasNext()) {
Cookie cookie = cookieIterator.next(); Cookie cookie = cookieIterator.next();
if (host.equals(cookie.domain()) && cookie.secure() && cookie.httpOnly() && if (host.equals(cookie.domain()) && cookie.secure() && cookie.httpOnly() && cookie.expiresAt() < (System.currentTimeMillis() + 1000 * 60 * 60 * 48)) {
cookie.expiresAt() < (System.currentTimeMillis() + 1000 * 60 * 60 * 48)) { if (cdnCookie != null && !cdnCookie.name().equals(cookie.name())) {
if (cdnCookie != null &&
!cdnCookie.name().equals(cookie.name())) {
cookieMap.remove(host); cookieMap.remove(host);
cdnCookie = null; cdnCookie = null;
break; break;
@ -488,8 +476,7 @@ public class Http {
private final HashMap<String, List<InetAddress>> fallbackCache; private final HashMap<String, List<InetAddress>> fallbackCache;
public FallBackDNS(Context context, Dns parent, String... fallbacks) { public FallBackDNS(Context context, Dns parent, String... fallbacks) {
this.sharedPreferences = context.getSharedPreferences( this.sharedPreferences = context.getSharedPreferences("mmm_dns", Context.MODE_PRIVATE);
"mmm_dns", Context.MODE_PRIVATE);
this.parent = parent; this.parent = parent;
this.fallbacks = new HashSet<>(Arrays.asList(fallbacks)); this.fallbacks = new HashSet<>(Arrays.asList(fallbacks));
this.fallbackCache = new HashMap<>(); this.fallbackCache = new HashMap<>();
@ -502,15 +489,13 @@ public class Http {
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()) if (!inetAddressIterator.hasNext()) return stringBuilder.toString();
return stringBuilder.toString();
stringBuilder.append("|"); stringBuilder.append("|");
} }
} }
@NonNull @NonNull
private static List<InetAddress> fromString(@NonNull String string) private static List<InetAddress> fromString(@NonNull String string) throws UnknownHostException {
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);
@ -527,25 +512,21 @@ 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) if (addresses != null) return addresses;
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( this.sharedPreferences.edit().putString(s.replace('.', '_'), toString(addresses)).apply();
s.replace('.', '_'), toString(addresses)).apply();
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
String key = this.sharedPreferences.getString( String key = this.sharedPreferences.getString(s.replace('.', '_'), "");
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( this.sharedPreferences.edit().remove(s.replace('.', '_')).apply();
s.replace('.', '_')).apply();
throw e; throw e;
} }
} }

@ -5,9 +5,5 @@
<trust-anchors> <trust-anchors>
<certificates src="@raw/androidacy_root_ca" /> <certificates src="@raw/androidacy_root_ca" />
</trust-anchors> </trust-anchors>
<pin-set expiration="2023-03-16">
<pin digest="SHA-256">6x/7mHVkS/6XLcenTc5gxonnGPTB1MD5mPQFqHTbfa4=</pin>
<pin digest="SHA-256">Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=</pin>
</pin-set>
</domain-config> </domain-config>
</network-security-config> </network-security-config>
Loading…
Cancel
Save