mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-03-26 06:29:46 +08:00
安卓签名证书
This commit is contained in:
@@ -21,6 +21,12 @@ if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
@@ -53,16 +59,30 @@ android {
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
signingConfig signingConfigs.release
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
android/key.properties
Normal file
4
android/key.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
storePassword=proxypin
|
||||
keyPassword=proxypin
|
||||
keyAlias=proxypin
|
||||
storeFile=../keystore.jks
|
||||
BIN
android/keystore.jks
Normal file
BIN
android/keystore.jks
Normal file
Binary file not shown.
@@ -92,7 +92,6 @@ class Network {
|
||||
}
|
||||
String? host = hostAndPort?.host;
|
||||
host ??= TLS.getDomain(data);
|
||||
|
||||
//ssl自签证书
|
||||
var certificate = await CertificateManager.getCertificateContext(host!);
|
||||
//服务端等待客户端ssl握手
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
/*
|
||||
* Copyright 2023 WangHongEn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
class TLS {
|
||||
///判断是否是TLS Client Hello
|
||||
static bool isTLSClientHello(Uint8List data) {
|
||||
if (data.length < 43) return false;
|
||||
if (data[0] != 0x16 /* handshake */) return false;
|
||||
if (data[1] != 0x03 || data[2] < 0x00 || data[2] > 0x03) return false;
|
||||
if (data[5] != 0x01 /* client_hello */) return false;
|
||||
if (data[9] != 0x03 || data[10] < 0x00 || data[10] > 0x03) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
///从TLS Client Hello 解析域名
|
||||
static String? getDomain(Uint8List data) {
|
||||
try {
|
||||
|
||||
@@ -321,7 +321,7 @@ class ScriptList extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ScriptListState extends State<ScriptList> {
|
||||
Map<int, bool> selected = {};
|
||||
int selected = -1;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -354,47 +354,9 @@ class _ScriptListState extends State<ScriptList> {
|
||||
}
|
||||
});
|
||||
},
|
||||
onSecondaryTapDown: (details) {
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (_) => ScriptEdit(scriptItem: list[index], script: script)).then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("导出"), onTap: () => export(list[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: list[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
list[index].enabled = !list[index].enabled;
|
||||
setState(() {});
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
setState(() {});
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]);
|
||||
},
|
||||
onSecondaryTapDown: (details) => showMenus(details, index),
|
||||
child: Container(
|
||||
color: selected[index] == true
|
||||
color: selected == index
|
||||
? primaryColor.withOpacity(0.8)
|
||||
: index.isEven
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
@@ -421,6 +383,52 @@ class _ScriptListState extends State<ScriptList> {
|
||||
});
|
||||
}
|
||||
|
||||
//点击菜单
|
||||
showMenus(TapDownDetails details, int index) {
|
||||
setState(() {
|
||||
selected = index;
|
||||
});
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(widget.scripts[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (_) => ScriptEdit(scriptItem: widget.scripts[index], script: script)).then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("导出"), onTap: () => export(widget.scripts[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: widget.scripts[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
widget.scripts[index].enabled = !widget.scripts[index].enabled;
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]).then((value) {
|
||||
setState(() {
|
||||
selected = -1;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//导出js
|
||||
export(ScriptItem item) async {
|
||||
//文件名称
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:network_proxy/main.dart';
|
||||
|
||||
class ThemeSetting extends StatelessWidget {
|
||||
const ThemeSetting({Key? key}) : super(key: key);
|
||||
const ThemeSetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -12,7 +12,8 @@ class SocketLaunch extends StatefulWidget {
|
||||
final bool startup;
|
||||
final Function? onStart;
|
||||
final Function? onStop;
|
||||
final bool serverLaunch;
|
||||
|
||||
final bool serverLaunch; //是否启动代理服务器
|
||||
|
||||
const SocketLaunch(
|
||||
{super.key,
|
||||
@@ -30,7 +31,7 @@ class SocketLaunch extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SocketLaunchState extends State<SocketLaunch> with WindowListener, WidgetsBindingObserver {
|
||||
bool started = false;
|
||||
static bool started = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:easy_permission/easy_permission.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
|
||||
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/host_filter.dart';
|
||||
@@ -211,7 +212,7 @@ class MoreEnum extends StatelessWidget {
|
||||
hostname: response.headers.get("hostname"));
|
||||
|
||||
if (context.mounted && Navigator.canPop(context)) {
|
||||
FlutterToastr.show("连接成功${proxyServer.isRunning ? '' : ',手机需要开启抓包才可以抓取请求哦'}", context, duration: 3);
|
||||
FlutterToastr.show("连接成功${Vpn.isVpnStarted ? '' : ',手机需要开启抓包才可以抓取请求哦'}", context, duration: 3);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ class _MobileScriptState extends State<MobileScript> {
|
||||
}
|
||||
|
||||
try {
|
||||
var json = jsonDecode(await file.readAsString());
|
||||
var json = jsonDecode(utf8.decode(await file.readAsBytes()));
|
||||
var scriptItem = ScriptItem.fromJson(json);
|
||||
(await ScriptManager.instance).addScript(scriptItem, json['script']);
|
||||
_refreshScript();
|
||||
@@ -148,7 +148,7 @@ class ScriptEdit extends StatefulWidget {
|
||||
final ScriptItem? scriptItem;
|
||||
final String? script;
|
||||
|
||||
const ScriptEdit({Key? key, this.scriptItem, this.script}) : super(key: key);
|
||||
const ScriptEdit({super.key, this.scriptItem, this.script});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ScriptEditState();
|
||||
@@ -230,8 +230,7 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
CodeTheme(
|
||||
data: CodeThemeData(styles: monokaiSublimeTheme),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeField(
|
||||
textStyle: const TextStyle(fontSize: 14), controller: script)))
|
||||
child: CodeField(textStyle: const TextStyle(fontSize: 14), controller: script)))
|
||||
],
|
||||
))));
|
||||
}
|
||||
@@ -271,14 +270,19 @@ class ScriptList extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ScriptListState extends State<ScriptList> {
|
||||
int selected = -1;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(children: rows(widget.scripts));
|
||||
}
|
||||
|
||||
List<Widget> rows(List<ScriptItem> list) {
|
||||
var primaryColor = Theme.of(context).primaryColor;
|
||||
|
||||
return List.generate(list.length, (index) {
|
||||
return InkWell(
|
||||
splashColor: primaryColor.withOpacity(0.3),
|
||||
onDoubleTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
@@ -292,47 +296,13 @@ class _ScriptListState extends State<ScriptList> {
|
||||
}
|
||||
});
|
||||
},
|
||||
onTapDown: (details) {
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => ScriptEdit(scriptItem: list[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("分享"), onTap: () => export(list[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: list[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
list[index].enabled = !list[index].enabled;
|
||||
setState(() {});
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
setState(() {});
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]);
|
||||
},
|
||||
onTapDown: (details) => showMenus(details, index),
|
||||
child: Container(
|
||||
color: index.isEven ? Colors.grey.withOpacity(0.1) : null,
|
||||
color: selected == index
|
||||
? primaryColor.withOpacity(0.8)
|
||||
: index.isEven
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
: null,
|
||||
height: 45,
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Row(
|
||||
@@ -358,6 +328,52 @@ class _ScriptListState extends State<ScriptList> {
|
||||
});
|
||||
}
|
||||
|
||||
//点击菜单
|
||||
showMenus(TapDownDetails details, int index) {
|
||||
setState(() {
|
||||
selected = index;
|
||||
});
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(widget.scripts[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => ScriptEdit(scriptItem: widget.scripts[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("分享"), onTap: () => export(widget.scripts[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: widget.scripts[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
widget.scripts[index].enabled = !widget.scripts[index].enabled;
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]).then((value) {
|
||||
setState(() {
|
||||
selected = -1;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//导出js
|
||||
export(ScriptItem item) async {
|
||||
//文件名称
|
||||
|
||||
58
pubspec.lock
58
pubspec.lock
@@ -267,10 +267,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: ad76540d21c066228ee3f9d1dad64a9f7e46530e8bb7c85011a88bc1fd874bc5
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.0.1"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -337,6 +337,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -353,6 +361,22 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.8.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7e108028e3d258667d079986da8c0bc32da4cb57431c2af03b1dc1038621a9dc"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.0.13"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: b06739349ec2477e943055aea30172c5c7000225f79dad4702e2ec0eda79a6ff
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
linked_scroll_controller:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -397,18 +421,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -734,14 +758,30 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "14f1f70c51119012600c5f1f60ca68efda5a9b6077748163c6af2893ec5df8fc"
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.1-beta"
|
||||
version: "0.3.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -767,5 +807,5 @@ packages:
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
sdks:
|
||||
dart: ">=3.2.0-157.0.dev <4.0.0"
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
|
||||
@@ -37,7 +37,7 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.0
|
||||
flutter_lints: ^3.0.1
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
Reference in New Issue
Block a user