fix: potential risk of being unable to launch URLs without HTTP(S) scheme (#4867)

This commit is contained in:
Lucas.Xu 2024-03-11 11:02:29 +08:00 committed by GitHub
parent 4b5195d891
commit fb887bec10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,10 +1,10 @@
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:string_validator/string_validator.dart';
import 'package:url_launcher/url_launcher.dart' as launcher; import 'package:url_launcher/url_launcher.dart' as launcher;
typedef OnFailureCallback = void Function(Uri uri); typedef OnFailureCallback = void Function(Uri uri);
@ -16,35 +16,60 @@ Future<bool> afLaunchUrl(
launcher.LaunchMode mode = launcher.LaunchMode.platformDefault, launcher.LaunchMode mode = launcher.LaunchMode.platformDefault,
String? webOnlyWindowName, String? webOnlyWindowName,
}) async { }) async {
// try to launch the uri directly
bool result;
try { try {
return await launcher.launchUrl( result = await launcher.launchUrl(uri);
uri,
mode: mode,
webOnlyWindowName: webOnlyWindowName,
);
} on PlatformException catch (e) { } on PlatformException catch (e) {
Log.error("Failed to open uri: $e"); Log.error('Failed to open uri: $e');
} finally {
result = false;
}
// if the uri is not a valid url, try to launch it with https scheme
final url = uri.toString();
if (!result && !isURL(url, {'require_protocol': true})) {
try {
final uriWithScheme = Uri.parse('https://$url');
result = await launcher.launchUrl(uriWithScheme);
} on PlatformException catch (e) {
Log.error('Failed to open uri: $e');
if (context != null && context.mounted) {
_errorHandler(uri, context: context, onFailure: onFailure, e: e);
}
}
}
return result;
}
Future<bool> afLaunchUrlString(String url) async {
final Uri uri;
try {
uri = Uri.parse(url);
} on FormatException catch (e) {
Log.error('Failed to parse url: $e');
return false;
}
// try to launch the uri directly
return afLaunchUrl(uri);
}
void _errorHandler(
Uri uri, {
BuildContext? context,
OnFailureCallback? onFailure,
PlatformException? e,
}) {
Log.error('Failed to open uri: $e');
if (onFailure != null) { if (onFailure != null) {
onFailure(uri); onFailure(uri);
} else { } else {
showMessageToast( showMessageToast(
LocaleKeys.failedToOpenUrl.tr(args: [e.message ?? "PlatformException"]), LocaleKeys.failedToOpenUrl.tr(args: [e?.message ?? "PlatformException"]),
context: context, context: context,
); );
} }
} }
return false;
}
Future<void> afLaunchUrlString(String url) async {
try {
final uri = Uri.parse(url);
await launcher.launchUrl(uri);
} on PlatformException catch (e) {
Log.error("Failed to open uri: $e");
} on FormatException catch (e) {
Log.error("Failed to parse url: $e");
}
}