diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index c27e851f..19630c67 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -1,10 +1,13 @@ import 'dart:async'; +import 'dart:convert'; // import 'dart:io'; import 'package:computer/computer.dart'; import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gbk2utf8/flutter_gbk2utf8.dart'; import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/core/sync.dart'; import 'package:server_box/core/utils/server.dart'; @@ -443,10 +446,53 @@ class ServerProvider extends Provider { String? raw; try { - raw = await sv.client?.run(ShellFunc.status.exec(spi.id, systemType: sv.status.system)).string; + final execResult = await sv.client?.run(ShellFunc.status.exec(spi.id, systemType: sv.status.system)); + if (execResult != null) { + String? rawStr; + bool needGbk = false; + try { + rawStr = utf8.decode(execResult, allowMalformed: true); + // If there are characters that cannot be parsed, try to fallback to gbk decoding + if (rawStr.contains('�')) { + Loggers.app.warning('UTF8 decoding failed, use GBK decoding'); + needGbk = true; + } + } catch (e) { + Loggers.app.warning('UTF8 decoding failed, use GBK decoding', e); + needGbk = true; + }if (needGbk) { + try { + rawStr = gbk.decode(execResult); + } catch (e2) { + Loggers.app.warning('GBK decoding failed', e2); + rawStr = null; + } + } + if (rawStr == null) { + Loggers.app.warning('Decoding failed, execResult: $execResult'); + } + raw = rawStr; + } else { + raw = execResult.toString(); + } + + if (raw == null || raw.isEmpty) { + TryLimiter.inc(sid); + sv.status.err = SSHErr( + type: SSHErrType.segements, + message: 'decode or split failed, raw:\n$raw', + ); + _setServerState(s, ServerConn.failed); + + // Update SSH session status to disconnected on segments error + final sessionId = 'ssh_${spi.id}'; + TermSessionManager.updateStatus(sessionId, TermSessionStatus.disconnected); + return; + } + //dprint('Get status from ${spi.name}:\n$raw'); - segments = raw?.split(ScriptConstants.separator).map((e) => e.trim()).toList(); - if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) { + segments = raw.split(ScriptConstants.separator).map((e) => e.trim()).toList(); + if (raw.isEmpty || segments.isEmpty) { if (Stores.setting.keepStatusWhenErr.fetch()) { // Keep previous server status when err occurs if (sv.conn != ServerConn.failed && sv.status.more.isNotEmpty) { diff --git a/pubspec.lock b/pubspec.lock index 182aacdb..9a0afe09 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -515,6 +515,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + flutter_gbk2utf8: + dependency: "direct main" + description: + name: flutter_gbk2utf8 + sha256: c17323808d6ae7cfaf7676669e0130c33df6be322eb807cdd32face5824c1134 + url: "https://pub.dev" + source: hosted + version: "1.0.1" flutter_highlight: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 11481125..bf14afba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: git: url: https://github.com/lppcg/fl_lib ref: v1.0.338 + flutter_gbk2utf8: ^1.0.1 dependency_overrides: # webdav_client_plus: