set allowMalformed to true when decode utf8 (#12693)

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages
2025-08-20 14:55:52 +08:00
committed by GitHub
parent e0ab3f0c92
commit 5ff1740b5b
5 changed files with 27 additions and 15 deletions

View File

@@ -42,6 +42,7 @@ import 'package:flutter_hbb/native/win32.dart'
if (dart.library.html) 'package:flutter_hbb/web/win32.dart'; if (dart.library.html) 'package:flutter_hbb/web/win32.dart';
import 'package:flutter_hbb/native/common.dart' import 'package:flutter_hbb/native/common.dart'
if (dart.library.html) 'package:flutter_hbb/web/common.dart'; if (dart.library.html) 'package:flutter_hbb/web/common.dart';
import 'package:http/http.dart' as http;
final globalKey = GlobalKey<NavigatorState>(); final globalKey = GlobalKey<NavigatorState>();
final navigationBarKey = GlobalKey(); final navigationBarKey = GlobalKey();
@@ -2753,7 +2754,7 @@ class ServerConfig {
} catch (err) { } catch (err) {
final input = msg.split('').reversed.join(''); final input = msg.split('').reversed.join('');
final bytes = base64Decode(base64.normalize(input)); final bytes = base64Decode(base64.normalize(input));
json = jsonDecode(utf8.decode(bytes)); json = jsonDecode(utf8.decode(bytes, allowMalformed: true));
} }
idServer = json['host'] ?? ''; idServer = json['host'] ?? '';
relayServer = json['relay'] ?? ''; relayServer = json['relay'] ?? '';
@@ -3931,3 +3932,14 @@ String getConnectionText(bool secure, bool direct, String streamType) {
return '$connectionText ($streamType)'; return '$connectionText ($streamType)';
} }
} }
String decode_http_response(http.Response resp) {
try {
// https://github.com/rustdesk/rustdesk-server-pro/discussions/758
return utf8.decode(resp.bodyBytes, allowMalformed: true);
} catch (e) {
debugPrint('Failed to decode response as UTF-8: $e');
// Fallback to bodyString which handles encoding automatically
return resp.body;
}
}

View File

@@ -208,7 +208,7 @@ class AbModel {
return false; return false;
} }
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }
@@ -234,7 +234,7 @@ class AbModel {
return false; return false;
} }
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }
@@ -271,7 +271,7 @@ class AbModel {
headers['Content-Type'] = "application/json"; headers['Content-Type'] = "application/json";
final resp = await http.post(uri, headers: headers); final resp = await http.post(uri, headers: headers);
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }
@@ -925,7 +925,7 @@ class LegacyAb extends BaseAb {
peers.clear(); peers.clear();
} else if (resp.body.isNotEmpty) { } else if (resp.body.isNotEmpty) {
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} else if (json.containsKey('data')) { } else if (json.containsKey('data')) {
@@ -983,7 +983,7 @@ class LegacyAb extends BaseAb {
ret = true; ret = true;
} else { } else {
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} else if (resp.statusCode == 200) { } else if (resp.statusCode == 200) {
@@ -1359,7 +1359,7 @@ class Ab extends BaseAb {
final resp = await http.post(uri, headers: headers); final resp = await http.post(uri, headers: headers);
statusCode = resp.statusCode; statusCode = resp.statusCode;
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespMap(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }
@@ -1416,7 +1416,7 @@ class Ab extends BaseAb {
final resp = await http.post(uri, headers: headers); final resp = await http.post(uri, headers: headers);
statusCode = resp.statusCode; statusCode = resp.statusCode;
List<dynamic> json = List<dynamic> json =
_jsonDecodeRespList(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeRespList(decode_http_response(resp), resp.statusCode);
if (resp.statusCode != 200) { if (resp.statusCode != 200) {
throw 'HTTP ${resp.statusCode}'; throw 'HTTP ${resp.statusCode}';
} }

View File

@@ -122,7 +122,7 @@ class GroupModel {
final resp = await http.get(uri, headers: getHttpHeaders()); final resp = await http.get(uri, headers: getHttpHeaders());
_statusCode = resp.statusCode; _statusCode = resp.statusCode;
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeResp(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }
@@ -180,7 +180,7 @@ class GroupModel {
final resp = await http.get(uri, headers: getHttpHeaders()); final resp = await http.get(uri, headers: getHttpHeaders());
_statusCode = resp.statusCode; _statusCode = resp.statusCode;
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeResp(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
if (json['error'] == 'Admin required!' || if (json['error'] == 'Admin required!' ||
json['error'] json['error']
@@ -246,7 +246,7 @@ class GroupModel {
_statusCode = resp.statusCode; _statusCode = resp.statusCode;
Map<String, dynamic> json = Map<String, dynamic> json =
_jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode); _jsonDecodeResp(decode_http_response(resp), resp.statusCode);
if (json.containsKey('error')) { if (json.containsKey('error')) {
throw json['error']; throw json['error'];
} }

View File

@@ -304,14 +304,14 @@ class TerminalModel with ChangeNotifier {
// Try to decode as base64 first // Try to decode as base64 first
try { try {
final bytes = base64Decode(data); final bytes = base64Decode(data);
text = utf8.decode(bytes); text = utf8.decode(bytes, allowMalformed: true);
} catch (e) { } catch (e) {
// If base64 decode fails, treat as plain text // If base64 decode fails, treat as plain text
text = data; text = data;
} }
} else if (data is List) { } else if (data is List) {
// Handle if data comes as byte array // Handle if data comes as byte array
text = utf8.decode(List<int>.from(data)); text = utf8.decode(List<int>.from(data), allowMalformed: true);
} else { } else {
debugPrint('[TerminalModel] Unknown data type: ${data.runtimeType}'); debugPrint('[TerminalModel] Unknown data type: ${data.runtimeType}');
return; return;

View File

@@ -66,7 +66,7 @@ class UserModel {
reset(resetOther: status == 401); reset(resetOther: status == 401);
return; return;
} }
final data = json.decode(utf8.decode(response.bodyBytes)); final data = json.decode(decode_http_response(response));
final error = data['error']; final error = data['error'];
if (error != null) { if (error != null) {
throw error; throw error;
@@ -160,7 +160,7 @@ class UserModel {
final Map<String, dynamic> body; final Map<String, dynamic> body;
try { try {
body = jsonDecode(utf8.decode(resp.bodyBytes)); body = jsonDecode(decode_http_response(resp));
} catch (e) { } catch (e) {
debugPrint("login: jsonDecode resp body failed: ${e.toString()}"); debugPrint("login: jsonDecode resp body failed: ${e.toString()}");
if (resp.statusCode != 200) { if (resp.statusCode != 200) {