Added "allow insecure request" option (#1825)

This commit is contained in:
Imran Remtulla
2024-09-08 03:58:51 -04:00
parent 19bb9a0331
commit d801994fed
26 changed files with 72 additions and 18 deletions

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Dijeli sa AppVerifier-om, zatim se vratite kada ste spremni.", "appVerifierInstructionToast": "Dijeli sa AppVerifier-om, zatim se vratite kada ste spremni.",
"wiki": "Pomoć/Wiki", "wiki": "Pomoć/Wiki",
"crowdsourcedConfigsLabel": "Konfiguracije aplikacije obezbeđene pomoću velikog broja ljudi (crowdsourcing) (koristite na svoju odgovornost)", "crowdsourcedConfigsLabel": "Konfiguracije aplikacije obezbeđene pomoću velikog broja ljudi (crowdsourcing) (koristite na svoju odgovornost)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?", "one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?" "other": "Želite li ukloniti aplikacije?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.", "appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.",
"wiki": "Nápověda/Wiki", "wiki": "Nápověda/Wiki",
"crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)", "crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)",
"allowInsecure": "Povolení nezabezpečených požadavků HTTP",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Odstranit Apku?", "one": "Odstranit Apku?",
"other": "Odstranit Apky?" "other": "Odstranit Apky?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Del til AppVerifier, og vend tilbage hertil, når du er klar.", "appVerifierInstructionToast": "Del til AppVerifier, og vend tilbage hertil, når du er klar.",
"wiki": "Hjælp/Wiki", "wiki": "Hjælp/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourcede app-konfigurationer (brug på egen risiko)", "crowdsourcedConfigsLabel": "Crowdsourcede app-konfigurationer (brug på egen risiko)",
"allowInsecure": "Tillad usikre HTTP-anmodninger",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Fjern app?", "one": "Fjern app?",
"other": "Fjern apps?" "other": "Fjern apps?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.", "appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.",
"wiki": "Hilfe/Wiki", "wiki": "Hilfe/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App-Konfigurationen (Verwendung auf eigene Gefahr)", "crowdsourcedConfigsLabel": "Crowdsourced App-Konfigurationen (Verwendung auf eigene Gefahr)",
"allowInsecure": "Unsichere HTTP-Anfragen zulassen",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App entfernen?", "one": "App entfernen?",
"other": "Apps entfernen?" "other": "Apps entfernen?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Diskonigu kun AppVerifier, poste revenu ĉi tie kiam preta.", "appVerifierInstructionToast": "Diskonigu kun AppVerifier, poste revenu ĉi tie kiam preta.",
"wiki": "Helpo/Vikio", "wiki": "Helpo/Vikio",
"crowdsourcedConfigsLabel": "Komunumaj apo-agordoj (uzu kun singardo)", "crowdsourcedConfigsLabel": "Komunumaj apo-agordoj (uzu kun singardo)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Forigi la aplikaĵon?", "one": "Forigi la aplikaĵon?",
"other": "Forigi la aplikaĵojn?" "other": "Forigi la aplikaĵojn?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
"wiki": "Help/Wiki", "wiki": "Help/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remove App?", "one": "Remove App?",
"other": "Remove Apps?" "other": "Remove Apps?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.", "appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.",
"wiki": "Ayuda/Wiki", "wiki": "Ayuda/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)",
"allowInsecure": "Permitir peticiones HTTP inseguras",
"removeAppQuestion": { "removeAppQuestion": {
"one": "¿Eliminar aplicación?", "one": "¿Eliminar aplicación?",
"other": "¿Eliminar aplicaciones?" "other": "¿Eliminar aplicaciones?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "در AppVerifier به اشتراک بگذارید، سپس پس از آماده شدن به اینجا برگردید.", "appVerifierInstructionToast": "در AppVerifier به اشتراک بگذارید، سپس پس از آماده شدن به اینجا برگردید.",
"wiki": "راهنما/ویکی", "wiki": "راهنما/ویکی",
"crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)", "crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "برنامه حذف شود؟", "one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟" "other": "برنامه ها حذف شوند؟"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque tout est prêt.", "appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque tout est prêt.",
"wiki": "Aide/Wiki", "wiki": "Aide/Wiki",
"crowdsourcedConfigsLabel": "Configurations d'applications par la communauté (à utiliser à vos risques et périls)", "crowdsourcedConfigsLabel": "Configurations d'applications par la communauté (à utiliser à vos risques et périls)",
"allowInsecure": "Autoriser les requêtes HTTP non sécurisées",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Supprimer l'application?", "one": "Supprimer l'application?",
"other": "Supprimer les applications?" "other": "Supprimer les applications?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.", "appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.",
"wiki": "Súgó/Wiki", "wiki": "Súgó/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App Configurations (használat saját felelősségre)", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (használat saját felelősségre)",
"allowInsecure": "Bizonytalan HTTP-kérések engedélyezése",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?", "one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazásokat?" "other": "Eltávolítja az alkalmazásokat?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.", "appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.",
"wiki": "Aiuto/Wiki", "wiki": "Aiuto/Wiki",
"crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)", "crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)",
"allowInsecure": "Consentire le richieste HTTP non sicure",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Rimuovere l'app?", "one": "Rimuovere l'app?",
"other": "Rimuovere le app?" "other": "Rimuovere le app?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。", "appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。",
"wiki": "ヘルプ/ウィキ", "wiki": "ヘルプ/ウィキ",
"crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)", "crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)",
"allowInsecure": "安全でないHTTPリクエストを許可する",
"removeAppQuestion": { "removeAppQuestion": {
"one": "アプリを削除しますか?", "one": "アプリを削除しますか?",
"other": "アプリを削除しますか?" "other": "アプリを削除しますか?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.", "appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.",
"wiki": "Help/Wiki", "wiki": "Help/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)", "crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)",
"allowInsecure": "Onveilige HTTP-verzoeken toestaan",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App verwijderen?", "one": "App verwijderen?",
"other": "Apps verwijderen?" "other": "Apps verwijderen?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.", "appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.",
"wiki": "Pomoc/Wiki", "wiki": "Pomoc/Wiki",
"crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)", "crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)",
"allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Usunąć aplikację?", "one": "Usunąć aplikację?",
"few": "Usunąć aplikacje?", "few": "Usunąć aplikacje?",

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.", "appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.",
"wiki": "Ajuda/Wiki", "wiki": "Ajuda/Wiki",
"crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)", "crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)",
"allowInsecure": "Permitir pedidos HTTP inseguros",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remover aplicativo?", "one": "Remover aplicativo?",
"other": "Remover aplicativos?" "other": "Remover aplicativos?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.", "appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.",
"wiki": "Помощь/Вики", "wiki": "Помощь/Вики",
"crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)", "crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)",
"allowInsecure": "Разрешить небезопасные HTTP-запросы",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Удалить приложение?", "one": "Удалить приложение?",
"other": "Удалить приложения?" "other": "Удалить приложения?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.", "appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.",
"wiki": "Hjälp/Wiki", "wiki": "Hjälp/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)", "crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)",
"allowInsecure": "Tillåt osäkra HTTP-förfrågningar",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Ta Bort App?", "one": "Ta Bort App?",
"other": "Ta Bort Appar?" "other": "Ta Bort Appar?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.", "appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.",
"wiki": "Yardım/Wiki", "wiki": "Yardım/Wiki",
"crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)", "crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)",
"allowInsecure": "Güvensiz HTTP isteklerine izin ver",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Uygulamayı Kaldır?", "one": "Uygulamayı Kaldır?",
"other": "Uygulamaları Kaldır?" "other": "Uygulamaları Kaldır?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.", "appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.",
"wiki": "Довідка/Вікі", "wiki": "Довідка/Вікі",
"crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)", "crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)",
"allowInsecure": "Дозволити незахищені HTTP-запити",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Видалити застосунок?", "one": "Видалити застосунок?",
"other": "Видалити застосунки?" "other": "Видалити застосунки?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "Chia sẻ lên AppVerifier, sau đó quay lại đây khi sẵn sàng.", "appVerifierInstructionToast": "Chia sẻ lên AppVerifier, sau đó quay lại đây khi sẵn sàng.",
"wiki": "Trợ giúp/Wiki", "wiki": "Trợ giúp/Wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Gỡ ứng dụng?", "one": "Gỡ ứng dụng?",
"other": "Gỡ ứng dụng?" "other": "Gỡ ứng dụng?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "分享至 AppVerifier然後準備好時回到此處。", "appVerifierInstructionToast": "分享至 AppVerifier然後準備好時回到此處。",
"wiki": "幫助/維基", "wiki": "幫助/維基",
"crowdsourcedConfigsLabel": "群眾外包的應用程式設定(使用風險自負)", "crowdsourcedConfigsLabel": "群眾外包的應用程式設定(使用風險自負)",
"allowInsecure": "Allow insecure HTTP requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "移除應用程式?", "one": "移除應用程式?",
"other": "移除應用程式?" "other": "移除應用程式?"

View File

@@ -314,6 +314,7 @@
"appVerifierInstructionToast": "分享至 AppVerifier完成后返回此处。", "appVerifierInstructionToast": "分享至 AppVerifier完成后返回此处。",
"wiki": "帮助/Wiki", "wiki": "帮助/Wiki",
"crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)", "crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)",
"allowInsecure": "允许不安全的 HTTP 请求",
"removeAppQuestion": { "removeAppQuestion": {
"one": "是否删除应用?", "one": "是否删除应用?",
"other": "是否删除应用?" "other": "是否删除应用?"

View File

@@ -26,7 +26,6 @@ class DirectAPKLink extends AppSource {
@override @override
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) { String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
print('AAA');
if (!forSelection) { if (!forSelection) {
return url; return url;
} }

View File

@@ -350,7 +350,8 @@ class HTML extends AppSource {
? rel.hashCode.toString() ? rel.hashCode.toString()
: (await checkPartialDownloadHashDynamic(rel, : (await checkPartialDownloadHashDynamic(rel,
headers: await getRequestHeaders(additionalSettings, headers: await getRequestHeaders(additionalSettings,
forAPKDownload: true))) forAPKDownload: true),
allowInsecure: additionalSettings['allowInsecure'] == true))
.toString(); .toString();
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
AppNames(uri.host, tr('app'))); AppNames(uri.host, tr('app')));

View File

@@ -17,6 +17,7 @@ import 'package:device_info_plus/device_info_plus.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:http/io_client.dart';
import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/components/generated_form_modal.dart'; import 'package:obtainium/components/generated_form_modal.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
@@ -146,17 +147,23 @@ Future<File> downloadFileWithRetry(String url, String fileName,
bool fileNameHasExt, Function? onProgress, String destDir, bool fileNameHasExt, Function? onProgress, String destDir,
{bool useExisting = true, {bool useExisting = true,
Map<String, String>? headers, Map<String, String>? headers,
int retries = 3}) async { int retries = 3,
bool allowInsecure = false}) async {
try { try {
return await downloadFile( return await downloadFile(
url, fileName, fileNameHasExt, onProgress, destDir, url, fileName, fileNameHasExt, onProgress, destDir,
useExisting: useExisting, headers: headers); useExisting: useExisting,
headers: headers,
allowInsecure: allowInsecure);
} catch (e) { } catch (e) {
if (retries > 0 && e is ClientException) { if (retries > 0 && e is ClientException) {
await Future.delayed(const Duration(seconds: 5)); await Future.delayed(const Duration(seconds: 5));
return await downloadFileWithRetry( return await downloadFileWithRetry(
url, fileName, fileNameHasExt, onProgress, destDir, url, fileName, fileNameHasExt, onProgress, destDir,
useExisting: useExisting, headers: headers, retries: (retries - 1)); useExisting: useExisting,
headers: headers,
retries: (retries - 1),
allowInsecure: allowInsecure);
} else { } else {
rethrow; rethrow;
} }
@@ -173,11 +180,14 @@ String hashListOfLists(List<List<int>> data) {
Future<String> checkPartialDownloadHashDynamic(String url, Future<String> checkPartialDownloadHashDynamic(String url,
{int startingSize = 1024, {int startingSize = 1024,
int lowerLimit = 128, int lowerLimit = 128,
Map<String, String>? headers}) async { Map<String, String>? headers,
bool allowInsecure = false}) async {
for (int i = startingSize; i >= lowerLimit; i -= 256) { for (int i = startingSize; i >= lowerLimit; i -= 256) {
List<String> ab = await Future.wait([ List<String> ab = await Future.wait([
checkPartialDownloadHash(url, i, headers: headers), checkPartialDownloadHash(url, i,
checkPartialDownloadHash(url, i, headers: headers) headers: headers, allowInsecure: allowInsecure),
checkPartialDownloadHash(url, i,
headers: headers, allowInsecure: allowInsecure)
]); ]);
if (ab[0] == ab[1]) { if (ab[0] == ab[1]) {
return ab[0]; return ab[0];
@@ -187,13 +197,13 @@ Future<String> checkPartialDownloadHashDynamic(String url,
} }
Future<String> checkPartialDownloadHash(String url, int bytesToGrab, Future<String> checkPartialDownloadHash(String url, int bytesToGrab,
{Map<String, String>? headers}) async { {Map<String, String>? headers, bool allowInsecure = false}) async {
var req = Request('GET', Uri.parse(url)); var req = Request('GET', Uri.parse(url));
if (headers != null) { if (headers != null) {
req.headers.addAll(headers); req.headers.addAll(headers);
} }
req.headers[HttpHeaders.rangeHeader] = 'bytes=0-$bytesToGrab'; req.headers[HttpHeaders.rangeHeader] = 'bytes=0-$bytesToGrab';
var client = http.Client(); var client = IOClient(createHttpClient(allowInsecure));
var response = await client.send(req); var response = await client.send(req);
if (response.statusCode < 200 || response.statusCode > 299) { if (response.statusCode < 200 || response.statusCode > 299) {
throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError'));
@@ -204,12 +214,14 @@ Future<String> checkPartialDownloadHash(String url, int bytesToGrab,
Future<File> downloadFile(String url, String fileName, bool fileNameHasExt, Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
Function? onProgress, String destDir, Function? onProgress, String destDir,
{bool useExisting = true, Map<String, String>? headers}) async { {bool useExisting = true,
Map<String, String>? headers,
bool allowInsecure = false}) async {
// Send the initial request but cancel it as soon as you have the headers // Send the initial request but cancel it as soon as you have the headers
var reqHeaders = headers ?? {}; var reqHeaders = headers ?? {};
var req = Request('GET', Uri.parse(url)); var req = Request('GET', Uri.parse(url));
req.headers.addAll(reqHeaders); req.headers.addAll(reqHeaders);
var client = http.Client(); var client = IOClient(createHttpClient(allowInsecure));
StreamedResponse response = await client.send(req); StreamedResponse response = await client.send(req);
var resHeaders = response.headers; var resHeaders = response.headers;
@@ -275,7 +287,7 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
IOSink? sink; IOSink? sink;
if (rangeFeatureEnabled && fullContentLength != null && rangeStart > 0) { if (rangeFeatureEnabled && fullContentLength != null && rangeStart > 0) {
client.close(); client.close();
client = http.Client(); client = IOClient(createHttpClient(allowInsecure));
req = Request('GET', Uri.parse(url)); req = Request('GET', Uri.parse(url));
req.headers.addAll(reqHeaders); req.headers.addAll(reqHeaders);
req.headers.addAll({'range': 'bytes=$rangeStart-${fullContentLength - 1}'}); req.headers.addAll({'range': 'bytes=$rangeStart-${fullContentLength - 1}'});
@@ -318,12 +330,12 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
} }
Future<Map<String, String>> getHeaders(String url, Future<Map<String, String>> getHeaders(String url,
{Map<String, String>? headers}) async { {Map<String, String>? headers, bool allowInsecure = false}) async {
var req = http.Request('GET', Uri.parse(url)); var req = http.Request('GET', Uri.parse(url));
if (headers != null) { if (headers != null) {
req.headers.addAll(headers); req.headers.addAll(headers);
} }
var client = http.Client(); var client = IOClient(createHttpClient(allowInsecure));
var response = await client.send(req); var response = await client.send(req);
if (response.statusCode < 200 || response.statusCode > 299) { if (response.statusCode < 200 || response.statusCode > 299) {
throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError'));
@@ -468,7 +480,9 @@ class AppsProvider with ChangeNotifier {
notificationsProvider?.notify(notif); notificationsProvider?.notify(notif);
} }
prevProg = prog; prevProg = prog;
}, APKDir.path, useExisting: useExisting); }, APKDir.path,
useExisting: useExisting,
allowInsecure: app.additionalSettings['allowInsecure'] == true);
// Set to 90 for remaining steps, will make null in 'finally' // Set to 90 for remaining steps, will make null in 'finally'
if (apps[app.id] != null) { if (apps[app.id] != null) {
apps[app.id]!.downloadProgress = -1; apps[app.id]!.downloadProgress = -1;
@@ -1036,7 +1050,8 @@ class AppsProvider with ChangeNotifier {
.getRequestHeaders(app.additionalSettings, .getRequestHeaders(app.additionalSettings,
forAPKDownload: forAPKDownload:
fileUrl.key.endsWith('.apk') ? true : false), fileUrl.key.endsWith('.apk') ? true : false),
useExisting: false); useExisting: false,
allowInsecure: app.additionalSettings['allowInsecure'] == true);
notificationsProvider notificationsProvider
.notify(DownloadedNotification(fileUrl.key, fileUrl.value)); .notify(DownloadedNotification(fileUrl.key, fileUrl.value));
} catch (e) { } catch (e) {

View File

@@ -2,11 +2,13 @@
// AppSource is an abstract class with a concrete implementation for each source // AppSource is an abstract class with a concrete implementation for each source
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:html/dom.dart'; import 'package:html/dom.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:http/io_client.dart';
import 'package:obtainium/app_sources/apkmirror.dart'; import 'package:obtainium/app_sources/apkmirror.dart';
import 'package:obtainium/app_sources/apkpure.dart'; import 'package:obtainium/app_sources/apkpure.dart';
import 'package:obtainium/app_sources/aptoide.dart'; import 'package:obtainium/app_sources/aptoide.dart';
@@ -399,6 +401,15 @@ getSourceRegex(List<String> hosts) {
return '(${hosts.join('|').replaceAll('.', '\\.')})'; return '(${hosts.join('|').replaceAll('.', '\\.')})';
} }
HttpClient createHttpClient(bool insecure) {
final client = HttpClient();
if (insecure) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
return client;
}
abstract class AppSource { abstract class AppSource {
List<String> hosts = []; List<String> hosts = [];
bool hostChanged = false; bool hostChanged = false;
@@ -462,7 +473,9 @@ abstract class AppSource {
if (requestHeaders != null) { if (requestHeaders != null) {
req.headers.addAll(requestHeaders); req.headers.addAll(requestHeaders);
} }
return Response.fromStream(await Client().send(req)); return Response.fromStream(await IOClient(
createHttpClient(additionalSettings['allowInsecure'] == true))
.send(req));
} else { } else {
return get(Uri.parse(url)); return get(Uri.parse(url));
} }
@@ -538,6 +551,10 @@ abstract class AppSource {
GeneratedFormSwitch('shizukuPretendToBeGooglePlay', GeneratedFormSwitch('shizukuPretendToBeGooglePlay',
label: tr('shizukuPretendToBeGooglePlay'), defaultValue: false) label: tr('shizukuPretendToBeGooglePlay'), defaultValue: false)
], ],
[
GeneratedFormSwitch('allowInsecure',
label: tr('allowInsecure'), defaultValue: false)
],
[ [
GeneratedFormSwitch('exemptFromBackgroundUpdates', GeneratedFormSwitch('exemptFromBackgroundUpdates',
label: tr('exemptFromBackgroundUpdates')) label: tr('exemptFromBackgroundUpdates'))