From d801994fed674404683c259313a30a29d83625dd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 8 Sep 2024 03:58:51 -0400 Subject: [PATCH] Added "allow insecure request" option (#1825) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/da.json | 1 + assets/translations/de.json | 1 + assets/translations/en-EO.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/nl.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/sv.json | 1 + assets/translations/tr.json | 1 + assets/translations/uk.json | 1 + assets/translations/vi.json | 1 + assets/translations/zh-Hant-TW.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/directAPKLink.dart | 1 - lib/app_sources/html.dart | 3 +- lib/providers/apps_provider.dart | 45 +++++++++++++++++++---------- lib/providers/source_provider.dart | 19 +++++++++++- 26 files changed, 72 insertions(+), 18 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7868a31..b08151c 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Dijeli sa AppVerifier-om, zatim se vratite kada ste spremni.", "wiki": "Pomoć/Wiki", "crowdsourcedConfigsLabel": "Konfiguracije aplikacije obezbeđene pomoću velikog broja ljudi (crowdsourcing) (koristite na svoju odgovornost)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 537960c..11552ce 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.", "wiki": "Nápověda/Wiki", "crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)", + "allowInsecure": "Povolení nezabezpečených požadavků HTTP", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/da.json b/assets/translations/da.json index db918d0..7bc0450 100644 --- a/assets/translations/da.json +++ b/assets/translations/da.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Del til AppVerifier, og vend tilbage hertil, når du er klar.", "wiki": "Hjælp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourcede app-konfigurationer (brug på egen risiko)", + "allowInsecure": "Tillad usikre HTTP-anmodninger", "removeAppQuestion": { "one": "Fjern app?", "other": "Fjern apps?" diff --git a/assets/translations/de.json b/assets/translations/de.json index e199f6a..425b22d 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.", "wiki": "Hilfe/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App-Konfigurationen (Verwendung auf eigene Gefahr)", + "allowInsecure": "Unsichere HTTP-Anfragen zulassen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en-EO.json b/assets/translations/en-EO.json index 43b071f..4d14b33 100644 --- a/assets/translations/en-EO.json +++ b/assets/translations/en-EO.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Diskonigu kun AppVerifier, poste revenu ĉi tie kiam preta.", "wiki": "Helpo/Vikio", "crowdsourcedConfigsLabel": "Komunumaj apo-agordoj (uzu kun singardo)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "Forigi la aplikaĵon?", "other": "Forigi la aplikaĵojn?" diff --git a/assets/translations/en.json b/assets/translations/en.json index a0eba80..cea5156 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "wiki": "Help/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index d80c5e9..1899fc2 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.", "wiki": "Ayuda/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)", + "allowInsecure": "Permitir peticiones HTTP inseguras", "removeAppQuestion": { "one": "¿Eliminar aplicación?", "other": "¿Eliminar aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 4c88c0f..1c1c7cc 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "در AppVerifier به اشتراک بگذارید، سپس پس از آماده شدن به اینجا برگردید.", "wiki": "راهنما/ویکی", "crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 965d79d..8b4dab6 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque tout est prêt.", "wiki": "Aide/Wiki", "crowdsourcedConfigsLabel": "Configurations d'applications par la communauté (à utiliser à vos risques et périls)", + "allowInsecure": "Autoriser les requêtes HTTP non sécurisées", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index ad09e14..469e91e 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.", "wiki": "Súgó/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (használat saját felelősségre)", + "allowInsecure": "Bizonytalan HTTP-kérések engedélyezése", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazásokat?" diff --git a/assets/translations/it.json b/assets/translations/it.json index 6c79886..3d930d3 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.", "wiki": "Aiuto/Wiki", "crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)", + "allowInsecure": "Consentire le richieste HTTP non sicure", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 797b38b..1c58b3a 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。", "wiki": "ヘルプ/ウィキ", "crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)", + "allowInsecure": "安全でないHTTPリクエストを許可する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index 039f7cc..543f953 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.", "wiki": "Help/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)", + "allowInsecure": "Onveilige HTTP-verzoeken toestaan", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 7297882..3e64f8d 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.", "wiki": "Pomoc/Wiki", "crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)", + "allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index d0ff541..0012515 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.", "wiki": "Ajuda/Wiki", "crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)", + "allowInsecure": "Permitir pedidos HTTP inseguros", "removeAppQuestion": { "one": "Remover aplicativo?", "other": "Remover aplicativos?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ec8f603..5bd4b93 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.", "wiki": "Помощь/Вики", "crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)", + "allowInsecure": "Разрешить небезопасные HTTP-запросы", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 56dfd9d..490cbc3 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.", "wiki": "Hjälp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)", + "allowInsecure": "Tillåt osäkra HTTP-förfrågningar", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 7243da0..745d59f 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.", "wiki": "Yardım/Wiki", "crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)", + "allowInsecure": "Güvensiz HTTP isteklerine izin ver", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/uk.json b/assets/translations/uk.json index bd38802..9754ebe 100644 --- a/assets/translations/uk.json +++ b/assets/translations/uk.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.", "wiki": "Довідка/Вікі", "crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)", + "allowInsecure": "Дозволити незахищені HTTP-запити", "removeAppQuestion": { "one": "Видалити застосунок?", "other": "Видалити застосунки?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index e545fc1..1f09f12 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "Chia sẻ lên AppVerifier, sau đó quay lại đây khi sẵn sàng.", "wiki": "Trợ giúp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh-Hant-TW.json b/assets/translations/zh-Hant-TW.json index 5aec1b9..7f38e49 100644 --- a/assets/translations/zh-Hant-TW.json +++ b/assets/translations/zh-Hant-TW.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "分享至 AppVerifier,然後準備好時回到此處。", "wiki": "幫助/維基", "crowdsourcedConfigsLabel": "群眾外包的應用程式設定(使用風險自負)", + "allowInsecure": "Allow insecure HTTP requests", "removeAppQuestion": { "one": "移除應用程式?", "other": "移除應用程式?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 220dafd..ea41bf7 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -314,6 +314,7 @@ "appVerifierInstructionToast": "分享至 AppVerifier,完成后返回此处。", "wiki": "帮助/Wiki", "crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)", + "allowInsecure": "允许不安全的 HTTP 请求", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/directAPKLink.dart b/lib/app_sources/directAPKLink.dart index 1addc13..d17b3d7 100644 --- a/lib/app_sources/directAPKLink.dart +++ b/lib/app_sources/directAPKLink.dart @@ -26,7 +26,6 @@ class DirectAPKLink extends AppSource { @override String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) { - print('AAA'); if (!forSelection) { return url; } diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index d3244d8..553f4ec 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -350,7 +350,8 @@ class HTML extends AppSource { ? rel.hashCode.toString() : (await checkPartialDownloadHashDynamic(rel, headers: await getRequestHeaders(additionalSettings, - forAPKDownload: true))) + forAPKDownload: true), + allowInsecure: additionalSettings['allowInsecure'] == true)) .toString(); return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), AppNames(uri.host, tr('app'))); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 93201d5..d1b968d 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -17,6 +17,7 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.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_modal.dart'; import 'package:obtainium/custom_errors.dart'; @@ -146,17 +147,23 @@ Future downloadFileWithRetry(String url, String fileName, bool fileNameHasExt, Function? onProgress, String destDir, {bool useExisting = true, Map? headers, - int retries = 3}) async { + int retries = 3, + bool allowInsecure = false}) async { try { return await downloadFile( url, fileName, fileNameHasExt, onProgress, destDir, - useExisting: useExisting, headers: headers); + useExisting: useExisting, + headers: headers, + allowInsecure: allowInsecure); } catch (e) { if (retries > 0 && e is ClientException) { await Future.delayed(const Duration(seconds: 5)); return await downloadFileWithRetry( url, fileName, fileNameHasExt, onProgress, destDir, - useExisting: useExisting, headers: headers, retries: (retries - 1)); + useExisting: useExisting, + headers: headers, + retries: (retries - 1), + allowInsecure: allowInsecure); } else { rethrow; } @@ -173,11 +180,14 @@ String hashListOfLists(List> data) { Future checkPartialDownloadHashDynamic(String url, {int startingSize = 1024, int lowerLimit = 128, - Map? headers}) async { + Map? headers, + bool allowInsecure = false}) async { for (int i = startingSize; i >= lowerLimit; i -= 256) { List ab = await Future.wait([ - checkPartialDownloadHash(url, i, headers: headers), - checkPartialDownloadHash(url, i, headers: headers) + checkPartialDownloadHash(url, i, + headers: headers, allowInsecure: allowInsecure), + checkPartialDownloadHash(url, i, + headers: headers, allowInsecure: allowInsecure) ]); if (ab[0] == ab[1]) { return ab[0]; @@ -187,13 +197,13 @@ Future checkPartialDownloadHashDynamic(String url, } Future checkPartialDownloadHash(String url, int bytesToGrab, - {Map? headers}) async { + {Map? headers, bool allowInsecure = false}) async { var req = Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); } req.headers[HttpHeaders.rangeHeader] = 'bytes=0-$bytesToGrab'; - var client = http.Client(); + var client = IOClient(createHttpClient(allowInsecure)); var response = await client.send(req); if (response.statusCode < 200 || response.statusCode > 299) { throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); @@ -204,12 +214,14 @@ Future checkPartialDownloadHash(String url, int bytesToGrab, Future downloadFile(String url, String fileName, bool fileNameHasExt, Function? onProgress, String destDir, - {bool useExisting = true, Map? headers}) async { + {bool useExisting = true, + Map? headers, + bool allowInsecure = false}) async { // Send the initial request but cancel it as soon as you have the headers var reqHeaders = headers ?? {}; var req = Request('GET', Uri.parse(url)); req.headers.addAll(reqHeaders); - var client = http.Client(); + var client = IOClient(createHttpClient(allowInsecure)); StreamedResponse response = await client.send(req); var resHeaders = response.headers; @@ -275,7 +287,7 @@ Future downloadFile(String url, String fileName, bool fileNameHasExt, IOSink? sink; if (rangeFeatureEnabled && fullContentLength != null && rangeStart > 0) { client.close(); - client = http.Client(); + client = IOClient(createHttpClient(allowInsecure)); req = Request('GET', Uri.parse(url)); req.headers.addAll(reqHeaders); req.headers.addAll({'range': 'bytes=$rangeStart-${fullContentLength - 1}'}); @@ -318,12 +330,12 @@ Future downloadFile(String url, String fileName, bool fileNameHasExt, } Future> getHeaders(String url, - {Map? headers}) async { + {Map? headers, bool allowInsecure = false}) async { var req = http.Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); } - var client = http.Client(); + var client = IOClient(createHttpClient(allowInsecure)); var response = await client.send(req); if (response.statusCode < 200 || response.statusCode > 299) { throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); @@ -468,7 +480,9 @@ class AppsProvider with ChangeNotifier { notificationsProvider?.notify(notif); } 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' if (apps[app.id] != null) { apps[app.id]!.downloadProgress = -1; @@ -1036,7 +1050,8 @@ class AppsProvider with ChangeNotifier { .getRequestHeaders(app.additionalSettings, forAPKDownload: fileUrl.key.endsWith('.apk') ? true : false), - useExisting: false); + useExisting: false, + allowInsecure: app.additionalSettings['allowInsecure'] == true); notificationsProvider .notify(DownloadedNotification(fileUrl.key, fileUrl.value)); } catch (e) { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index d60e19f..43b90ba 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -2,11 +2,13 @@ // AppSource is an abstract class with a concrete implementation for each source import 'dart:convert'; +import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/dom.dart'; import 'package:http/http.dart'; +import 'package:http/io_client.dart'; import 'package:obtainium/app_sources/apkmirror.dart'; import 'package:obtainium/app_sources/apkpure.dart'; import 'package:obtainium/app_sources/aptoide.dart'; @@ -399,6 +401,15 @@ getSourceRegex(List hosts) { 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 { List hosts = []; bool hostChanged = false; @@ -462,7 +473,9 @@ abstract class AppSource { if (requestHeaders != null) { req.headers.addAll(requestHeaders); } - return Response.fromStream(await Client().send(req)); + return Response.fromStream(await IOClient( + createHttpClient(additionalSettings['allowInsecure'] == true)) + .send(req)); } else { return get(Uri.parse(url)); } @@ -538,6 +551,10 @@ abstract class AppSource { GeneratedFormSwitch('shizukuPretendToBeGooglePlay', label: tr('shizukuPretendToBeGooglePlay'), defaultValue: false) ], + [ + GeneratedFormSwitch('allowInsecure', + label: tr('allowInsecure'), defaultValue: false) + ], [ GeneratedFormSwitch('exemptFromBackgroundUpdates', label: tr('exemptFromBackgroundUpdates'))