mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-03-15 04:23:17 +08:00
ssl配置
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,7 +9,7 @@
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
Podfile.lock
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# network proxy
|
||||
# network proxy
|
||||
|
||||
network proxy
|
||||
http、https抓包工具,支持windows、mac、linux
|
||||
|
||||
mac会提示已损坏,需要到系统偏好设置-安全性与隐私-允许任何来源
|
||||
|
||||
https://blog.niekun.net/archives/1629.html
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMjCCAhoCCQC+wWaWR1OT6jANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJD
|
||||
TjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMQ0wCwYDVQQKDAR3YW5nMQ4wDAYD
|
||||
VQQLDAVzdHVkeTESMBAGA1UEAwwJSHR0cFByb3h5MCAXDTIzMDUyNTA4MTE0NVoY
|
||||
DzIxMjMwNTAxMDgxMTQ1WjBaMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxCzAJ
|
||||
BgNVBAcMAkJKMQ0wCwYDVQQKDAR3YW5nMQ4wDAYDVQQLDAVzdHVkeTESMBAGA1UE
|
||||
AwwJSHR0cFByb3h5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw4KN
|
||||
x5QOzL02eU0vsyEatfT76b6Brdr+/Dky4GzUoIKWX+6Rit5avzUH1whCV8tbahZw
|
||||
Ixs5Qw7oHbHAt0MdY7TJJgpsaiQKQsIJH4M88YILR405GtgsfdU32crdVlMwTTl3
|
||||
qABncvQkmT1KkNyOgQvvlQErl8rx7uXTOZa5WhyX2c/egFu7BG+uDLKvwxBBW7ih
|
||||
JlqonS5XzWzP/jd91gukcsPCxtUdWbQVjZwS37oDg12m7nXdL4vACQNnSa4v8VFL
|
||||
Euaq9+62EHdj4A3M45MAh2nytyzOpg6/U17R4/0BicOiOfYM0UtAubirEWggj/4i
|
||||
pzo1an79HHWffVw5/QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB71piBuwMvKlyz
|
||||
SAX55hLCvPSxgIIjrLRiH3xqYTAbxvyaxgxlCjexNZZjuf5tJtrZ18OY+blw9SFT
|
||||
SSY943q+6Go/rPo89vOa64fZ/yafR2AIF8S7K44F48QS0avz3kn1ljYu3CPEv9Ca
|
||||
XFaYV8iPbMymIj0ahIM+edoVP4Iv6fWSqrSt+LyIMTWrB59pS91169kISoyDHUO0
|
||||
isE8xqT82i2Jzi/AowVs9gDkVUumwv8GlkhoqQFQzaQgLVggK2bkYkRw7PaH3992
|
||||
tezjL5KswWcBaVBPELCDAsh4tJ/2SzyUm6kKjoU446W4CXcjCjxYj140UhBj7tWw
|
||||
l1IW1yiL
|
||||
MIIDPDCCAiQCCQDjt1nXbWzgyDANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJD
|
||||
TjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMQ4wDAYDVQQKDAVQcm94eTERMA8G
|
||||
A1UECwwIUHJveHlQaW4xFDASBgNVBAMMC1Byb3h5UGluIENBMB4XDTIzMDYxODA2
|
||||
MTg1NFoXDTMzMDYxNTA2MTg1NFowYDELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJK
|
||||
MQswCQYDVQQHDAJCSjEOMAwGA1UECgwFUHJveHkxETAPBgNVBAsMCFByb3h5UGlu
|
||||
MRQwEgYDVQQDDAtQcm94eVBpbiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBAMRjfFvFDZS+PsdedUNq0Kn5t7RFNS0iQrZALr4LJm3UwtatHtMEWBb9
|
||||
ptam8pWezxrZPZ81+qnTcaq/To82yus5hJa4JRk223YWn5JDd4izH4gcnSomhUQ6
|
||||
Ycrc0v+I7UEaHV+bQsleHEfYi2+E1qF+FBhRveLSPmz2QORd/U4+gDlOptgNWMQ9
|
||||
OTRHsMoDzb8J4SlcBu+s0dnq2WHOM9boGnfk2wIgE+16uB23epPoYjex8zYGUswh
|
||||
8gNrIzXsr7i9IGtGf67FQYCWOXfZLeGgy0Q0/r1lwSmywUkNaZIsiGZHveZsLtW9
|
||||
3MWMFw0uneEvHsuQV+e8sdLI/633TGcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
VaGFU7tprM5irUOajfKJ3CXidmRCR3j2IBjOEkMHohGJWZukBphuTHM5OTAlseGl
|
||||
gO/kFDn1K/Exit67koqqJGPQCg3bmtjLGApInQzVD1UFs6ePtVGj6oXuBPdz2gl8
|
||||
StnZfOgIf8m8gxs8h8hsovR8ra3NFMnfgt5TJdvarsqKF8+CepEXDkJrtp6geAvp
|
||||
ELJ5y1DA7OSPjBzXQqlr+X4Xh/kqCe4h7EZ48NJRtWX59jruMxnbclV86FNkWjS8
|
||||
P5gm+MygFCMaJYTyyZwT+YztVPiDZIco+IJ1MSRajgaAErqH9FZ4lvcgxiXtz/mc
|
||||
0uPLBkXBktcf2DGR2AAa7w==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,CEF6FB49B2B5361D
|
||||
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
Binary file not shown.
@@ -11,13 +11,29 @@ Future<void> main() async {
|
||||
}
|
||||
|
||||
class ProxyServer {
|
||||
int port = 8888;
|
||||
|
||||
EventListener? listener;
|
||||
ServerSocket? serverSocket;
|
||||
Server? server;
|
||||
|
||||
ProxyServer({this.listener});
|
||||
|
||||
Future<ServerSocket> start() {
|
||||
const port = 8888;
|
||||
///是否启用ssl
|
||||
bool get enableSsl => server?.enableSsl == true;
|
||||
|
||||
set enableSsl(bool enableSsl) {
|
||||
server?.enableSsl = enableSsl;
|
||||
if (server?.isRunning == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Platform.isMacOS) {
|
||||
setSslProxyEnableMacOS(enableSsl);
|
||||
}
|
||||
}
|
||||
|
||||
/// 启动代理服务
|
||||
Future<Server> start() {
|
||||
Server server = Server(port)
|
||||
..initChannel((channel) {
|
||||
channel.pipeline.handle(HttpRequestCodec(), HttpResponseCodec(), HttpChannelHandler(listener: listener));
|
||||
@@ -26,22 +42,24 @@ class ProxyServer {
|
||||
return server.bind().then((serverSocket) {
|
||||
log.i("listen on $port");
|
||||
_setSystemProxy(port);
|
||||
this.serverSocket = serverSocket;
|
||||
|
||||
return serverSocket;
|
||||
this.server = server;
|
||||
return server;
|
||||
});
|
||||
}
|
||||
|
||||
Future<ServerSocket?> stop() async {
|
||||
log.i("stop on ${serverSocket?.port}");
|
||||
/// 停止代理服务
|
||||
Future<Server?> stop() async {
|
||||
log.i("stop on ${server?.port}");
|
||||
if (Platform.isMacOS) {
|
||||
await _setProxyEnableMacOS(false);
|
||||
await setProxyEnableMacOS(false);
|
||||
} else if (Platform.isWindows) {
|
||||
await _setProxyEnableWindows(false);
|
||||
}
|
||||
return serverSocket?.close();
|
||||
await server?.stop();
|
||||
return server;
|
||||
}
|
||||
|
||||
/// 设置系统代理
|
||||
void _setSystemProxy(int port) async {
|
||||
if (Platform.isMacOS) {
|
||||
_setProxyServerMacOS("127.0.0.1:$port");
|
||||
@@ -52,87 +70,79 @@ class ProxyServer {
|
||||
}
|
||||
|
||||
Future<bool> _setProxyServerMacOS(String proxyServer) async {
|
||||
try {
|
||||
var match = RegExp(r"^(?:http://)?(?<host>.+):(?<port>\d+)$").firstMatch(proxyServer);
|
||||
if (match == null) {
|
||||
print('proxyServer parse error!');
|
||||
return false;
|
||||
}
|
||||
var host = match.namedGroup('host');
|
||||
var port = match.namedGroup('port');
|
||||
var results = await Process.run('bash', [
|
||||
'-c',
|
||||
_concatCommands([
|
||||
'networksetup -setwebproxy wi-fi $host $port',
|
||||
// 'networksetup -setsecurewebproxy wi-fi $host $port',
|
||||
'networksetup -setproxybypassdomains wi-fi 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 127.0.0.1, localhost, *.local, timestamp.apple.com, sequoia.apple.com, seed-sequoia.siri.apple.com',
|
||||
])
|
||||
]);
|
||||
return results.exitCode == 0;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
var match = RegExp(r"^(?:http://)?(?<host>.+):(?<port>\d+)$").firstMatch(proxyServer);
|
||||
if (match == null) {
|
||||
print('proxyServer parse error!');
|
||||
return false;
|
||||
}
|
||||
var host = match.namedGroup('host');
|
||||
var port = match.namedGroup('port');
|
||||
var results = await Process.run('bash', [
|
||||
'-c',
|
||||
_concatCommands([
|
||||
'networksetup -setwebproxy wi-fi $host $port',
|
||||
enableSsl ? 'networksetup -setsecurewebproxy wi-fi $host $port' : '',
|
||||
'networksetup -setproxybypassdomains wi-fi 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 127.0.0.1, localhost, *.local, timestamp.apple.com, sequoia.apple.com, seed-sequoia.siri.apple.com',
|
||||
])
|
||||
]);
|
||||
print('set proxyServer, exitCode: ${results.exitCode}, stdout: ${results.stdout}');
|
||||
return results.exitCode == 0;
|
||||
}
|
||||
|
||||
Future<bool> _setProxyEnableMacOS(bool proxyEnable) async {
|
||||
try {
|
||||
var proxyMode = proxyEnable ? 'on' : 'off';
|
||||
var results = await Process.run('bash', [
|
||||
'-c',
|
||||
_concatCommands([
|
||||
'networksetup -setwebproxystate wi-fi $proxyMode',
|
||||
// 'networksetup -setsecurewebproxystate wi-fi $proxyMode',
|
||||
])
|
||||
]);
|
||||
return results.exitCode == 0;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return false;
|
||||
}
|
||||
Future<bool> setProxyEnableMacOS(bool proxyEnable) async {
|
||||
var proxyMode = proxyEnable ? 'on' : 'off';
|
||||
var results = await Process.run('bash', [
|
||||
'-c',
|
||||
_concatCommands([
|
||||
'networksetup -setwebproxystate wi-fi $proxyMode',
|
||||
enableSsl ? 'networksetup -setsecurewebproxystate wi-fi $proxyMode' : '',
|
||||
])
|
||||
]);
|
||||
return results.exitCode == 0;
|
||||
}
|
||||
|
||||
Future<bool> setSslProxyEnableMacOS(bool proxyEnable) async {
|
||||
var results = await Process.run('bash', [
|
||||
'-c',
|
||||
_concatCommands([
|
||||
proxyEnable
|
||||
? 'networksetup -setsecurewebproxy wi-fi 127.0.0.1 ${server?.port}'
|
||||
: 'networksetup -setsecurewebproxystate wi-fi off',
|
||||
])
|
||||
]);
|
||||
return results.exitCode == 0;
|
||||
}
|
||||
|
||||
Future<bool> _setProxyEnableWindows(bool proxyEnable) async {
|
||||
try {
|
||||
var results = await Process.run('reg', [
|
||||
'add',
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'/v',
|
||||
'ProxyEnable',
|
||||
'/t',
|
||||
'REG_DWORD',
|
||||
'/f',
|
||||
'/d',
|
||||
proxyEnable ? '1' : '0',
|
||||
]);
|
||||
print('set proxyEnable, exitCode: ${results.exitCode}, stdout: ${results.stdout}');
|
||||
return results.exitCode == 0;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return false;
|
||||
}
|
||||
var results = await Process.run('reg', [
|
||||
'add',
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'/v',
|
||||
'ProxyEnable',
|
||||
'/t',
|
||||
'REG_DWORD',
|
||||
'/f',
|
||||
'/d',
|
||||
proxyEnable ? '1' : '0',
|
||||
]);
|
||||
return results.exitCode == 0;
|
||||
}
|
||||
|
||||
Future<bool> _setProxyServerWindows(String proxyServer) async {
|
||||
try {
|
||||
var results = await Process.run('reg', [
|
||||
'add',
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'/v',
|
||||
'ProxyServer',
|
||||
'/f',
|
||||
'/d',
|
||||
proxyServer,
|
||||
]);
|
||||
print('set proxyServer, exitCode: ${results.exitCode}, stdout: ${results.stdout}');
|
||||
return results.exitCode == 0;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_concatCommands(List<String> commands) {
|
||||
return commands.join(' && ');
|
||||
var results = await Process.run('reg', [
|
||||
'add',
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'/v',
|
||||
'ProxyServer',
|
||||
'/f',
|
||||
'/d',
|
||||
proxyServer,
|
||||
]);
|
||||
print('set proxyServer, exitCode: ${results.exitCode}, stdout: ${results.stdout}');
|
||||
return results.exitCode == 0;
|
||||
}
|
||||
}
|
||||
|
||||
_concatCommands(List<String> commands) {
|
||||
return commands.where((element) => element.isNotEmpty).join(' && ');
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class Channel {
|
||||
|
||||
Socket get socket => _socket;
|
||||
|
||||
set secureSocket(secureSocket) => _socket = secureSocket;
|
||||
set secureSocket(SecureSocket secureSocket) => _socket = secureSocket;
|
||||
|
||||
Future<void> write(Object obj) async {
|
||||
var data = pipeline._encoder.encode(obj);
|
||||
@@ -105,6 +105,12 @@ class ChannelPipeline extends ChannelHandler<Uint8List> {
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
void listen(Channel channel) {
|
||||
channel.socket.listen((data) => channel.pipeline.channelRead(channel, data),
|
||||
onError: (error, trace) => channel.pipeline.exceptionCaught(channel, error, trace: trace),
|
||||
onDone: () => channel.pipeline.channelInactive(channel));
|
||||
}
|
||||
|
||||
@override
|
||||
void channelActive(Channel channel) {
|
||||
_handler.channelActive(channel);
|
||||
@@ -227,6 +233,7 @@ abstract interface class ChannelInitializer {
|
||||
|
||||
class Network {
|
||||
late Function _channelInitializer;
|
||||
bool enableSsl = false;
|
||||
|
||||
Network initChannel(void Function(Channel channel) initializer) {
|
||||
_channelInitializer = initializer;
|
||||
@@ -245,29 +252,40 @@ class Network {
|
||||
|
||||
_onEvent(Uint8List data, Channel channel) async {
|
||||
HostAndPort? hostAndPort = channel.getAttribute(AttributeKeys.host);
|
||||
//黑名单 直接转发
|
||||
if (HostFilter.filter(hostAndPort?.host) || (hostAndPort?.isSsl() == true && !enableSsl)) {
|
||||
relay(channel, channel.getAttribute(channel.id));
|
||||
channel.pipeline.channelRead(channel, data);
|
||||
return;
|
||||
}
|
||||
|
||||
//ssl握手
|
||||
if (hostAndPort?.isSsl() == true) {
|
||||
try {
|
||||
var certificate = await CertificateManager.getCertificateContext(hostAndPort!.host);
|
||||
SecureSocket secureSocket = await SecureSocket.secureServer(channel.socket, certificate, bufferedData: data);
|
||||
channel.secureSocket = secureSocket;
|
||||
secureSocket.listen((event) => channel.pipeline.channelRead(channel, event));
|
||||
} catch (error, trace) {
|
||||
channel.pipeline._handler.exceptionCaught(channel, error, trace: trace);
|
||||
}
|
||||
ssl(channel, hostAndPort!, data);
|
||||
return;
|
||||
}
|
||||
//黑名单
|
||||
if (hostAndPort != null && HostFilter.filter(hostAndPort.host)) {
|
||||
if (HostFilter.filter(hostAndPort.host)) {
|
||||
relay(channel, channel.getAttribute(channel.id));
|
||||
}
|
||||
}
|
||||
|
||||
channel.pipeline.channelRead(channel, data);
|
||||
}
|
||||
|
||||
void ssl(Channel channel, HostAndPort hostAndPort, Uint8List data) async {
|
||||
try {
|
||||
//客户端ssl
|
||||
Channel remoteChannel = channel.getAttribute(channel.id);
|
||||
remoteChannel.secureSocket =
|
||||
await SecureSocket.secure(remoteChannel.socket, onBadCertificate: (certificate) => true);
|
||||
remoteChannel.pipeline.listen(remoteChannel);
|
||||
|
||||
//服务端ssl
|
||||
var certificate = await CertificateManager.getCertificateContext(hostAndPort.host);
|
||||
SecureSocket secureSocket = await SecureSocket.secureServer(channel.socket, certificate, bufferedData: data);
|
||||
channel.secureSocket = secureSocket;
|
||||
channel.pipeline.listen(channel);
|
||||
} catch (error, trace) {
|
||||
channel.pipeline._handler.exceptionCaught(channel, error, trace: trace);
|
||||
}
|
||||
}
|
||||
|
||||
/// 转发请求
|
||||
void relay(Channel clientChannel, Channel remoteChannel) {
|
||||
var rawCodec = RawCodec();
|
||||
@@ -284,11 +302,11 @@ class Server extends Network {
|
||||
Server(this.port);
|
||||
|
||||
Future<ServerSocket> bind() async {
|
||||
serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, port);
|
||||
serverSocket = await ServerSocket.bind(InternetAddress.anyIPv4, port);
|
||||
serverSocket.listen((socket) {
|
||||
isRunning = true;
|
||||
listen(socket);
|
||||
});
|
||||
isRunning = true;
|
||||
return serverSocket;
|
||||
}
|
||||
|
||||
@@ -300,13 +318,7 @@ class Server extends Network {
|
||||
}
|
||||
|
||||
class Client extends Network {
|
||||
var log = Logger();
|
||||
|
||||
Future<Channel> connect(HostAndPort hostAndPort) async {
|
||||
if (hostAndPort.isSsl()) {
|
||||
return SecureSocket.connect(hostAndPort.host, hostAndPort.port, onBadCertificate: (certificate) => true)
|
||||
.then((socket) => listen(socket));
|
||||
}
|
||||
return Socket.connect(hostAndPort.host, hostAndPort.port, timeout: const Duration(seconds: 10))
|
||||
.then((socket) => listen(socket));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:network/network/http/http.dart';
|
||||
import 'package:network/network/http/http_headers.dart';
|
||||
import 'package:network/network/util/attribute_keys.dart';
|
||||
@@ -34,7 +35,7 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
void channelRead(Channel channel, HttpRequest msg) async {
|
||||
forward(channel, msg).catchError((error, trace) {
|
||||
if (error is SocketException &&
|
||||
(error.message.contains("Failed host lookup") || error.message.contains(" Operation timed out"))) {
|
||||
(error.message.contains("Failed host lookup") || error.message.contains("Connection timed out"))) {
|
||||
log.e("连接失败 ${error.message}");
|
||||
channel.close();
|
||||
return;
|
||||
@@ -54,14 +55,21 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
Future<void> forward(Channel channel, HttpRequest httpRequest) async {
|
||||
channel.putAttribute(AttributeKeys.request, httpRequest);
|
||||
|
||||
if (httpRequest.uri == 'http://proxy.pin/ssl') {
|
||||
_crtDownload(channel, httpRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
var remoteChannel = await _getRemoteChannel(channel, httpRequest);
|
||||
|
||||
//实现抓包代理转发
|
||||
if (httpRequest.method != HttpMethod.connect) {
|
||||
if (channel.getAttribute(AttributeKeys.host) == null) {
|
||||
remoteChannel.putAttribute(AttributeKeys.uri, httpRequest.uri);
|
||||
} else {
|
||||
if (httpRequest.uri.startsWith("/")) {
|
||||
remoteChannel.putAttribute(AttributeKeys.uri, '${channel.getAttribute(AttributeKeys.host)}${httpRequest.uri}');
|
||||
} else {
|
||||
remoteChannel.putAttribute(AttributeKeys.uri, httpRequest.uri);
|
||||
}
|
||||
|
||||
// log.i("[${channel.id}] ${remoteChannel.getAttribute(AttributeKeys.uri)}");
|
||||
listener?.onRequest(channel, httpRequest);
|
||||
//实现抓包代理转发
|
||||
@@ -69,6 +77,16 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
}
|
||||
}
|
||||
|
||||
void _crtDownload(Channel channel, HttpRequest request) async{
|
||||
const String fileMimeType = 'application/x-x509-ca-cert';
|
||||
var body = await rootBundle.load('assets/certs/ca.crt');
|
||||
var response = HttpResponse(request.protocolVersion, HttpStatus.ok);
|
||||
response.headers.set(HttpHeaders.CONTENT_TYPE, fileMimeType);
|
||||
response.headers.set("Content-Disposition", 'attachment; filename="ProxyPin CA.crt"');
|
||||
response.body = body.buffer.asUint8List();
|
||||
channel.write(response);
|
||||
}
|
||||
|
||||
/// 获取远程连接
|
||||
Future<Channel> _getRemoteChannel(Channel clientChannel, HttpRequest httpRequest) async {
|
||||
String clientId = clientChannel.id;
|
||||
@@ -127,6 +145,10 @@ class RelayHandler extends ChannelHandler<Object> {
|
||||
//发送给客户端
|
||||
remoteChannel.write(msg);
|
||||
}
|
||||
@override
|
||||
void channelInactive(Channel channel) {
|
||||
remoteChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
class HttpClients {
|
||||
|
||||
@@ -168,7 +168,7 @@ abstract class HttpCodec<T extends HttpMessage> implements Codec<T> {
|
||||
List<int> _convertBody() {
|
||||
List<int> bytes = _bodyBuffer.toBytes();
|
||||
if (message.headers.isGzip) {
|
||||
bytes = gzipDecode(bytes);
|
||||
bytes = gzipDecode(bytes);
|
||||
}
|
||||
_bodyBuffer.clear();
|
||||
return bytes;
|
||||
|
||||
@@ -46,9 +46,15 @@ abstract class HostList {
|
||||
final List<RegExp> list = [];
|
||||
bool enabled = false;
|
||||
|
||||
List<Function> initListens = [];
|
||||
List<Function> _initListens = [];
|
||||
bool _inited = false;
|
||||
|
||||
void addInitListen(void Function() action) {
|
||||
if (!_inited) {
|
||||
_initListens.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initList() async {
|
||||
if (_inited) {
|
||||
return;
|
||||
@@ -67,7 +73,7 @@ abstract class HostList {
|
||||
}
|
||||
});
|
||||
_inited = true;
|
||||
for (var fun in initListens) {
|
||||
for (var fun in _initListens) {
|
||||
fun();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:network/network/bin/server.dart';
|
||||
import 'package:network/network/channel.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class SocketLaunch extends StatefulWidget {
|
||||
@@ -55,7 +54,7 @@ class _SocketLaunchState extends State<SocketLaunch> with WindowListener {
|
||||
size: 25,
|
||||
),
|
||||
onPressed: () async {
|
||||
Future<ServerSocket?> result = started ? widget.proxyServer.stop() : widget.proxyServer.start();
|
||||
Future<Server?> result = started ? widget.proxyServer.stop() : widget.proxyServer.start();
|
||||
result.then((value) => setState(() {
|
||||
started = !started;
|
||||
}));
|
||||
|
||||
@@ -27,6 +27,9 @@ class _DomainFilterState extends State<DomainFilter> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
widget.hostList.addInitListen(() {
|
||||
widget.hostEnableNotifier.value = !widget.hostEnableNotifier.value;
|
||||
});
|
||||
domainList = DomainList(widget.hostList);
|
||||
|
||||
return Column(
|
||||
@@ -145,7 +148,7 @@ class _DomainListState extends State<DomainList> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
widget.hostList.initListens.add(() {
|
||||
widget.hostList.addInitListen(() {
|
||||
setState(() {});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:network/network/bin/server.dart';
|
||||
import 'package:network/ui/toolbar/setting/theme.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../../network/util/host_filter.dart';
|
||||
import 'filter.dart';
|
||||
|
||||
class Setting extends StatefulWidget {
|
||||
const Setting({super.key});
|
||||
final ProxyServer proxyServer;
|
||||
const Setting({super.key, required this.proxyServer});
|
||||
|
||||
@override
|
||||
State<Setting> createState() => _SettingState();
|
||||
@@ -24,25 +27,38 @@ class _SettingState extends State<Setting> {
|
||||
return [
|
||||
PopupMenuItem<String>(
|
||||
child: Row(children: [
|
||||
const Padding(padding: EdgeInsets.only(left: 18)),
|
||||
const Text("端口号:", style: TextStyle(fontSize: 15)),
|
||||
const Padding(padding: EdgeInsets.only(left: 16)),
|
||||
const Text("端口号:", style: TextStyle(fontSize: 13)),
|
||||
SizedBox(
|
||||
width: 80,
|
||||
child: TextFormField(
|
||||
initialValue: "8888",
|
||||
initialValue: widget.proxyServer.port.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
LengthLimitingTextInputFormatter(5),
|
||||
FilteringTextInputFormatter.allow(RegExp("[0-9]"))
|
||||
],
|
||||
decoration: const InputDecoration(),
|
||||
decoration: const InputDecoration( ),
|
||||
))
|
||||
])),
|
||||
const PopupMenuItem(
|
||||
child: ThemeSetting(),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
child: ListTile(title: const Text("域名过滤"), trailing: const Icon(Icons.arrow_right), onTap: () => _filter()),
|
||||
child: ListTile(
|
||||
title: const Text("域名过滤"),
|
||||
dense: true,
|
||||
trailing: const Icon(Icons.arrow_right),
|
||||
onTap: () => _filter())
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
child: const ListTile(
|
||||
title: Text("Github"),
|
||||
dense: true,
|
||||
trailing: Icon(Icons.arrow_right)),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse("https://github.com/wanghongenpin/network-proxy-flutter"));
|
||||
},
|
||||
)
|
||||
];
|
||||
},
|
||||
|
||||
@@ -7,27 +7,32 @@ class ThemeSetting extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopupMenuButton(
|
||||
tooltip: themeNotifier.value.name,
|
||||
surfaceTintColor: Colors.white70,
|
||||
offset: const Offset(150, 0),
|
||||
itemBuilder: (BuildContext context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
child: const ListTile(trailing: Icon(Icons.cached), title: Text("跟随系统")),
|
||||
child: const ListTile(trailing: Icon(Icons.cached), dense: true, title: Text("跟随系统")),
|
||||
onTap: () {
|
||||
themeNotifier.value = ThemeMode.system;
|
||||
}),
|
||||
PopupMenuItem(
|
||||
child: const ListTile(trailing: Icon(Icons.nightlight_outlined), title: Text("深色")),
|
||||
child: const ListTile(trailing: Icon(Icons.nightlight_outlined), dense: true, title: Text("深色")),
|
||||
onTap: () {
|
||||
themeNotifier.value = ThemeMode.dark;
|
||||
}),
|
||||
PopupMenuItem(
|
||||
child: const ListTile(trailing: Icon(Icons.sunny), title: Text("浅色")),
|
||||
child: const ListTile(trailing: Icon(Icons.sunny), dense: true, title: Text("浅色")),
|
||||
onTap: () {
|
||||
themeNotifier.value = ThemeMode.light;
|
||||
}),
|
||||
];
|
||||
},
|
||||
child: const ListTile(title: Text("主题"), trailing: Icon(Icons.arrow_right)));
|
||||
child: const ListTile(
|
||||
title: Text("主题"),
|
||||
trailing: Icon(Icons.arrow_right),
|
||||
dense: true,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import 'package:file_selector/file_selector.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../../network/bin/server.dart';
|
||||
|
||||
class SslWidget extends StatefulWidget {
|
||||
const SslWidget({super.key});
|
||||
final ProxyServer proxyServer;
|
||||
|
||||
const SslWidget({super.key, required this.proxyServer});
|
||||
|
||||
@override
|
||||
State<SslWidget> createState() => _SslState();
|
||||
@@ -13,36 +18,88 @@ class _SslState extends State<SslWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopupMenuButton<String>(
|
||||
tooltip: "ssl证书",
|
||||
icon: const Icon(Icons.https),
|
||||
surfaceTintColor: Colors.white70,
|
||||
tooltip: "Https代理",
|
||||
offset: const Offset(10, 30),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
child: SwitchListTile(title: const Text("启用Https代理"), value: true, onChanged: (d) {}),
|
||||
),
|
||||
PopupMenuItem(child: _Switch(proxyServer: widget.proxyServer)),
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
title: const Text("ssl证书"),
|
||||
dense: true,
|
||||
title: const Text("安装根证书到系统"),
|
||||
trailing: const Icon(Icons.arrow_right),
|
||||
onTap: () {
|
||||
_downloadCert();
|
||||
pcCer();
|
||||
},
|
||||
)),
|
||||
const PopupMenuItem<String>(
|
||||
child: ListTile(title: Text("安装根证书到IOS"), trailing: Icon(Icons.arrow_right)),
|
||||
PopupMenuItem<String>(
|
||||
child: ListTile(
|
||||
title: const Text("安装根证书到手机"),
|
||||
dense: true,
|
||||
trailing: const Icon(Icons.arrow_right),
|
||||
onTap: () {
|
||||
mobileCer();
|
||||
}),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
child: ListTile(title: Text("安装根证书到Android"), trailing: Icon(Icons.arrow_right)),
|
||||
)
|
||||
// const PopupMenuItem<String>(
|
||||
// child: ListTile(title: Text("安装根证书到Android"), dense: true, trailing: Icon(Icons.arrow_right)),
|
||||
// )
|
||||
];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void pcCer() async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
contentPadding: const EdgeInsets.all(16),
|
||||
title: const Text("电脑https抓包配置", style: TextStyle(fontSize: 16)),
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const Text("1.下载根证书安装到本系统(已完成忽略)"),
|
||||
FilledButton(onPressed: () => _downloadCert(), child: const Text("下载证书")),
|
||||
const SizedBox(height: 10),
|
||||
const Text("2.双击安装证书,Mac安装完选择“始终信任此证书”,\n Windows选择“受信任的根证书颁发机构” "),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
void mobileCer() async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
contentPadding: const EdgeInsets.all(16),
|
||||
title: const Text("手机https抓包配置", style: TextStyle(fontSize: 16)),
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const Text("1. 根证书安装到本系统(已完成忽略)"),
|
||||
const SizedBox(height: 10),
|
||||
const Text.rich(TextSpan(text: "2.配置手机Wifi代理 ")),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
const Text("3.打开手机系统自带浏览器访问:"),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
launchUrl(Uri.parse("http://proxy.pin/ssl"));
|
||||
},
|
||||
child:
|
||||
const Text("http://proxy.pin/ssl", style: TextStyle(decoration: TextDecoration.underline)))
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const Text("4.打开手机设置下载安装证书(Profile)和信任证书(Certificate) \n\t 设置 > 通用 > 关于本机 > 证书信任设置"),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
void _downloadCert() async {
|
||||
final String? path = await getSavePath(suggestedName: "ca_root.crt");
|
||||
final String? path = await getSavePath(suggestedName: "ProxyPinCA.crt");
|
||||
if (path != null) {
|
||||
const String fileMimeType = 'application/x-x509-ca-cert';
|
||||
var body = await rootBundle.load('assets/certs/ca.crt');
|
||||
@@ -54,3 +111,27 @@ class _SslState extends State<SslWidget> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _Switch extends StatefulWidget {
|
||||
final ProxyServer proxyServer;
|
||||
|
||||
const _Switch({Key? key, required this.proxyServer}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_Switch> createState() => _SwitchState();
|
||||
}
|
||||
|
||||
class _SwitchState extends State<_Switch> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SwitchListTile(
|
||||
title: const Text("启用Https代理", style: TextStyle(fontSize: 12)),
|
||||
visualDensity: const VisualDensity(horizontal: -4),
|
||||
dense: true,
|
||||
value: widget.proxyServer.enableSsl,
|
||||
onChanged: (val) {
|
||||
widget.proxyServer.enableSsl = val;
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,16 +30,15 @@ class _ToolbarState extends State<Toolbar> with WindowListener {
|
||||
SocketLaunch(proxyServer: widget.proxyServer),
|
||||
const Padding(padding: EdgeInsets.only(left: 30)),
|
||||
IconButton(
|
||||
isSelected: true,
|
||||
tooltip: "清理",
|
||||
icon: const Icon(Icons.cleaning_services_outlined),
|
||||
onPressed: () {
|
||||
widget.domainWidget.clean();
|
||||
}),
|
||||
const Padding(padding: EdgeInsets.only(left: 30)),
|
||||
const SslWidget(),
|
||||
SslWidget(proxyServer: widget.proxyServer),
|
||||
const Padding(padding: EdgeInsets.only(left: 30)),
|
||||
const Setting(),
|
||||
Setting(proxyServer: widget.proxyServer),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,12 @@ import 'dart:io';
|
||||
///GZIP 解压缩
|
||||
List<int> gzipDecode(List<int> byteBuffer) {
|
||||
GZipCodec gzipCodec = GZipCodec();
|
||||
return gzipCodec.decode(byteBuffer);
|
||||
try {
|
||||
return gzipCodec.decode(byteBuffer);
|
||||
} catch (e) {
|
||||
print("gzipDecode error: $e");
|
||||
return byteBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
///GZIP 解压缩
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
@@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
screen_retriever
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ import Foundation
|
||||
import file_selector_macos
|
||||
import path_provider_foundation
|
||||
import screen_retriever
|
||||
import url_launcher_macos
|
||||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* network.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = network.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10ED2044A3C60003C045 /* ProxyPin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProxyPin.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@@ -160,7 +160,7 @@
|
||||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* network.app */,
|
||||
33CC10ED2044A3C60003C045 /* ProxyPin.app */,
|
||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
@@ -253,7 +253,7 @@
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* network.app */;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* ProxyPin.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
@@ -608,7 +608,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = DM3F8VR243;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -745,6 +745,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = DM3F8VR243;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -765,10 +766,11 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = DM3F8VR243;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "network.app"
|
||||
BuildableName = "ProxyPin.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
@@ -31,7 +31,7 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "network.app"
|
||||
BuildableName = "ProxyPin.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
@@ -65,7 +65,7 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "network.app"
|
||||
BuildableName = "ProxyPin.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
@@ -82,7 +82,7 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "network.app"
|
||||
BuildableName = "ProxyPin.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<false/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.scripting-targets</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.scripting-targets</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
64
pubspec.lock
64
pubspec.lock
@@ -421,6 +421,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.11"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.35"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.17"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -17,6 +17,7 @@ dependencies:
|
||||
file_selector: ^0.9.3
|
||||
window_manager: ^0.3.4
|
||||
path_provider: ^2.0.15
|
||||
url_launcher: ^6.1.11
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
@@ -15,6 +16,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
WindowManagerPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_windows
|
||||
screen_retriever
|
||||
url_launcher_windows
|
||||
window_manager
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user