123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- import 'dart:io';
- import 'package:speed_safe/app/util/log.dart';
- import 'package:path/path.dart' as p;
- enum OS { windows, linux, macos }
- enum Architecture { x86_64, arm64 }
- const speedVersion = '0.7.6';
- const speedBuildNumber = 7;
- const speedFullVersion = '$speedVersion+$speedBuildNumber';
- const speedLastCommitHash = 'SELF_BUILD';
- const String singBoxUrl = 'https://github.com/SagerNet/sing-box';
- const String xrayCoreRepoUrl = 'https://github.com/xtls/xray-core';
- const String shadowsocksRustUrl =
- 'https://github.com/shadowsocks/shadowsocks-rust';
- const String hysteriaUrl = 'https://github.com/apernet/hysteria';
- const String singBoxRulesRepoUrl = 'https://github.com/lyc8503/sing-box-rules';
- const String geositeDBUrl =
- 'https://github.com/lyc8503/sing-box-rules/releases/latest/download/geosite.db';
- const String geoipDBUrl =
- 'https://github.com/lyc8503/sing-box-rules/releases/latest/download/geoip.db';
- const String v2rayRulesDatRepoUrl =
- 'https://github.com/Loyalsoldier/v2ray-rules-dat';
- const String geositeDatUrl =
- 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat';
- const String geoipDatUrl =
- 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat';
- const String sphiaRepoUrl = 'https://github.com/YukidouSatoru/sphia';
- final coreRepositories = {
- 'sing-box': singBoxUrl,
- 'xray-core': xrayCoreRepoUrl,
- 'shadowsocks-rust': shadowsocksRustUrl,
- 'hysteria': hysteriaUrl,
- 'sing-box-rules': singBoxRulesRepoUrl,
- 'v2ray-rules-dat': v2rayRulesDatRepoUrl,
- 'sphia': sphiaRepoUrl,
- // Add new core here
- };
- class SystemUtil{
- static late final OS os;
- static late final Architecture architecture;
- static late final bool isRoot;
- static void init() {
- os = determineOS();
- architecture = determineArchitecture();
- isRoot = determineIsRoot();
- }
- static OS determineOS() {
- if(Platform.isWindows) {
- return OS.windows;
- } else if (Platform.isLinux) {
- return OS.linux;
- } else if (Platform.isMacOS){
- return OS.macos;
- } else {
- logger.e('Unsupported OS');
- throw Exception('Unsupported OS');
- }
- }
- static Architecture determineArchitecture() {
- if (os == OS.windows) {
- final arch = Platform.environment['PROCESSOR_ARCHITECTURE'];
- // https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details
- if (arch == 'AMD64') {
- return Architecture.x86_64;
- } else if (arch == 'ARM64') {
- return Architecture.arm64;
- } else {
- logger.e('Unsupported Architecture');
- throw Exception('Unsupported Architecture');
- }
- } else {
- final result = Process.runSync('uname', ['-m']);
- if (result.exitCode == 0) {
- final arch = result.stdout.toString().trim();
- if (arch == 'x86_64') {
- return Architecture.x86_64;
- } else if (arch == 'aarch64' || arch == 'arm64') {
- return Architecture.arm64;
- } else {
- logger.e('Unsupported Architecture');
- throw Exception('Unsupported Architecture');
- }
- } else {
- logger.e('Unsupported Architecture');
- throw Exception('Unsupported Architecture');
- }
- }
- }
- static bool determineIsRoot() {
- if (os == OS.windows) {
- final result = Process.runSync('net', ['session']);
- if (result.exitCode == 0) {
- return true;
- } else {
- return false;
- }
- } else {
- final result = Process.runSync('id', ['-u']);
- if (result.exitCode == 0) {
- return result.stdout.toString().trim() == '0';
- } else {
- return false;
- }
- }
- }
- static void enableWindowsProxy(String listen, int httpPort) async {
- await runCommand('reg', [
- 'add',
- 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
- '/v',
- 'ProxyEnable',
- '/t',
- 'REG_DWORD',
- '/d',
- '1',
- '/f'
- ]);
- await runCommand('reg', [
- 'add',
- 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
- '/v',
- 'ProxyServer',
- '/d',
- '$listen:$httpPort',
- '/f'
- ]);
- await runCommand('reg', [
- 'add',
- 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
- '/v',
- 'ProxyOverride',
- '/d',
- '127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*',
- '/f'
- ]);
- }
- static void disableWindowsProxy() async {
- await runCommand('reg', [
- 'add',
- 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
- '/v',
- 'ProxyEnable',
- '/t',
- 'REG_DWORD',
- '/d',
- '0',
- '/f'
- ]);
- }
- static void enableMacOSProxy(String listen, int httpPort) async {
- await runCommand(
- 'networksetup', ['-setwebproxy', 'wi-fi', listen, httpPort.toString()]);
- await runCommand('networksetup',
- ['-setsecurewebproxy', 'wi-fi', listen, httpPort.toString()]);
- await runCommand('networksetup', ['-setwebproxystate', 'wi-fi', 'on']);
- await runCommand(
- 'networksetup', ['-setsecurewebproxystate', 'wi-fi', 'on']);
- }
- static void disableMacOSProxy() async {
- await runCommand('networksetup', ['-setwebproxystate', 'wi-fi', 'off']);
- await runCommand(
- 'networksetup', ['-setsecurewebproxystate', 'wi-fi', 'off']);
- }
- static Future<void> runCommand(
- String executable, List<String> arguments) async {
- final result = await Process.run(executable, arguments, runInShell: true);
- if (result.exitCode != 0) {
- logger.e('Failed to run command: $executable $arguments');
- throw Exception('Failed to run command: $executable $arguments');
- }
- }
- static String getCoreFileName(String coreName) {
- final ext = os == OS.windows ? '.exe' : '';
- switch (coreName) {
- case 'sing-box':
- return 'sing-box$ext';
- case 'xray-core':
- return 'xray$ext';
- case 'shadowsocks-rust':
- return 'sslocal$ext';
- case 'hysteria':
- final plat = os == OS.macos ? 'darwin' : os.name;
- final arch = architecture == Architecture.arm64 ? 'arm64' : 'amd64';
- return 'hysteria-$plat-$arch$ext';
- case 'sphia':
- return 'sphia$ext';
- case 'upgradeAgent':
- return 'upgradeAgent$ext';
- default:
- throw Exception('Unsupported core: $coreName');
- }
- }
- static void setFilePermission(String fileName) {
- if (os != OS.windows) {
- Process.runSync('chmod', ['+x', fileName]);
- }
- }
- static void createDirectory(String dirName) {
- final dir = Directory(dirName);
- try {
- if (!dir.existsSync()) {
- logger.i('Creating directory: $dirName');
- dir.createSync();
- }
- } catch (e) {
- logger.e('Error creating directory: $e');
- }
- }
- static bool fileExists(String fileName) {
- return File(p.join(binPath, fileName)).existsSync();
- }
- static void deleteFileIfExists(String filePath, String logMessage) {
- final file = File(filePath);
- if (file.existsSync()) {
- logger.i(logMessage);
- file.deleteSync();
- }
- }
- static bool coreExists(String coreName) {
- if (coreName == 'sing-box-rules') {
- return fileExists(p.join(binPath, 'geoip.db')) &&
- fileExists(p.join(binPath, 'geosite.db'));
- } else if (coreName == 'v2ray-rules-dat') {
- return fileExists(p.join(binPath, 'geoip.dat')) &&
- fileExists(p.join(binPath, 'geosite.dat'));
- } else {
- return fileExists(p.join(binPath, getCoreFileName(coreName)));
- }
- }
- static List<String> getCoreFileNames() {
- List<String> fileNames = [];
- coreRepositories.entries
- .toList()
- .sublist(0, coreRepositories.length - 3)
- .forEach((entry) {
- fileNames.add(getCoreFileName(entry.key));
- });
- return fileNames;
- }
- static void initPaths() {
- binPath = p.join(appPath, 'bin');
- configPath = p.join(appPath, 'config');
- logPath = p.join(appPath, 'log');
- tempPath = p.join(appPath, 'temp');
- }
- }
- late final String execPath;
- late final String appPath;
- late String binPath;
- late String configPath;
- late String logPath;
- late String tempPath;
|