diff --git a/lib/core/utils/executable_manager.dart b/lib/core/utils/executable_manager.dart index 51ea08a4..747cfaef 100644 --- a/lib/core/utils/executable_manager.dart +++ b/lib/core/utils/executable_manager.dart @@ -29,6 +29,7 @@ class ExecutableInfo { /// Generic executable manager for downloading and managing external tools abstract final class ExecutableManager { static const String _executablesDirName = 'executables'; + static const int _posixExecuteBitsMask = 0x49; // Equivalent to POSIX octal 0o111 static late final Directory _executablesDir; static final Map _customExecutables = {}; static bool _customExecutablesLoaded = false; @@ -137,7 +138,7 @@ abstract final class ExecutableManager { return await getExecutablePath(name); } - return await getExecutablePath(name); + throw ExecutableException('Executable "$name" not found and automatic installation is not implemented'); } /// Remove a local executable @@ -270,7 +271,7 @@ abstract final class ExecutableManager { } else { // Check file permissions final stat = file.statSync(); - return (stat.mode & 0x111) != 0; // Check execute bits + return (stat.mode & _posixExecuteBitsMask) != 0; // Check execute bits } } diff --git a/lib/data/model/server/proxy_command_config.dart b/lib/data/model/server/proxy_command_config.dart index c571b014..666d19c3 100644 --- a/lib/data/model/server/proxy_command_config.dart +++ b/lib/data/model/server/proxy_command_config.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:server_box/core/utils/proxy_command_executor.dart' show ProxyCommandException; part 'proxy_command_config.freezed.dart'; part 'proxy_command_config.g.dart'; @@ -65,6 +66,12 @@ const Map proxyCommandPresets = { extension ProxyCommandConfigExtension on ProxyCommandConfig { /// Get the final command with placeholders replaced String getFinalCommand({required String hostname, required int port, required String user}) { + if (!command.contains('%h') && !command.contains('%p') && !command.contains('%r')) { + throw ProxyCommandException( + message: 'Proxy command "$command" must include at least one placeholder (%h, %p, %r)', + ); + } + var finalCommand = command; finalCommand = finalCommand.replaceAll('%h', hostname); finalCommand = finalCommand.replaceAll('%p', port.toString()); diff --git a/lib/data/model/server/server_private_info.dart b/lib/data/model/server/server_private_info.dart index 5dad420c..61631ef3 100644 --- a/lib/data/model/server/server_private_info.dart +++ b/lib/data/model/server/server_private_info.dart @@ -22,7 +22,7 @@ part 'server_private_info.g.dart'; abstract class Spi with _$Spi { const Spi._(); - @JsonSerializable(includeIfNull: false) + @JsonSerializable(includeIfNull: false, explicitToJson: true) const factory Spi({ required String name, required String ip, diff --git a/lib/data/model/server/server_private_info.freezed.dart b/lib/data/model/server/server_private_info.freezed.dart index e39eed9c..f87ebbba 100644 --- a/lib/data/model/server/server_private_info.freezed.dart +++ b/lib/data/model/server/server_private_info.freezed.dart @@ -237,7 +237,7 @@ return $default(_that.name,_that.ip,_that.port,_that.user,_that.pwd,_that.keyId, /// @nodoc -@JsonSerializable(includeIfNull: false) +@JsonSerializable(includeIfNull: false, explicitToJson: true) class _Spi extends Spi { const _Spi({required this.name, required this.ip, required this.port, required this.user, this.pwd, @JsonKey(name: 'pubKeyId') this.keyId, final List? tags, this.alterUrl, this.autoConnect = true, this.jumpId, this.custom, this.wolCfg, final Map? envs, @JsonKey(fromJson: Spi.parseId) this.id = '', this.customSystemType, final List? disabledCmdTypes, this.proxyCommand}): _tags = tags,_envs = envs,_disabledCmdTypes = disabledCmdTypes,super._(); factory _Spi.fromJson(Map json) => _$SpiFromJson(json); diff --git a/lib/data/model/server/server_private_info.g.dart b/lib/data/model/server/server_private_info.g.dart index 7b20fe48..7c2d826f 100644 --- a/lib/data/model/server/server_private_info.g.dart +++ b/lib/data/model/server/server_private_info.g.dart @@ -52,13 +52,13 @@ Map _$SpiToJson(_Spi instance) => { 'alterUrl': ?instance.alterUrl, 'autoConnect': instance.autoConnect, 'jumpId': ?instance.jumpId, - 'custom': ?instance.custom, - 'wolCfg': ?instance.wolCfg, + 'custom': ?instance.custom?.toJson(), + 'wolCfg': ?instance.wolCfg?.toJson(), 'envs': ?instance.envs, 'id': instance.id, 'customSystemType': ?_$SystemTypeEnumMap[instance.customSystemType], 'disabledCmdTypes': ?instance.disabledCmdTypes, - 'proxyCommand': ?instance.proxyCommand, + 'proxyCommand': ?instance.proxyCommand?.toJson(), }; const _$SystemTypeEnumMap = { diff --git a/pubspec.lock b/pubspec.lock index e42bc6b1..1bd48163 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1007,10 +1007,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -1581,26 +1581,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" + sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" url: "https://pub.dev" source: hosted - version: "1.26.2" + version: "1.26.3" test_api: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.7" test_core: dependency: transitive description: name: test_core - sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" + sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" url: "https://pub.dev" source: hosted - version: "0.6.11" + version: "0.6.12" timing: dependency: transitive description: