diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 724bedf..8e0cdc8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -12,6 +12,8 @@ "port": "Port: ", "proxy": "Proxy", "externalProxy": "External Proxy", + "username": "Username", + "password": "Password", "proxySetting": "Proxy Setting", "systemProxy": "Set as System Proxy", "serverNotStart": "Proxy server not started", @@ -243,6 +245,8 @@ "headerExpanded": "Headers Expanded", "headerExpandedSubtitle": "Details page Headers is expanded by default", + "externalProxyAuth": "Proxy Auth (Optional)", + "externalProxyServer": "Proxy Server", "externalProxyConnectFailure": "External Proxy Connect failure", "externalProxyFailureConfirm": "Access to all http will fail due to network connectivity issues,Do you want to continue setting up external proxies。", "mobileDisplayPacketCapture": "Mobile Display Packet Capture:", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index f67274c..ae6fcf9 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -12,6 +12,8 @@ "port": "端口号: ", "proxy": "代理", "externalProxy": "外部代理设置", + "username": "用户名", + "password": "密码", "proxySetting": "代理设置", "systemProxy": "设置为系统代理", "serverNotStart": "未开启抓包", @@ -243,6 +245,8 @@ "headerExpanded": "Headers自动展开", "headerExpandedSubtitle": "详情页Headers栏是否自动展开", + "externalProxyAuth": "代理认证 (可选)", + "externalProxyServer": "代理服务器", "externalProxyConnectFailure": "外部代理连接失败", "externalProxyFailureConfirm": "网络不通所有接口将会访问失败,是否继续设置外部代理。", "mobileDisplayPacketCapture": "手机端是否展示抓包:", diff --git a/lib/network/channel.dart b/lib/network/channel.dart index 4be0ebd..add8932 100644 --- a/lib/network/channel.dart +++ b/lib/network/channel.dart @@ -288,7 +288,13 @@ class ChannelPipeline extends ChannelHandler { var clientChannel = channelContext.clientChannel!; Channel? remoteChannel = channelContext.serverChannel ?? await channelContext.connectServerChannel(remote, RelayHandler(clientChannel)); + ProxyInfo? proxyInfo = channelContext.getAttribute(AttributeKeys.proxyInfo); if (clientChannel.isSsl && !remoteChannel.isSsl) { + //代理认证 + if (proxyInfo?.isAuthenticated == true) { + await HttpClients.connectRequest(remote, remoteChannel, proxyInfo: proxyInfo); + } + await remoteChannel.secureSocket(channelContext, host: channelContext.getAttribute(AttributeKeys.domain)); } diff --git a/lib/network/handler.dart b/lib/network/handler.dart index ed3ac3d..7e0126f 100644 --- a/lib/network/handler.dart +++ b/lib/network/handler.dart @@ -15,6 +15,7 @@ */ import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; import 'package:network_proxy/network/components/host_filter.dart'; @@ -22,6 +23,7 @@ import 'package:network_proxy/network/components/request_rewrite_manager.dart'; import 'package:network_proxy/network/components/script_manager.dart'; import 'package:network_proxy/network/host_port.dart'; import 'package:network_proxy/network/http/http.dart'; +import 'package:network_proxy/network/http/http_headers.dart'; import 'package:network_proxy/network/http/websocket.dart'; import 'package:network_proxy/network/proxy_helper.dart'; import 'package:network_proxy/network/util/attribute_keys.dart'; @@ -187,16 +189,24 @@ class HttpProxyChannelHandler extends ChannelHandler { HostAndPort? remote = channelContext.getAttribute(AttributeKeys.remote); //外部代理 ProxyInfo? proxyInfo = channelContext.getAttribute(AttributeKeys.proxyInfo); + if (remote != null || proxyInfo != null) { HostAndPort connectHost = remote ?? HostAndPort.host(proxyInfo!.host, proxyInfo.port!); final proxyChannel = await connectRemote(channelContext, clientChannel, connectHost); //代理建立完连接判断是否是https 需要发起connect请求 if (httpRequest.method == HttpMethod.connect) { + + //proxy Authorization + if (proxyInfo?.isAuthenticated == true) { + String auth = base64Encode(utf8.encode("${proxyInfo?.username}:${proxyInfo?.password}")); + httpRequest.headers.set(HttpHeaders.PROXY_AUTHORIZATION, 'Basic $auth'); + } + await proxyChannel.write(httpRequest); } else { if (clientChannel.isSsl) { - await HttpClients.connectRequest(hostAndPort, proxyChannel); + await HttpClients.connectRequest(hostAndPort, proxyChannel, proxyInfo: proxyInfo); await proxyChannel.secureSocket(channelContext, host: hostAndPort.host); } } diff --git a/lib/network/host_port.dart b/lib/network/host_port.dart index d729cc1..473f2f3 100644 --- a/lib/network/host_port.dart +++ b/lib/network/host_port.dart @@ -111,15 +111,23 @@ class ProxyInfo { String host = '127.0.0.1'; int? port; + //authorization + String? username; + String? password; + ProxyInfo(); ProxyInfo.of(this.host, this.port) : enabled = true; + bool get isAuthenticated => username?.isNotEmpty == true; + ProxyInfo.fromJson(Map json) { enabled = json['enabled'] == true; capturePacket = json['capturePacket'] ?? true; host = json['host']; port = json['port']; + username = json['username']; + password = json['password']; } Map toJson() { @@ -128,11 +136,13 @@ class ProxyInfo { 'capturePacket': capturePacket, 'host': host, 'port': port, + 'username': username, + 'password': password, }; } @override String toString() { - return 'ProxyInfo{enabled: $enabled, capturePacket: $capturePacket, host: $host, port: $port}'; + return 'ProxyInfo{enabled: $enabled, capturePacket: $capturePacket, host: $host, port: $port, username: $username, password: $password}'; } } diff --git a/lib/network/http/body_reader.dart b/lib/network/http/body_reader.dart index 13d05fd..8ece07a 100644 --- a/lib/network/http/body_reader.dart +++ b/lib/network/http/body_reader.dart @@ -76,10 +76,6 @@ class BodyReader { if (message.contentLength == -1 || _bodyBuffer.length >= message.contentLength) { _state = ReaderState.done; - - if (message.contentLength != -1 && _bodyBuffer.length > message.contentLength) { - print(String.fromCharCodes(_bodyBuffer.toBytes().sublist(message.contentLength))); - } } } diff --git a/lib/network/http/http_headers.dart b/lib/network/http/http_headers.dart index 3a6307a..2b8ffe5 100644 --- a/lib/network/http/http_headers.dart +++ b/lib/network/http/http_headers.dart @@ -25,6 +25,7 @@ class HttpHeaders { static const String HOST = "Host"; static const String TRANSFER_ENCODING = "Transfer-Encoding"; static const String Cookie = "Cookie"; + static const String PROXY_AUTHORIZATION = "Proxy-Authorization"; final LinkedHashMap> _headers = LinkedHashMap>(); diff --git a/lib/network/http_client.dart b/lib/network/http_client.dart index 931ac57..e1d0cc5 100644 --- a/lib/network/http_client.dart +++ b/lib/network/http_client.dart @@ -14,12 +14,12 @@ * limitations under the License. */ - import 'dart:async'; -import 'dart:io'; +import 'dart:convert'; import 'package:network_proxy/network/host_port.dart'; import 'package:network_proxy/network/http/http.dart'; +import 'package:network_proxy/network/http/http_headers.dart'; import 'package:network_proxy/network/network.dart'; import 'package:network_proxy/network/util/system_proxy.dart'; import 'package:proxy_manager/proxy_manager.dart'; @@ -52,7 +52,7 @@ class HttpClients { var channel = await client.connect(connectHost, channelContext); if (proxyInfo != null && hostAndPort.isSsl()) { - await connectRequest(hostAndPort, channel); + await connectRequest(hostAndPort, channel, proxyInfo: proxyInfo); } if (hostAndPort.isSsl()) { @@ -63,14 +63,20 @@ class HttpClients { } ///发起代理连接请求 - static Future connectRequest(HostAndPort hostAndPort, Channel channel) async { + static Future connectRequest(HostAndPort hostAndPort, Channel channel, {ProxyInfo? proxyInfo}) async { ChannelHandler handler = channel.pipeline.handler; //代理 发送connect请求 var httpResponseHandler = HttpResponseHandler(); channel.pipeline.handler = httpResponseHandler; HttpRequest proxyRequest = HttpRequest(HttpMethod.connect, '${hostAndPort.host}:${hostAndPort.port}'); - proxyRequest.headers.set(HttpHeaders.hostHeader, '${hostAndPort.host}:${hostAndPort.port}'); + proxyRequest.headers.set(HttpHeaders.HOST, '${hostAndPort.host}:${hostAndPort.port}'); + + //proxy Authorization + if (proxyInfo?.isAuthenticated == true) { + String auth = base64Encode(utf8.encode("${proxyInfo?.username}:${proxyInfo?.password}")); + proxyRequest.headers.set(HttpHeaders.PROXY_AUTHORIZATION, 'Basic $auth'); + } await channel.write(proxyRequest); var response = await httpResponseHandler.getResponse(const Duration(seconds: 5)); @@ -132,7 +138,8 @@ class HttpClients { var httpResponseHandler = HttpResponseHandler(); request.hostAndPort ??= HostAndPort.of(request.requestUrl); - Channel channel = await proxyConnect(proxyInfo: proxyInfo, request.hostAndPort!, httpResponseHandler, channelContext); + Channel channel = + await proxyConnect(proxyInfo: proxyInfo, request.hostAndPort!, httpResponseHandler, channelContext); if (channel.isSsl && !request.uri.startsWith("/")) { Uri? uri = request.requestUri; diff --git a/lib/network/network.dart b/lib/network/network.dart index e203936..b3e9ef5 100644 --- a/lib/network/network.dart +++ b/lib/network/network.dart @@ -97,9 +97,9 @@ class Server extends Network { //外部代理信息 if (configuration.externalProxy?.enabled == true) { ProxyInfo externalProxy = configuration.externalProxy!; - if (externalProxy.capturePacket == true) { - channelContext.putAttribute(AttributeKeys.proxyInfo, externalProxy); - } else { + channelContext.putAttribute(AttributeKeys.proxyInfo, externalProxy); + + if (externalProxy.capturePacket == false) { //不抓包直接转发 channelContext.putAttribute(AttributeKeys.remote, HostAndPort.host(externalProxy.host, externalProxy.port!)); } diff --git a/lib/network/util/system_proxy.dart b/lib/network/util/system_proxy.dart index 5db49fd..3182ce8 100644 --- a/lib/network/util/system_proxy.dart +++ b/lib/network/util/system_proxy.dart @@ -294,7 +294,6 @@ class LinuxSystemProxy extends SystemProxy { return Future.wait([hostFuture, portFuture]).then((value) { var host = Strings.trimWrap(value[0], "'"); var port = Strings.trimWrap(value[1], "'"); - print("$host:$port"); if (host.isNotEmpty && port.isNotEmpty) { return ProxyInfo.of(host, int.parse(port)); } diff --git a/lib/storage/histories.dart b/lib/storage/histories.dart index 73d693a..4807f3a 100644 --- a/lib/storage/histories.dart +++ b/lib/storage/histories.dart @@ -63,7 +63,7 @@ class HistoryStorage { _histories.add(HistoryItem.formJson(entry)); } } catch (e) { - print(e); + logger.e("历史记录解析错误", error: e); } } } diff --git a/lib/ui/configuration.dart b/lib/ui/configuration.dart index 905d537..b758472 100644 --- a/lib/ui/configuration.dart +++ b/lib/ui/configuration.dart @@ -19,6 +19,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:network_proxy/network/util/logger.dart'; import 'package:network_proxy/utils/platform.dart'; import 'package:path_provider/path_provider.dart'; @@ -153,7 +154,7 @@ class AppConfiguration { Future initConfig() async { // 读取配置文件 var file = await _path; - print(file); + logger.d(file); var exits = await file.exists(); if (!exits) { return; @@ -185,7 +186,7 @@ class AppConfiguration { panelRatio = config['panelRatio']; } } catch (e) { - print(e); + logger.e(e); } } diff --git a/lib/ui/content/body.dart b/lib/ui/content/body.dart index 11151d0..afd66b0 100644 --- a/lib/ui/content/body.dart +++ b/lib/ui/content/body.dart @@ -386,7 +386,6 @@ class _BodyState extends State<_Body> { return SelectableText(message!.body!.map(intToHex).join(" "), contextMenuBuilder: contextMenu); } } catch (e) { - // ignore: avoid_print logger.e(e, stackTrace: StackTrace.current); } @@ -404,6 +403,7 @@ class Tabs { } if (contentType == ContentType.video) { + tabs.list.add(ViewType.video); tabs.list.add(ViewType.hex); return tabs; } diff --git a/lib/ui/desktop/toolbar/setting/external_proxy.dart b/lib/ui/desktop/toolbar/setting/external_proxy.dart index 01e890d..caeba4e 100644 --- a/lib/ui/desktop/toolbar/setting/external_proxy.dart +++ b/lib/ui/desktop/toolbar/setting/external_proxy.dart @@ -20,6 +20,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:network_proxy/network/bin/configuration.dart'; import 'package:network_proxy/network/host_port.dart'; +import 'package:network_proxy/ui/component/widgets.dart'; /// @author wanghongen /// 2023/10/8 @@ -51,6 +52,8 @@ class _ExternalProxyDialogState extends State { @override Widget build(BuildContext context) { + bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh'); + return AlertDialog( scrollable: true, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)), @@ -72,41 +75,96 @@ class _ExternalProxyDialogState extends State { ], content: Form( key: formKey, - child: Column(mainAxisSize: MainAxisSize.min, children: [ + child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), Row(children: [ - Text("${localizations.enable}:"), + Expanded(child: Text("${localizations.enable}:")), Expanded( - child: Switch( + child: SwitchWidget( value: externalProxy.enabled, + scale: 0.85, onChanged: (val) { - setState(() => externalProxy.enabled = val); + externalProxy.enabled = val; }, )) ]), - Row(children: [ - const SizedBox(width: 60, child: Text("Host:")), - Expanded( - child: TextFormField( - initialValue: externalProxy.host, - validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, - onChanged: (val) => externalProxy.host = val, - )) - ]), - Row(children: [ - SizedBox(width: 60, child: Text(localizations.port)), - Expanded( - child: TextFormField( - initialValue: externalProxy.port?.toString() ?? '', - inputFormatters: [ - LengthLimitingTextInputFormatter(5), - FilteringTextInputFormatter.allow(RegExp("[0-9]")) - ], - onChanged: (val) => externalProxy.port = int.parse(val), - validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, - decoration: const InputDecoration(), - )) - ]), + + const SizedBox(height: 3), + Text(localizations.externalProxyServer, style: const TextStyle(fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + SizedBox( + height: 36, + child: Row(children: [ + Expanded( + child: TextFormField( + initialValue: externalProxy.host, + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + onChanged: (val) => externalProxy.host = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + hintText: 'Host', + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder(), + ), + )), + const SizedBox(child: Text(' : ', style: TextStyle(fontSize: 22))), + SizedBox( + width: 65, + child: TextFormField( + initialValue: externalProxy.port?.toString() ?? '', + inputFormatters: [ + LengthLimitingTextInputFormatter(5), + FilteringTextInputFormatter.allow(RegExp("[0-9]")) + ], + onChanged: (val) => externalProxy.port = int.parse(val), + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + hintText: 'Port', + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder(), + ), + )) + ])), + + //认证 + const SizedBox(height: 15), + Text(localizations.externalProxyAuth, style: const TextStyle(fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + SizedBox( + height: 36, + child: Row(children: [ + SizedBox( + width: isCN ? 65 : 85, + child: Text('${localizations.username}:', style: const TextStyle(fontWeight: FontWeight.w300))), + Expanded( + child: TextFormField( + initialValue: externalProxy.username, + onChanged: (val) => externalProxy.username = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + border: OutlineInputBorder(), + ), + )) + ])), + const SizedBox(height: 10), + + SizedBox( + height: 36, + child: Row(children: [ + SizedBox( + width: isCN ? 65 : 85, + child: Text('${localizations.password}:', style: const TextStyle(fontWeight: FontWeight.w300))), + Expanded( + child: TextFormField( + initialValue: externalProxy.password, + onChanged: (val) => externalProxy.password = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + border: OutlineInputBorder(), + ), + )) + ])), ]))); } diff --git a/lib/ui/launch/launch.dart b/lib/ui/launch/launch.dart index 5fc8935..120a123 100644 --- a/lib/ui/launch/launch.dart +++ b/lib/ui/launch/launch.dart @@ -20,6 +20,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/network/bin/server.dart'; +import 'package:network_proxy/network/util/logger.dart'; import 'package:network_proxy/utils/lang.dart'; import 'package:network_proxy/utils/platform.dart'; import 'package:window_manager/window_manager.dart'; @@ -86,7 +87,7 @@ class _SocketLaunchState extends State with WindowListener, Widget @override void onWindowClose() async { - print("onWindowClose"); + logger.d("onWindowClose"); await appExit(); } @@ -106,7 +107,7 @@ class _SocketLaunchState extends State with WindowListener, Widget @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.detached) { - print('AppLifecycleState.detached'); + logger.d('AppLifecycleState.detached'); widget.onStop?.call(); widget.proxyServer.stop(); started = false; diff --git a/lib/ui/mobile/menu/menu.dart b/lib/ui/mobile/menu/menu.dart index b2eb801..eef0aff 100644 --- a/lib/ui/mobile/menu/menu.dart +++ b/lib/ui/mobile/menu/menu.dart @@ -24,6 +24,7 @@ import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/native/vpn.dart'; import 'package:network_proxy/network/bin/server.dart'; import 'package:network_proxy/network/http_client.dart'; +import 'package:network_proxy/network/util/logger.dart'; import 'package:network_proxy/ui/mobile/mobile.dart'; import 'package:network_proxy/ui/mobile/setting/app_filter.dart'; import 'package:network_proxy/ui/mobile/setting/ssl.dart'; @@ -88,7 +89,7 @@ class MoreMenu extends StatelessWidget { title: Text(localizations.myQRCode), onTap: () async { Navigator.maybePop(context); - var ip = await localIp(); + var ip = await localIp(readCache: false); if (context.mounted) { connectQrCode(context, ip, proxyServer.port); } @@ -172,7 +173,7 @@ class MoreMenu extends StatelessWidget { } } } catch (e) { - print(e); + logger.e(e); if (context.mounted) { showDialog( context: context, diff --git a/lib/ui/mobile/mobile.dart b/lib/ui/mobile/mobile.dart index ec1b4fe..bd3ed4e 100644 --- a/lib/ui/mobile/mobile.dart +++ b/lib/ui/mobile/mobile.dart @@ -172,7 +172,7 @@ class MobileHomeState extends State implements EventListener, Li Widget build(BuildContext context) { return PopScope( canPop: false, - onPopInvokedWithResult: (d, result) async { + onPopInvoked: (d) async { if (await enterPictureInPicture()) { return; } @@ -234,7 +234,7 @@ class MobileHomeState extends State implements EventListener, Li } Vpn.startVpn( - Platform.isAndroid ? await localIp() : "127.0.0.1", proxyServer.port, proxyServer.configuration); + Platform.isAndroid ? await localIp(readCache: false) : "127.0.0.1", proxyServer.port, proxyServer.configuration); }, onStop: () => Vpn.stopVpn())), ); diff --git a/lib/ui/mobile/setting/proxy.dart b/lib/ui/mobile/setting/proxy.dart index 6572e9d..13df80c 100644 --- a/lib/ui/mobile/setting/proxy.dart +++ b/lib/ui/mobile/setting/proxy.dart @@ -35,6 +35,9 @@ class _ExternalProxyDialogState extends State { @override Widget build(BuildContext context) { + bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh'); + + return AlertDialog( scrollable: true, title: Text(localizations.externalProxy, style: const TextStyle(fontSize: 15)), @@ -51,7 +54,7 @@ class _ExternalProxyDialogState extends State { ], content: Form( key: formKey, - child: Column(mainAxisSize: MainAxisSize.min, children: [ + child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), Row(children: [ Expanded(flex: 2, child: Text("${localizations.enable}:")), @@ -75,29 +78,82 @@ class _ExternalProxyDialogState extends State { }, )) ]), - Row(children: [ - const Text("Host:"), - Expanded( - child: TextFormField( - initialValue: externalProxy.host, - validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, - onChanged: (val) => externalProxy.host = val, - )) - ]), - Row(children: [ - const Text("Port:"), - Expanded( - child: TextFormField( - initialValue: externalProxy.port?.toString() ?? '', - inputFormatters: [ - LengthLimitingTextInputFormatter(5), - FilteringTextInputFormatter.allow(RegExp("[0-9]")) - ], - onChanged: (val) => externalProxy.port = int.parse(val), - validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, - decoration: const InputDecoration(), - )) - ]), + const SizedBox(height: 3), + Text(localizations.externalProxyServer, style: const TextStyle(fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + SizedBox( + height: 36, + child: Row(children: [ + Expanded( + child: TextFormField( + initialValue: externalProxy.host, + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + onChanged: (val) => externalProxy.host = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + hintText: 'Host', + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder(), + ), + )), + const SizedBox(child: Text(' : ', style: TextStyle(fontSize: 22))), + SizedBox( + width: 68, + child: TextFormField( + initialValue: externalProxy.port?.toString() ?? '', + inputFormatters: [ + LengthLimitingTextInputFormatter(5), + FilteringTextInputFormatter.allow(RegExp("[0-9]")) + ], + onChanged: (val) => externalProxy.port = int.parse(val), + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + hintText: 'Port', + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder(), + ), + )) + ])), + + //认证 + const SizedBox(height: 15), + Text(localizations.externalProxyAuth, style: const TextStyle(fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + SizedBox( + height: 36, + child: Row(children: [ + SizedBox( + width: isCN ? 65 : 85, + child: Text('${localizations.username}:', style: const TextStyle(fontWeight: FontWeight.w300))), + Expanded( + child: TextFormField( + initialValue: externalProxy.username, + onChanged: (val) => externalProxy.username = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + border: OutlineInputBorder(), + ), + )) + ])), + const SizedBox(height: 10), + + SizedBox( + height: 36, + child: Row(children: [ + SizedBox( + width: isCN ? 65 : 85, + child: Text('${localizations.password}:', style: const TextStyle(fontWeight: FontWeight.w300))), + Expanded( + child: TextFormField( + initialValue: externalProxy.password, + onChanged: (val) => externalProxy.password = val, + decoration: const InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 8), + border: OutlineInputBorder(), + ), + )) + ])), ]))); } diff --git a/lib/utils/compress.dart b/lib/utils/compress.dart index e3678d5..af0f05b 100644 --- a/lib/utils/compress.dart +++ b/lib/utils/compress.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:brotli/brotli.dart'; +import 'package:network_proxy/network/util/logger.dart'; ///GZIP 解压缩 List gzipDecode(List byteBuffer) { @@ -8,7 +9,7 @@ List gzipDecode(List byteBuffer) { try { return gzipCodec.decode(byteBuffer); } catch (e) { - print("gzipDecode error: $e"); + logger.e("gzipDecode error: $e"); return byteBuffer; } } @@ -23,7 +24,7 @@ List brDecode(List byteBuffer) { try { return brotli.decode(byteBuffer); } catch (e) { - print("brDecode error: $e"); + logger.e("brDecode error: $e"); return byteBuffer; } } diff --git a/lib/utils/ip.dart b/lib/utils/ip.dart index 3d66dac..18710be 100644 --- a/lib/utils/ip.dart +++ b/lib/utils/ip.dart @@ -16,7 +16,10 @@ void main() { String? ip; /// 获取本机ip (en0 or WLAN)优先 -Future localIp() async { +Future localIp({bool readCache = true}) async { + if (!readCache) { + ip = null; + } ip ??= await localAddress().then((value) => value.address); return ip!; } diff --git a/lib/utils/python.dart b/lib/utils/python.dart index b73c09a..62e5829 100644 --- a/lib/utils/python.dart +++ b/lib/utils/python.dart @@ -47,7 +47,6 @@ bool processCookies(StringBuffer py, List headers) { for (String header in headers) { if (header.toLowerCase().startsWith("cookie:")) { py.write('cookies = {\n'); - print(header); var cookies = header.substring(9, header.length - 1).trim().split(';'); for (var cookie in cookies) { var parts = cookie.split('='); diff --git a/pubspec.yaml b/pubspec.yaml index 0eddf0d..b5d94ce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: network_proxy description: ProxyPin publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.1.2+12 +version: 1.1.3+12 environment: sdk: '>=3.0.2 <4.0.0'