Compare commits

..
101 Commits
Author SHA1 Message Date
Administrator 9afd362de6 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 17:55:49 +08:00
Administrator 5b9cf5a538 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 17:55:48 +08:00
Administrator db203d01e1 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 17:10:32 +08:00
Administrator 8690824663 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 17:10:29 +08:00
Administrator 5ca8148c42 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 16:17:59 +08:00
Administrator e54cafd16b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 16:17:53 +08:00
Administrator c21504993f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 11:49:07 +08:00
Administrator 8e90c904ee Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-14 11:49:04 +08:00
Administrator 85e60c01bc Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-08-06 11:44:55 +08:00
sc 0ce1a57a53 查询逻辑修改,调整aes解码时机日志记录有密文改为明文 2026-08-06 11:44:53 +08:00
sc c2451be4a2 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-07-18 00:45:38 +08:00
sc 8aa79a46e3 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-07-18 00:45:36 +08:00
sc 654f73aca8 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-07-17 23:00:36 +08:00
Administrator a0eeb9c8c4 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-17 23:00:34 +08:00
Administrator ebbb44b132 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 16:53:40 +08:00
Administrator c94fe5c62f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 16:53:39 +08:00
Administrator ffc9b3d425 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 15:51:20 +08:00
Administrator d9d00cc9fa Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 15:51:18 +08:00
Administrator e28be80856 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 15:31:15 +08:00
Administrator db73d606e8 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 15:31:13 +08:00
Administrator 7fb76a9d12 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 14:48:14 +08:00
Administrator 7437355573 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-07-03 14:48:11 +08:00
Administrator 65cfef8d02 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 17:34:26 +08:00
Administrator ea2e55787c 添加字符串加密 2026-06-25 17:34:17 +08:00
Administrator 85a4630020 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 13:36:30 +08:00
Administrator 5aca5ad39f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 13:36:27 +08:00
Administrator fd88cca4c6 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 12:42:38 +08:00
Administrator cb1e7a2e65 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 12:42:35 +08:00
Administrator ee65be0f93 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 12:38:04 +08:00
Administrator 59e1272cdb Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-25 12:38:00 +08:00
sc 474093d2f2 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-06-21 18:19:14 +08:00
sc d39aadc98d Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-06-21 18:19:12 +08:00
sc eb3e13c63a Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-06-21 17:07:31 +08:00
Administrator 610c9c31ac Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-21 17:07:30 +08:00
Administrator e38418500d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-12 00:11:00 +08:00
Administrator b70596cf31 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-12 00:10:59 +08:00
Administrator 5c8071f1f4 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-11 23:09:55 +08:00
Administrator 3bbfe20f84 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-11 23:09:25 +08:00
Administrator 9a5195cb0a Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-11 00:36:15 +08:00
Administrator 683f8ac880 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-11 00:36:14 +08:00
Administrator 0b444636a4 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-10 20:23:08 +08:00
Administrator 710672bfc0 机台信息管理页面修改 2026-06-10 20:23:06 +08:00
Administrator a92610c2f4 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 23:24:38 +08:00
Administrator c43531c206 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 23:24:35 +08:00
Administrator f1085c0291 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 18:12:31 +08:00
Administrator 7860fe088b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 18:12:28 +08:00
Administrator dbcdc02d91 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 18:04:43 +08:00
Administrator d35420bed1 历史查询功能 2026-06-08 18:04:17 +08:00
Administrator 7039c1d5eb Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 01:12:41 +08:00
Administrator 919e0b662b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-08 01:12:30 +08:00
Administrator 498f65dae9 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-06 00:13:26 +08:00
Administrator 797738c240 添加信息通知,回复Notification请求的信息 2026-06-06 00:13:23 +08:00
Administrator c5c8c536be Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-03 23:32:47 +08:00
Administrator aee911cc20 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-03 23:32:44 +08:00
Administrator 8213e51756 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-03 00:30:54 +08:00
Administrator 751bbe5199 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-03 00:30:52 +08:00
Administrator a58132e6d8 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-02 23:40:56 +08:00
Administrator c362d9177f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-02 23:40:54 +08:00
Administrator e06aeb054c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-02 23:13:41 +08:00
Administrator ea0077a3e7 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-02 23:13:39 +08:00
Administrator 7ec9c22520 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-02 00:23:43 +08:00
Administrator 5d9ab90ed3 用户信息和数据库的增删改查修改 2026-06-02 00:23:41 +08:00
Administrator f2a3b697d2 日志输出逻辑修改 2026-06-01 17:53:48 +08:00
Administrator 10611241d1 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-01 15:42:45 +08:00
Administrator 6c27d7c0e5 添加行为记录查看 2026-06-01 15:39:01 +08:00
Administrator b079f6556c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-01 13:28:02 +08:00
Administrator 6b16bc838c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-01 13:28:00 +08:00
Administrator a5151aa64a Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-06-01 01:01:59 +08:00
Administrator 43438924e6 公网服务器连接 2026-06-01 00:46:21 +08:00
Administrator d9cb455c19 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-28 00:20:32 +08:00
Administrator 480d705255 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-28 00:20:29 +08:00
Administrator 6bd3b7ba60 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-24 01:38:15 +08:00
Administrator 9b010a4998 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-24 01:38:14 +08:00
Administrator 4e6ad0a7dc Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-24 01:20:57 +08:00
Administrator 351ce7cb32 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-24 01:20:54 +08:00
Administrator 6dd5b39eca Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-24 01:12:43 +08:00
Administrator c379f00675 添加服务状态表格 2026-05-24 01:12:37 +08:00
Administrator 86fb94f049 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-23 17:21:26 +08:00
Administrator d03deee97a Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-23 17:21:23 +08:00
Administrator ef203da2cd Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-21 21:08:34 +08:00
Administrator 3840701756 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-21 21:08:32 +08:00
Administrator bedb32e988 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-20 01:48:49 +08:00
Administrator a61a74340e 料单查询相关指令 2026-05-20 01:48:47 +08:00
Administrator a74aacf255 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-19 01:34:34 +08:00
Administrator 84b14491e2 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-19 01:34:31 +08:00
Administrator 4b9da1b72d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-14 23:03:52 +08:00
Administrator 650c7c47d9 添加ip获取 2026-05-14 23:03:48 +08:00
Administrator 60cf47936e Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-12 01:41:12 +08:00
Administrator ecd78d8f6b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-12 01:41:11 +08:00
Administrator 7c3d90c2f8 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-11 02:15:22 +08:00
Administrator ec7e89f5bb Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-11 02:15:19 +08:00
Administrator a63bd23ced Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-08 02:37:34 +08:00
Administrator 4f1025e247 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-08 02:37:32 +08:00
Administrator 439df0d204 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationManager 2026-05-08 01:14:07 +08:00
sc 489460969f 客户端连线记录 2026-05-08 01:14:04 +08:00
sc 66385b1ce4 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-05-03 17:22:31 +08:00
sc 425285b837 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-05-03 17:22:29 +08:00
sc ebe8f4e636 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationManager 2026-05-03 17:20:23 +08:00
sc a36dc31538 项目目录修改 2026-05-03 17:20:21 +08:00
sc 6d5033dbd1 冲突处理 2026-05-03 17:19:28 +08:00
sc c2d15699ab Person添加成员(ip)
项目目录修改
2026-05-03 17:18:37 +08:00
67 changed files with 26123 additions and 164 deletions

No files matched your search

+53 -1
View File
@@ -3,6 +3,7 @@ using System.Configuration;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace SunlightAggregationManager
{
@@ -11,7 +12,58 @@ namespace SunlightAggregationManager
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
RegisterGlobalExceptionHandlers();
}
private void RegisterGlobalExceptionHandlers()
{
// 1. 捕获 UI 主线程的未处理异常
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
// 2. 捕获非 UI 线程(后台线程)的未处理异常
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
// 3. 捕获 Task 异步任务中的未观察到的异常
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
// UI线程异常处理
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogAndShowError("UI线程发生异常", e.Exception);
// 【关键】将 Handled 设为 true,告诉 WPF 该异常已被处理,阻止程序自动闪退
e.Handled = true;
}
// 非UI线程异常处理
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
bool isTerminating = e.IsTerminating;
LogAndShowError($"非UI线程异常 (即将终止: {isTerminating})", exception);
// 注意:此事件不允许设置 Handled=true,默认情况下致命异常仍会导致程序退出
}
// Task线程异常处理
private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
LogAndShowError("Task异步任务异常", e.Exception);
// 标记异常已被观察,防止它被重新抛出导致进程终止
e.SetObserved();
}
private void LogAndShowError(string context, Exception ex)
{
// 在这里记录日志或弹出友好的自定义错误提示窗口
MessageBox.Show($"{context}:\n{ex?.Message}", "程序遇到错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
+23
View File
@@ -0,0 +1,23 @@
[SYS]
Language=zh-CN
Name=YZ
Enterprise=YONGZHAO
[SQL_SERVER]
SQL1=192.168.15.248
SQL2=BatchDyeingCentral
SQL3=SQL SERVER
SQL4=sa
SQL5=yf888999
[NETWORK]
TCP=1
HTTP=1
TLS=0
TCP_PORT1=7789
TCP_PORT2=7790
HTTP_PORT=7791
[SERVER]
SERVERIP=www.scserverddns.top:7795
SERVERNAME=SUNLIGHT
SERVERUSER=SUNLIGHT
SERRVERPASWORD=SUNLIGHT
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
+25
View File
@@ -0,0 +1,25 @@
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
+109
View File
@@ -0,0 +1,109 @@
# This map is not a full koi8-r <> utf8 map: it does not contain
# box-drawing and some other characters. Besides this map contains
# several koi8-u and Byelorussian letters which are not in koi8-r.
# If you need a full and standard map, use contrib/unicode2nginx/koi-utf
# map instead.
charset_map koi8-r utf-8 {
80 E282AC ; # euro
95 E280A2 ; # bullet
9A C2A0 ; # &nbsp;
9E C2B7 ; # &middot;
A3 D191 ; # small yo
A4 D194 ; # small Ukrainian ye
A6 D196 ; # small Ukrainian i
A7 D197 ; # small Ukrainian yi
AD D291 ; # small Ukrainian soft g
AE D19E ; # small Byelorussian short u
B0 C2B0 ; # &deg;
B3 D081 ; # capital YO
B4 D084 ; # capital Ukrainian YE
B6 D086 ; # capital Ukrainian I
B7 D087 ; # capital Ukrainian YI
B9 E28496 ; # numero sign
BD D290 ; # capital Ukrainian soft G
BE D18E ; # capital Byelorussian short U
BF C2A9 ; # (C)
C0 D18E ; # small yu
C1 D0B0 ; # small a
C2 D0B1 ; # small b
C3 D186 ; # small ts
C4 D0B4 ; # small d
C5 D0B5 ; # small ye
C6 D184 ; # small f
C7 D0B3 ; # small g
C8 D185 ; # small kh
C9 D0B8 ; # small i
CA D0B9 ; # small j
CB D0BA ; # small k
CC D0BB ; # small l
CD D0BC ; # small m
CE D0BD ; # small n
CF D0BE ; # small o
D0 D0BF ; # small p
D1 D18F ; # small ya
D2 D180 ; # small r
D3 D181 ; # small s
D4 D182 ; # small t
D5 D183 ; # small u
D6 D0B6 ; # small zh
D7 D0B2 ; # small v
D8 D18C ; # small soft sign
D9 D18B ; # small y
DA D0B7 ; # small z
DB D188 ; # small sh
DC D18D ; # small e
DD D189 ; # small shch
DE D187 ; # small ch
DF D18A ; # small hard sign
E0 D0AE ; # capital YU
E1 D090 ; # capital A
E2 D091 ; # capital B
E3 D0A6 ; # capital TS
E4 D094 ; # capital D
E5 D095 ; # capital YE
E6 D0A4 ; # capital F
E7 D093 ; # capital G
E8 D0A5 ; # capital KH
E9 D098 ; # capital I
EA D099 ; # capital J
EB D09A ; # capital K
EC D09B ; # capital L
ED D09C ; # capital M
EE D09D ; # capital N
EF D09E ; # capital O
F0 D09F ; # capital P
F1 D0AF ; # capital YA
F2 D0A0 ; # capital R
F3 D0A1 ; # capital S
F4 D0A2 ; # capital T
F5 D0A3 ; # capital U
F6 D096 ; # capital ZH
F7 D092 ; # capital V
F8 D0AC ; # capital soft sign
F9 D0AB ; # capital Y
FA D097 ; # capital Z
FB D0A8 ; # capital SH
FC D0AD ; # capital E
FD D0A9 ; # capital SHCH
FE D0A7 ; # capital CH
FF D0AA ; # capital hard sign
}
+103
View File
@@ -0,0 +1,103 @@
charset_map koi8-r windows-1251 {
80 88 ; # euro
95 95 ; # bullet
9A A0 ; # &nbsp;
9E B7 ; # &middot;
A3 B8 ; # small yo
A4 BA ; # small Ukrainian ye
A6 B3 ; # small Ukrainian i
A7 BF ; # small Ukrainian yi
AD B4 ; # small Ukrainian soft g
AE A2 ; # small Byelorussian short u
B0 B0 ; # &deg;
B3 A8 ; # capital YO
B4 AA ; # capital Ukrainian YE
B6 B2 ; # capital Ukrainian I
B7 AF ; # capital Ukrainian YI
B9 B9 ; # numero sign
BD A5 ; # capital Ukrainian soft G
BE A1 ; # capital Byelorussian short U
BF A9 ; # (C)
C0 FE ; # small yu
C1 E0 ; # small a
C2 E1 ; # small b
C3 F6 ; # small ts
C4 E4 ; # small d
C5 E5 ; # small ye
C6 F4 ; # small f
C7 E3 ; # small g
C8 F5 ; # small kh
C9 E8 ; # small i
CA E9 ; # small j
CB EA ; # small k
CC EB ; # small l
CD EC ; # small m
CE ED ; # small n
CF EE ; # small o
D0 EF ; # small p
D1 FF ; # small ya
D2 F0 ; # small r
D3 F1 ; # small s
D4 F2 ; # small t
D5 F3 ; # small u
D6 E6 ; # small zh
D7 E2 ; # small v
D8 FC ; # small soft sign
D9 FB ; # small y
DA E7 ; # small z
DB F8 ; # small sh
DC FD ; # small e
DD F9 ; # small shch
DE F7 ; # small ch
DF FA ; # small hard sign
E0 DE ; # capital YU
E1 C0 ; # capital A
E2 C1 ; # capital B
E3 D6 ; # capital TS
E4 C4 ; # capital D
E5 C5 ; # capital YE
E6 D4 ; # capital F
E7 C3 ; # capital G
E8 D5 ; # capital KH
E9 C8 ; # capital I
EA C9 ; # capital J
EB CA ; # capital K
EC CB ; # capital L
ED CC ; # capital M
EE CD ; # capital N
EF CE ; # capital O
F0 CF ; # capital P
F1 DF ; # capital YA
F2 D0 ; # capital R
F3 D1 ; # capital S
F4 D2 ; # capital T
F5 D3 ; # capital U
F6 C6 ; # capital ZH
F7 C2 ; # capital V
F8 DC ; # capital soft sign
F9 DB ; # capital Y
FA C7 ; # capital Z
FB D8 ; # capital SH
FC DD ; # capital E
FD D9 ; # capital SHCH
FE D7 ; # capital CH
FF DA ; # capital hard sign
}
+99
View File
@@ -0,0 +1,99 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
+115
View File
@@ -0,0 +1,115 @@
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
+17
View File
@@ -0,0 +1,17 @@
scgi_param REQUEST_METHOD $request_method;
scgi_param REQUEST_URI $request_uri;
scgi_param QUERY_STRING $query_string;
scgi_param CONTENT_TYPE $content_type;
scgi_param DOCUMENT_URI $document_uri;
scgi_param DOCUMENT_ROOT $document_root;
scgi_param SCGI 1;
scgi_param SERVER_PROTOCOL $server_protocol;
scgi_param REQUEST_SCHEME $scheme;
scgi_param HTTPS $https if_not_empty;
scgi_param REMOTE_ADDR $remote_addr;
scgi_param REMOTE_PORT $remote_port;
scgi_param SERVER_PORT $server_port;
scgi_param SERVER_NAME $server_name;
+17
View File
@@ -0,0 +1,17 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+126
View File
@@ -0,0 +1,126 @@
# This map is not a full windows-1251 <> utf8 map: it does not
# contain Serbian and Macedonian letters. If you need a full map,
# use contrib/unicode2nginx/win-utf map instead.
charset_map windows-1251 utf-8 {
82 E2809A ; # single low-9 quotation mark
84 E2809E ; # double low-9 quotation mark
85 E280A6 ; # ellipsis
86 E280A0 ; # dagger
87 E280A1 ; # double dagger
88 E282AC ; # euro
89 E280B0 ; # per mille
91 E28098 ; # left single quotation mark
92 E28099 ; # right single quotation mark
93 E2809C ; # left double quotation mark
94 E2809D ; # right double quotation mark
95 E280A2 ; # bullet
96 E28093 ; # en dash
97 E28094 ; # em dash
99 E284A2 ; # trade mark sign
A0 C2A0 ; # &nbsp;
A1 D18E ; # capital Byelorussian short U
A2 D19E ; # small Byelorussian short u
A4 C2A4 ; # currency sign
A5 D290 ; # capital Ukrainian soft G
A6 C2A6 ; # borken bar
A7 C2A7 ; # section sign
A8 D081 ; # capital YO
A9 C2A9 ; # (C)
AA D084 ; # capital Ukrainian YE
AB C2AB ; # left-pointing double angle quotation mark
AC C2AC ; # not sign
AD C2AD ; # soft hyphen
AE C2AE ; # (R)
AF D087 ; # capital Ukrainian YI
B0 C2B0 ; # &deg;
B1 C2B1 ; # plus-minus sign
B2 D086 ; # capital Ukrainian I
B3 D196 ; # small Ukrainian i
B4 D291 ; # small Ukrainian soft g
B5 C2B5 ; # micro sign
B6 C2B6 ; # pilcrow sign
B7 C2B7 ; # &middot;
B8 D191 ; # small yo
B9 E28496 ; # numero sign
BA D194 ; # small Ukrainian ye
BB C2BB ; # right-pointing double angle quotation mark
BF D197 ; # small Ukrainian yi
C0 D090 ; # capital A
C1 D091 ; # capital B
C2 D092 ; # capital V
C3 D093 ; # capital G
C4 D094 ; # capital D
C5 D095 ; # capital YE
C6 D096 ; # capital ZH
C7 D097 ; # capital Z
C8 D098 ; # capital I
C9 D099 ; # capital J
CA D09A ; # capital K
CB D09B ; # capital L
CC D09C ; # capital M
CD D09D ; # capital N
CE D09E ; # capital O
CF D09F ; # capital P
D0 D0A0 ; # capital R
D1 D0A1 ; # capital S
D2 D0A2 ; # capital T
D3 D0A3 ; # capital U
D4 D0A4 ; # capital F
D5 D0A5 ; # capital KH
D6 D0A6 ; # capital TS
D7 D0A7 ; # capital CH
D8 D0A8 ; # capital SH
D9 D0A9 ; # capital SHCH
DA D0AA ; # capital hard sign
DB D0AB ; # capital Y
DC D0AC ; # capital soft sign
DD D0AD ; # capital E
DE D0AE ; # capital YU
DF D0AF ; # capital YA
E0 D0B0 ; # small a
E1 D0B1 ; # small b
E2 D0B2 ; # small v
E3 D0B3 ; # small g
E4 D0B4 ; # small d
E5 D0B5 ; # small ye
E6 D0B6 ; # small zh
E7 D0B7 ; # small z
E8 D0B8 ; # small i
E9 D0B9 ; # small j
EA D0BA ; # small k
EB D0BB ; # small l
EC D0BC ; # small m
ED D0BD ; # small n
EE D0BE ; # small o
EF D0BF ; # small p
F0 D180 ; # small r
F1 D181 ; # small s
F2 D182 ; # small t
F3 D183 ; # small u
F4 D184 ; # small f
F5 D185 ; # small kh
F6 D186 ; # small ts
F7 D187 ; # small ch
F8 D188 ; # small sh
F9 D189 ; # small shch
FA D18A ; # small hard sign
FB D18B ; # small y
FC D18C ; # small soft sign
FD D18D ; # small e
FE D18E ; # small yu
FF D18F ; # small ya
}
+21
View File
@@ -0,0 +1,21 @@
geo2nginx.pl by Andrei Nigmatulin
The perl script to convert CSV geoip database ( free download
at http://www.maxmind.com/app/geoip_country ) to format, suitable
for use by the ngx_http_geo_module.
unicode2nginx by Maxim Dounin
The perl script to convert unicode mappings ( available
at http://www.unicode.org/Public/MAPPINGS/ ) to the nginx
configuration file format.
Two generated full maps for windows-1251 and koi8-r.
vim by Evan Miller
Syntax highlighting of nginx configuration for vim, to be
placed into ~/.vim/.
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/perl -w
# (c) Andrei Nigmatulin, 2005
#
# this script provided "as is", without any warranties. use it at your own risk.
#
# special thanx to Andrew Sitnikov for perl port
#
# this script converts CSV geoip database (free download at http://www.maxmind.com/app/geoip_country)
# to format, suitable for use with nginx_http_geo module (http://sysoev.ru/nginx)
#
# for example, line with ip range
#
# "62.16.68.0","62.16.127.255","1041253376","1041268735","RU","Russian Federation"
#
# will be converted to four subnetworks:
#
# 62.16.68.0/22 RU;
# 62.16.72.0/21 RU;
# 62.16.80.0/20 RU;
# 62.16.96.0/19 RU;
use warnings;
use strict;
while( <STDIN> ){
if (/"[^"]+","[^"]+","([^"]+)","([^"]+)","([^"]+)"/){
print_subnets($1, $2, $3);
}
}
sub print_subnets {
my ($a1, $a2, $c) = @_;
my $l;
while ($a1 <= $a2) {
for ($l = 0; ($a1 & (1 << $l)) == 0 && ($a1 + ((1 << ($l + 1)) - 1)) <= $a2; $l++){};
print long2ip($a1) . "/" . (32 - $l) . " " . $c . ";\n";
$a1 += (1 << $l);
}
}
sub long2ip {
my $ip = shift;
my $str = 0;
$str = ($ip & 255);
$ip >>= 8;
$str = ($ip & 255).".$str";
$ip >>= 8;
$str = ($ip & 255).".$str";
$ip >>= 8;
$str = ($ip & 255).".$str";
}
+131
View File
@@ -0,0 +1,131 @@
charset_map koi8-r utf-8 {
80 E29480 ; # BOX DRAWINGS LIGHT HORIZONTAL
81 E29482 ; # BOX DRAWINGS LIGHT VERTICAL
82 E2948C ; # BOX DRAWINGS LIGHT DOWN AND RIGHT
83 E29490 ; # BOX DRAWINGS LIGHT DOWN AND LEFT
84 E29494 ; # BOX DRAWINGS LIGHT UP AND RIGHT
85 E29498 ; # BOX DRAWINGS LIGHT UP AND LEFT
86 E2949C ; # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
87 E294A4 ; # BOX DRAWINGS LIGHT VERTICAL AND LEFT
88 E294AC ; # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
89 E294B4 ; # BOX DRAWINGS LIGHT UP AND HORIZONTAL
8A E294BC ; # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
8B E29680 ; # UPPER HALF BLOCK
8C E29684 ; # LOWER HALF BLOCK
8D E29688 ; # FULL BLOCK
8E E2968C ; # LEFT HALF BLOCK
8F E29690 ; # RIGHT HALF BLOCK
90 E29691 ; # LIGHT SHADE
91 E29692 ; # MEDIUM SHADE
92 E29693 ; # DARK SHADE
93 E28CA0 ; # TOP HALF INTEGRAL
94 E296A0 ; # BLACK SQUARE
95 E28899 ; # BULLET OPERATOR
96 E2889A ; # SQUARE ROOT
97 E28988 ; # ALMOST EQUAL TO
98 E289A4 ; # LESS-THAN OR EQUAL TO
99 E289A5 ; # GREATER-THAN OR EQUAL TO
9A C2A0 ; # NO-BREAK SPACE
9B E28CA1 ; # BOTTOM HALF INTEGRAL
9C C2B0 ; # DEGREE SIGN
9D C2B2 ; # SUPERSCRIPT TWO
9E C2B7 ; # MIDDLE DOT
9F C3B7 ; # DIVISION SIGN
A0 E29590 ; # BOX DRAWINGS DOUBLE HORIZONTAL
A1 E29591 ; # BOX DRAWINGS DOUBLE VERTICAL
A2 E29592 ; # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
A3 D191 ; # CYRILLIC SMALL LETTER IO
A4 E29593 ; # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
A5 E29594 ; # BOX DRAWINGS DOUBLE DOWN AND RIGHT
A6 E29595 ; # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
A7 E29596 ; # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
A8 E29597 ; # BOX DRAWINGS DOUBLE DOWN AND LEFT
A9 E29598 ; # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
AA E29599 ; # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
AB E2959A ; # BOX DRAWINGS DOUBLE UP AND RIGHT
AC E2959B ; # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
AD E2959C ; # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
AE E2959D ; # BOX DRAWINGS DOUBLE UP AND LEFT
AF E2959E ; # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
B0 E2959F ; # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
B1 E295A0 ; # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
B2 E295A1 ; # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
B3 D081 ; # CYRILLIC CAPITAL LETTER IO
B4 E295A2 ; # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
B5 E295A3 ; # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
B6 E295A4 ; # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
B7 E295A5 ; # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
B8 E295A6 ; # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
B9 E295A7 ; # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
BA E295A8 ; # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
BB E295A9 ; # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
BC E295AA ; # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
BD E295AB ; # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
BE E295AC ; # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
BF C2A9 ; # COPYRIGHT SIGN
C0 D18E ; # CYRILLIC SMALL LETTER YU
C1 D0B0 ; # CYRILLIC SMALL LETTER A
C2 D0B1 ; # CYRILLIC SMALL LETTER BE
C3 D186 ; # CYRILLIC SMALL LETTER TSE
C4 D0B4 ; # CYRILLIC SMALL LETTER DE
C5 D0B5 ; # CYRILLIC SMALL LETTER IE
C6 D184 ; # CYRILLIC SMALL LETTER EF
C7 D0B3 ; # CYRILLIC SMALL LETTER GHE
C8 D185 ; # CYRILLIC SMALL LETTER HA
C9 D0B8 ; # CYRILLIC SMALL LETTER I
CA D0B9 ; # CYRILLIC SMALL LETTER SHORT I
CB D0BA ; # CYRILLIC SMALL LETTER KA
CC D0BB ; # CYRILLIC SMALL LETTER EL
CD D0BC ; # CYRILLIC SMALL LETTER EM
CE D0BD ; # CYRILLIC SMALL LETTER EN
CF D0BE ; # CYRILLIC SMALL LETTER O
D0 D0BF ; # CYRILLIC SMALL LETTER PE
D1 D18F ; # CYRILLIC SMALL LETTER YA
D2 D180 ; # CYRILLIC SMALL LETTER ER
D3 D181 ; # CYRILLIC SMALL LETTER ES
D4 D182 ; # CYRILLIC SMALL LETTER TE
D5 D183 ; # CYRILLIC SMALL LETTER U
D6 D0B6 ; # CYRILLIC SMALL LETTER ZHE
D7 D0B2 ; # CYRILLIC SMALL LETTER VE
D8 D18C ; # CYRILLIC SMALL LETTER SOFT SIGN
D9 D18B ; # CYRILLIC SMALL LETTER YERU
DA D0B7 ; # CYRILLIC SMALL LETTER ZE
DB D188 ; # CYRILLIC SMALL LETTER SHA
DC D18D ; # CYRILLIC SMALL LETTER E
DD D189 ; # CYRILLIC SMALL LETTER SHCHA
DE D187 ; # CYRILLIC SMALL LETTER CHE
DF D18A ; # CYRILLIC SMALL LETTER HARD SIGN
E0 D0AE ; # CYRILLIC CAPITAL LETTER YU
E1 D090 ; # CYRILLIC CAPITAL LETTER A
E2 D091 ; # CYRILLIC CAPITAL LETTER BE
E3 D0A6 ; # CYRILLIC CAPITAL LETTER TSE
E4 D094 ; # CYRILLIC CAPITAL LETTER DE
E5 D095 ; # CYRILLIC CAPITAL LETTER IE
E6 D0A4 ; # CYRILLIC CAPITAL LETTER EF
E7 D093 ; # CYRILLIC CAPITAL LETTER GHE
E8 D0A5 ; # CYRILLIC CAPITAL LETTER HA
E9 D098 ; # CYRILLIC CAPITAL LETTER I
EA D099 ; # CYRILLIC CAPITAL LETTER SHORT I
EB D09A ; # CYRILLIC CAPITAL LETTER KA
EC D09B ; # CYRILLIC CAPITAL LETTER EL
ED D09C ; # CYRILLIC CAPITAL LETTER EM
EE D09D ; # CYRILLIC CAPITAL LETTER EN
EF D09E ; # CYRILLIC CAPITAL LETTER O
F0 D09F ; # CYRILLIC CAPITAL LETTER PE
F1 D0AF ; # CYRILLIC CAPITAL LETTER YA
F2 D0A0 ; # CYRILLIC CAPITAL LETTER ER
F3 D0A1 ; # CYRILLIC CAPITAL LETTER ES
F4 D0A2 ; # CYRILLIC CAPITAL LETTER TE
F5 D0A3 ; # CYRILLIC CAPITAL LETTER U
F6 D096 ; # CYRILLIC CAPITAL LETTER ZHE
F7 D092 ; # CYRILLIC CAPITAL LETTER VE
F8 D0AC ; # CYRILLIC CAPITAL LETTER SOFT SIGN
F9 D0AB ; # CYRILLIC CAPITAL LETTER YERU
FA D097 ; # CYRILLIC CAPITAL LETTER ZE
FB D0A8 ; # CYRILLIC CAPITAL LETTER SHA
FC D0AD ; # CYRILLIC CAPITAL LETTER E
FD D0A9 ; # CYRILLIC CAPITAL LETTER SHCHA
FE D0A7 ; # CYRILLIC CAPITAL LETTER CHE
FF D0AA ; # CYRILLIC CAPITAL LETTER HARD SIGN
}
@@ -0,0 +1,48 @@
#!/usr/bin/perl -w
# Convert unicode mappings to nginx configuration file format.
# You may find useful mappings in various places, including
# unicode.org official site:
#
# http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
# http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT
# Needs perl 5.6 or later.
# Written by Maxim Dounin, mdounin@mdounin.ru
###############################################################################
require 5.006;
while (<>) {
# Skip comments and empty lines
next if /^#/;
next if /^\s*$/;
chomp;
# Convert mappings
if (/^\s*0x(..)\s*0x(....)\s*(#.*)/) {
# Mapping <from-code> <unicode-code> "#" <unicode-name>
my $cs_code = $1;
my $un_code = $2;
my $un_name = $3;
# Produce UTF-8 sequence from character code;
my $un_utf8 = join('',
map { sprintf("%02X", $_) }
unpack("U0C*", pack("U", hex($un_code)))
);
print " $cs_code $un_utf8 ; $un_name\n";
} else {
warn "Unrecognized line: '$_'";
}
}
###############################################################################
+130
View File
@@ -0,0 +1,130 @@
charset_map windows-1251 utf-8 {
80 D082 ; #CYRILLIC CAPITAL LETTER DJE
81 D083 ; #CYRILLIC CAPITAL LETTER GJE
82 E2809A ; #SINGLE LOW-9 QUOTATION MARK
83 D193 ; #CYRILLIC SMALL LETTER GJE
84 E2809E ; #DOUBLE LOW-9 QUOTATION MARK
85 E280A6 ; #HORIZONTAL ELLIPSIS
86 E280A0 ; #DAGGER
87 E280A1 ; #DOUBLE DAGGER
88 E282AC ; #EURO SIGN
89 E280B0 ; #PER MILLE SIGN
8A D089 ; #CYRILLIC CAPITAL LETTER LJE
8B E280B9 ; #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
8C D08A ; #CYRILLIC CAPITAL LETTER NJE
8D D08C ; #CYRILLIC CAPITAL LETTER KJE
8E D08B ; #CYRILLIC CAPITAL LETTER TSHE
8F D08F ; #CYRILLIC CAPITAL LETTER DZHE
90 D192 ; #CYRILLIC SMALL LETTER DJE
91 E28098 ; #LEFT SINGLE QUOTATION MARK
92 E28099 ; #RIGHT SINGLE QUOTATION MARK
93 E2809C ; #LEFT DOUBLE QUOTATION MARK
94 E2809D ; #RIGHT DOUBLE QUOTATION MARK
95 E280A2 ; #BULLET
96 E28093 ; #EN DASH
97 E28094 ; #EM DASH
99 E284A2 ; #TRADE MARK SIGN
9A D199 ; #CYRILLIC SMALL LETTER LJE
9B E280BA ; #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
9C D19A ; #CYRILLIC SMALL LETTER NJE
9D D19C ; #CYRILLIC SMALL LETTER KJE
9E D19B ; #CYRILLIC SMALL LETTER TSHE
9F D19F ; #CYRILLIC SMALL LETTER DZHE
A0 C2A0 ; #NO-BREAK SPACE
A1 D08E ; #CYRILLIC CAPITAL LETTER SHORT U
A2 D19E ; #CYRILLIC SMALL LETTER SHORT U
A3 D088 ; #CYRILLIC CAPITAL LETTER JE
A4 C2A4 ; #CURRENCY SIGN
A5 D290 ; #CYRILLIC CAPITAL LETTER GHE WITH UPTURN
A6 C2A6 ; #BROKEN BAR
A7 C2A7 ; #SECTION SIGN
A8 D081 ; #CYRILLIC CAPITAL LETTER IO
A9 C2A9 ; #COPYRIGHT SIGN
AA D084 ; #CYRILLIC CAPITAL LETTER UKRAINIAN IE
AB C2AB ; #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
AC C2AC ; #NOT SIGN
AD C2AD ; #SOFT HYPHEN
AE C2AE ; #REGISTERED SIGN
AF D087 ; #CYRILLIC CAPITAL LETTER YI
B0 C2B0 ; #DEGREE SIGN
B1 C2B1 ; #PLUS-MINUS SIGN
B2 D086 ; #CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
B3 D196 ; #CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
B4 D291 ; #CYRILLIC SMALL LETTER GHE WITH UPTURN
B5 C2B5 ; #MICRO SIGN
B6 C2B6 ; #PILCROW SIGN
B7 C2B7 ; #MIDDLE DOT
B8 D191 ; #CYRILLIC SMALL LETTER IO
B9 E28496 ; #NUMERO SIGN
BA D194 ; #CYRILLIC SMALL LETTER UKRAINIAN IE
BB C2BB ; #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
BC D198 ; #CYRILLIC SMALL LETTER JE
BD D085 ; #CYRILLIC CAPITAL LETTER DZE
BE D195 ; #CYRILLIC SMALL LETTER DZE
BF D197 ; #CYRILLIC SMALL LETTER YI
C0 D090 ; #CYRILLIC CAPITAL LETTER A
C1 D091 ; #CYRILLIC CAPITAL LETTER BE
C2 D092 ; #CYRILLIC CAPITAL LETTER VE
C3 D093 ; #CYRILLIC CAPITAL LETTER GHE
C4 D094 ; #CYRILLIC CAPITAL LETTER DE
C5 D095 ; #CYRILLIC CAPITAL LETTER IE
C6 D096 ; #CYRILLIC CAPITAL LETTER ZHE
C7 D097 ; #CYRILLIC CAPITAL LETTER ZE
C8 D098 ; #CYRILLIC CAPITAL LETTER I
C9 D099 ; #CYRILLIC CAPITAL LETTER SHORT I
CA D09A ; #CYRILLIC CAPITAL LETTER KA
CB D09B ; #CYRILLIC CAPITAL LETTER EL
CC D09C ; #CYRILLIC CAPITAL LETTER EM
CD D09D ; #CYRILLIC CAPITAL LETTER EN
CE D09E ; #CYRILLIC CAPITAL LETTER O
CF D09F ; #CYRILLIC CAPITAL LETTER PE
D0 D0A0 ; #CYRILLIC CAPITAL LETTER ER
D1 D0A1 ; #CYRILLIC CAPITAL LETTER ES
D2 D0A2 ; #CYRILLIC CAPITAL LETTER TE
D3 D0A3 ; #CYRILLIC CAPITAL LETTER U
D4 D0A4 ; #CYRILLIC CAPITAL LETTER EF
D5 D0A5 ; #CYRILLIC CAPITAL LETTER HA
D6 D0A6 ; #CYRILLIC CAPITAL LETTER TSE
D7 D0A7 ; #CYRILLIC CAPITAL LETTER CHE
D8 D0A8 ; #CYRILLIC CAPITAL LETTER SHA
D9 D0A9 ; #CYRILLIC CAPITAL LETTER SHCHA
DA D0AA ; #CYRILLIC CAPITAL LETTER HARD SIGN
DB D0AB ; #CYRILLIC CAPITAL LETTER YERU
DC D0AC ; #CYRILLIC CAPITAL LETTER SOFT SIGN
DD D0AD ; #CYRILLIC CAPITAL LETTER E
DE D0AE ; #CYRILLIC CAPITAL LETTER YU
DF D0AF ; #CYRILLIC CAPITAL LETTER YA
E0 D0B0 ; #CYRILLIC SMALL LETTER A
E1 D0B1 ; #CYRILLIC SMALL LETTER BE
E2 D0B2 ; #CYRILLIC SMALL LETTER VE
E3 D0B3 ; #CYRILLIC SMALL LETTER GHE
E4 D0B4 ; #CYRILLIC SMALL LETTER DE
E5 D0B5 ; #CYRILLIC SMALL LETTER IE
E6 D0B6 ; #CYRILLIC SMALL LETTER ZHE
E7 D0B7 ; #CYRILLIC SMALL LETTER ZE
E8 D0B8 ; #CYRILLIC SMALL LETTER I
E9 D0B9 ; #CYRILLIC SMALL LETTER SHORT I
EA D0BA ; #CYRILLIC SMALL LETTER KA
EB D0BB ; #CYRILLIC SMALL LETTER EL
EC D0BC ; #CYRILLIC SMALL LETTER EM
ED D0BD ; #CYRILLIC SMALL LETTER EN
EE D0BE ; #CYRILLIC SMALL LETTER O
EF D0BF ; #CYRILLIC SMALL LETTER PE
F0 D180 ; #CYRILLIC SMALL LETTER ER
F1 D181 ; #CYRILLIC SMALL LETTER ES
F2 D182 ; #CYRILLIC SMALL LETTER TE
F3 D183 ; #CYRILLIC SMALL LETTER U
F4 D184 ; #CYRILLIC SMALL LETTER EF
F5 D185 ; #CYRILLIC SMALL LETTER HA
F6 D186 ; #CYRILLIC SMALL LETTER TSE
F7 D187 ; #CYRILLIC SMALL LETTER CHE
F8 D188 ; #CYRILLIC SMALL LETTER SHA
F9 D189 ; #CYRILLIC SMALL LETTER SHCHA
FA D18A ; #CYRILLIC SMALL LETTER HARD SIGN
FB D18B ; #CYRILLIC SMALL LETTER YERU
FC D18C ; #CYRILLIC SMALL LETTER SOFT SIGN
FD D18D ; #CYRILLIC SMALL LETTER E
FE D18E ; #CYRILLIC SMALL LETTER YU
FF D18F ; #CYRILLIC SMALL LETTER YA
}
+4
View File
@@ -0,0 +1,4 @@
au BufRead,BufNewFile *.nginx set ft=nginx
au BufRead,BufNewFile */etc/nginx/* set ft=nginx
au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx
au BufRead,BufNewFile nginx.conf set ft=nginx
+1
View File
@@ -0,0 +1 @@
setlocal commentstring=#\ %s
+11
View File
@@ -0,0 +1,11 @@
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal indentexpr=
" cindent actually works for nginx' simple file structure
setlocal cindent
" Just make sure that the comments are not reset as defs would be.
setlocal cinkeys-=0#
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+126
View File
@@ -0,0 +1,126 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances
of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards
of acceptable behavior and will take appropriate and fair corrective action
in response to any behavior that they deem inappropriate, threatening,
offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for
moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
<nginx-oss-community@f5.com>. All complaints will be reviewed and investigated
promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external
channels like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1,
available at
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion).
For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
+128
View File
@@ -0,0 +1,128 @@
# Contributing Guidelines
The following is a set of guidelines for contributing to nginx project.
We really appreciate that you are considering contributing!
## Table of Contents
- [Report a Bug](#report-a-bug)
- [Suggest a Feature or Enhancement](#suggest-a-feature-or-enhancement)
- [Open a Discussion](#open-a-discussion)
- [Submit a Pull Request](#submit-a-pull-request)
- [Issue Lifecycle](#issue-lifecycle)
## Report a Bug
To report a bug, open an issue on GitHub with the label `bug` using the
available [bug report issue form](/.github/ISSUE_TEMPLATE/bug_report.yml).
Please ensure the bug has not already been reported. **If the bug is a
potential security vulnerability, please report it using our
[security policy](/SECURITY.md).**
## Suggest a Feature or Enhancement
To suggest a feature or enhancement, please create an issue on GitHub with the
label `enhancement` using the available
[feature request issue form](/.github/ISSUE_TEMPLATE/feature_request.yml).
Please ensure the feature or enhancement has not already been suggested.
## Open a Discussion
If you want to engage in a conversation with the community and maintainers,
we encourage you to use
[GitHub Discussions](https://github.com/nginx/nginx/discussions) to discuss
the NGINX codebase or the [NGINX Community forum](https://community.nginx.org)
to chat anything else NGINX (including troubleshooting).
## Submit a Pull Request
Follow this plan to contribute a change to NGINX source code:
- Fork the NGINX repository
- Create a branch
- Implement your changes in this branch
- Submit a pull request (PR) when your changes are tested and ready for review
Refer to
[NGINX Development Guide](https://nginx.org/en/docs/dev/development_guide.html)
for questions about NGINX programming.
### Formatting Changes
- Changes should be formatted according to the
[code style](https://nginx.org/en/docs/dev/development_guide.html#code_style)
used by NGINX; sometimes, there is no clear rule, in which case examine how
existing NGINX sources are formatted and mimic this style; changes will more
likely be accepted if style corresponds to the surrounding code
- Keep a clean, concise and meaningful commit history on your branch, rebasing
locally and breaking changes logically into commits before submitting a PR
- Each commit message should have a single-line subject line followed by verbose
description after an empty line
- Limit the subject line to 67 characters, and the rest of the commit message
to 76 characters
- Use subject line prefixes for commits that affect a specific portion of the
code; examples include "Upstream:", "QUIC:", or "Core:"; see the commit history
to get an idea of the prefixes used
- If the commit fixes an open issue then you can use the "Closes:" tag/trailer
to reference it and have GitHub automatically close it once it's been merged.
E.g.:
`Closes: https://github.com/nginx/nginx/issues/9999`
That should go at the end of the commit message, separated by a blank line,
along with any other tags.
### Before Submitting
- The proposed changes should work properly on a wide range of
[supported platforms](https://nginx.org/en/index.html#tested_os_and_platforms)
- Try to make it clear why the suggested change is needed, and provide a use
case, if possible
- Passing your changes through the test suite is a good way to ensure that they
do not cause a regression; the repository with tests can be cloned with the
following command:
```bash
git clone https://github.com/nginx/nginx-tests.git
```
- Submitting a change implies granting project a permission to use it under the
[BSD-2-Clause license](/LICENSE)
### F5 Contributor License Agreement (CLA)
F5 requires all contributors to agree to the terms of the F5 CLA
(available [here](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md))
before any of their changes can be incorporated into an F5 Open Source
repository (even contributions to the F5 CLA itself!).
If you have not yet agreed to the F5 CLA terms and submit a PR to this
repository, a bot will prompt you to view and agree to the F5 CLA.
You will have to agree to the F5 CLA terms through a comment in the PR
before any of your changes can be merged. Your agreement signature
will be safely stored by F5 and no longer be required in future PRs.
## Issue Lifecycle
To ensure a balance between work carried out by the NGINX engineering team
while encouraging community involvement on this project, we use the following
issue lifecycle:
- A new issue is created by a community member
- An owner on the NGINX engineering team is assigned to the issue; this
owner shepherds the issue through the subsequent stages in the issue lifecycle
- The owner assigns one or more
[labels](https://github.com/nginx/nginx/issues/labels) to the issue
- The owner, in collaboration with the wider team (product management and
engineering), determines what milestone to attach to an issue;
generally, milestones correspond to product releases
+24
View File
@@ -0,0 +1,24 @@
Copyright (C) 2002-2021 Igor Sysoev
Copyright (C) 2011-2026 Nginx, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
+177
View File
@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
+104
View File
@@ -0,0 +1,104 @@
PCRE2 Licence
=============
| SPDX-License-Identifier: | BSD-3-Clause WITH PCRE2-exception |
|---------|-------|
PCRE2 is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
licence, as specified below, with one exemption for certain binary
redistributions. The documentation for PCRE2, supplied in the "doc" directory,
is distributed under the same terms as the software itself. The data in the
testdata directory is not copyrighted and is in the public domain.
The basic library functions are written in C and are freestanding. Also
included in the distribution is a just-in-time compiler that can be used to
optimize pattern matching. This is an optional feature that can be omitted when
the library is built. The just-in-time compiler is separately licensed under the
"2-clause BSD" licence.
COPYRIGHT
---------
### The basic library functions
Written by: Philip Hazel
Email local part: Philip.Hazel
Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2007 University of Cambridge
Copyright (c) 2007-2024 Philip Hazel
All rights reserved.
### PCRE2 Just-In-Time compilation support
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright (c) 2010-2024 Zoltan Herczeg
All rights reserved.
### Stack-less Just-In-Time compiler
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright (c) 2009-2024 Zoltan Herczeg
All rights reserved.
The code in the `deps/sljit` directory has its own LICENSE file.
### All other contributions
Many other contributors have participated in the authorship of PCRE2. As PCRE2
has never required a Contributor Licensing Agreement, or other copyright
assignment agreement, all contributions have copyright retained by each
original contributor or their employer.
THE "BSD" LICENCE
-----------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notices,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notices, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
------------------------------------------
The second condition in the BSD licence (covering binary redistributions) does
not apply all the way down a chain of software. If binary package A includes
PCRE2, it must respect the condition, but if package B is software that
includes package A, the condition is not imposed on package B unless it uses
PCRE2 independently.
+232
View File
@@ -0,0 +1,232 @@
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/9335b488-ffcc-4157-8364-2370a0b70ad0">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/3a7eeb08-1133-47f5-859c-fad4f5a6a013">
<img alt="NGINX Banner">
</picture>
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![Community Forum](https://img.shields.io/badge/community-forum-009639?logo=discourse&link=https%3A%2F%2Fcommunity.nginx.org)](https://community.nginx.org)
[![License](https://img.shields.io/badge/License-BSD%202--Clause-blue.svg)](/LICENSE)
[![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](/CODE_OF_CONDUCT.md)
NGINX (pronounced "engine x" or "en-jin-eks") is the world's most popular Web Server, high performance Load Balancer, Reverse Proxy, API Gateway and Content Cache.
NGINX is free and open source software, distributed under the terms of a simplified [2-clause BSD-like license](LICENSE).
Enterprise distributions, commercial support and training are available from [F5, Inc](https://www.f5.com/products/nginx).
> [!IMPORTANT]
> The goal of this README is to provide a basic, structured introduction to NGINX for novice users. Please refer to the [full NGINX documentation](https://nginx.org/en/docs/) for detailed information on [installing](https://nginx.org/en/docs/install.html), [building](https://nginx.org/en/docs/configure.html), [configuring](https://nginx.org/en/docs/dirindex.html), [debugging](https://nginx.org/en/docs/debugging_log.html), and more. These documentation pages also contain a more detailed [Beginners Guide](https://nginx.org/en/docs/beginners_guide.html), How-Tos, [Development guide](https://nginx.org/en/docs/dev/development_guide.html), and a complete module and [directive reference](https://nginx.org/en/docs/dirindex.html).
# Table of contents
- [How it works](#how-it-works)
- [Modules](#modules)
- [Configurations](#configurations)
- [Runtime](#runtime)
- [Downloading and installing](#downloading-and-installing)
- [Stable and Mainline binaries](#stable-and-mainline-binaries)
- [Linux binary installation process](#linux-binary-installation-process)
- [FreeBSD installation process](#freebsd-installation-process)
- [Windows executables](#windows-executables)
- [Dynamic modules](#dynamic-modules)
- [Getting started with NGINX](#getting-started-with-nginx)
- [Installing SSL certificates and enabling TLS encryption](#installing-ssl-certificates-and-enabling-tls-encryption)
- [Load Balancing](#load-balancing)
- [Rate limiting](#rate-limiting)
- [Content caching](#content-caching)
- [Building from source](#building-from-source)
- [Installing dependencies](#installing-dependencies)
- [Cloning the NGINX GitHub repository](#cloning-the-nginx-github-repository)
- [Configuring the build](#configuring-the-build)
- [Compiling](#compiling)
- [Location of binary and installation](#location-of-binary-and-installation)
- [Running and testing the installed binary](#running-and-testing-the-installed-binary)
- [Asking questions and reporting issues](#asking-questions-and-reporting-issues)
- [Contributing code](#contributing-code)
- [Additional help and resources](#additional-help-and-resources)
- [Changelog](#changelog)
- [License](#license)
# How it works
NGINX is installed software with binary packages available for all major operating systems and Linux distributions. See [Tested OS and Platforms](https://nginx.org/en/#tested_os_and_platforms) for a full list of compatible systems.
> [!IMPORTANT]
> While nearly all popular Linux-based operating systems are distributed with a community version of nginx, we highly advise installation and usage of official [packages](https://nginx.org/en/linux_packages.html) or sources from this repository. Doing so ensures that you're using the most recent release or source code, including the latest feature-set, fixes and security patches.
## Modules
NGINX is comprised of individual modules, each extending core functionality by providing additional, configurable features. See "Modules reference" at the bottom of [nginx documentation](https://nginx.org/en/docs/) for a complete list of official modules.
NGINX modules can be built and distributed as static or dynamic modules. Static modules are defined at build-time, compiled, and distributed in the resulting binaries. See [Dynamic Modules](#dynamic-modules) for more information on how they work, as well as, how to obtain, install, and configure them.
> [!TIP]
> You can issue the following command to see which static modules your NGINX binaries were built with:
```bash
nginx -V
```
> See [Configuring the build](#configuring-the-build) for information on how to include specific Static modules into your nginx build.
## Configurations
NGINX is highly flexible and configurable. Provisioning the software is achieved via text-based config file(s) accepting parameters called "[Directives](https://nginx.org/en/docs/dirindex.html)". See [Configuration File's Structure](https://nginx.org/en/docs/beginners_guide.html#conf_structure) for a comprehensive description of how NGINX configuration files work.
> [!NOTE]
> The set of directives available to your distribution of NGINX is dependent on which [modules](#modules) have been made available to it.
## Runtime
Rather than running in a single, monolithic process, NGINX is architected to scale beyond Operating System process limitations by operating as a collection of processes. They include:
- A "master" process that maintains worker processes, as well as, reads and evaluates configuration files.
- One or more "worker" processes that process data (eg. HTTP requests).
The number of [worker processes](https://nginx.org/en/docs/ngx_core_module.html#worker_processes) is defined in the configuration file and may be fixed for a given configuration or automatically adjusted to the number of available CPU cores. In most cases, the latter option optimally balances load across available system resources, as NGINX is designed to efficiently distribute work across all worker processes.
> [!TIP]
> Processes synchronize data through shared memory. For this reason, many NGINX directives require the allocation of shared memory zones. As an example, when configuring [rate limiting](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req), connecting clients may need to be tracked in a [common memory zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone) so all worker processes can know how many times a particular client has accessed the server in a span of time.
# Downloading and installing
Follow these steps to download and install precompiled NGINX binaries. You may also choose to [build NGINX locally from source code](#building-from-source).
## Stable and Mainline binaries
NGINX binaries are built and distributed in two versions: stable and mainline. Stable binaries are built from stable branches and only contain critical fixes backported from the mainline version. Mainline binaries are built from the [master branch](https://github.com/nginx/nginx/tree/master) and contain the latest features and bugfixes. You'll need to [decide which is appropriate for your purposes](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#choosing-between-a-stable-or-a-mainline-version).
## Linux binary installation process
The NGINX binary installation process takes advantage of package managers native to specific Linux distributions. For this reason, first-time installations involve adding the official NGINX package repository to your system's package manager. Follow [these steps](https://nginx.org/en/linux_packages.html) to download, verify, and install NGINX binaries using the package manager appropriate for your Linux distribution.
### Upgrades
Future upgrades to the latest version can be managed using the same package manager without the need to manually download and verify binaries.
## FreeBSD installation process
For more information on installing NGINX on FreeBSD system, visit https://nginx.org/en/docs/install.html
## Windows executables
Windows executables for mainline and stable releases can be found on the main [NGINX download page](https://nginx.org/en/download.html). Note that the current implementation of NGINX for Windows is at the Proof-of-Concept stage and should only be used for development and testing purposes. For additional information, please see [nginx for Windows](https://nginx.org/en/docs/windows.html).
## Dynamic modules
NGINX version 1.9.11 added support for [Dynamic Modules](https://nginx.org/en/docs/ngx_core_module.html#load_module). Unlike Static modules, dynamically built modules can be downloaded, installed, and configured after the core NGINX binaries have been built. [Official dynamic module binaries](https://nginx.org/en/linux_packages.html#dynmodules) are available from the same package repository as the core NGINX binaries described in previous steps.
> [!TIP]
> [NGINX JavaScript (njs)](https://github.com/nginx/njs), is a popular NGINX dynamic module that enables the extension of core NGINX functionality using familiar JavaScript syntax.
> [!IMPORTANT]
> If desired, dynamic modules can also be built statically into NGINX at compile time.
# Getting started with NGINX
For a gentle introduction to NGINX basics, please see our [Beginner’s Guide](https://nginx.org/en/docs/beginners_guide.html).
## Installing SSL certificates and enabling TLS encryption
See [Configuring HTTPS servers](https://nginx.org/en/docs/http/configuring_https_servers.html) for a quick guide on how to enable secure traffic to your NGINX installation.
## Load Balancing
For a quick start guide on configuring NGINX as a Load Balancer, please see [Using nginx as HTTP load balancer](https://nginx.org/en/docs/http/load_balancing.html).
## Rate limiting
See our [Rate Limiting with NGINX](https://blog.nginx.org/blog/rate-limiting-nginx) blog post for an overview of core concepts for provisioning NGINX as an API Gateway.
## Content caching
See [A Guide to Caching with NGINX and NGINX Plus](https://blog.nginx.org/blog/nginx-caching-guide) blog post for an overview of how to use NGINX as a content cache (e.g. edge server of a content delivery network).
# Building from source
The following steps can be used to build NGINX from source code available in this repository.
## Installing dependencies
Most Linux distributions will require several dependencies to be installed in order to build NGINX. The following instructions are specific to the `apt` package manager, widely available on most Ubuntu/Debian distributions and their derivatives.
> [!TIP]
> It is always a good idea to update your package repository lists prior to installing new packages.
> ```bash
> sudo apt update
> ```
### Installing compiler and make utility
Use the following command to install the GNU C compiler and Make utility.
```bash
sudo apt install gcc make
```
### Installing dependency libraries
```bash
sudo apt install libpcre3-dev zlib1g-dev
```
> [!WARNING]
> This is the minimal set of dependency libraries needed to build NGINX with rewriting and gzip capabilities. Other dependencies may be required if you choose to build NGINX with additional modules. Monitor the output of the `configure` command discussed in the following sections for information on which modules may be missing. For example, if you plan to use SSL certificates to encrypt traffic with TLS, you'll need to install the OpenSSL library. To do so, issue the following command.
>```bash
>sudo apt install libssl-dev
## Cloning the NGINX GitHub repository
Using your preferred method, clone the NGINX repository into your development directory. See [Cloning a GitHub Repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) for additional help.
```bash
git clone https://github.com/nginx/nginx.git
```
## Configuring the build
Prior to building NGINX, you must run the `configure` script with [appropriate flags](https://nginx.org/en/docs/configure.html). This will generate a Makefile in your NGINX source root directory that can then be used to compile NGINX with [options specified during configuration](https://nginx.org/en/docs/configure.html).
From the NGINX source code repository's root directory:
```bash
auto/configure
```
> [!IMPORTANT]
> Configuring the build without any flags will compile NGINX with the default set of options. Please refer to https://nginx.org/en/docs/configure.html for a full list of available build configuration options.
## Compiling
The `configure` script will generate a `Makefile` in the NGINX source root directory upon successful execution. To compile NGINX into a binary, issue the following command from that same directory:
```bash
make
```
## Location of binary and installation
After successful compilation, a binary will be generated at `<NGINX_SRC_ROOT_DIR>/objs/nginx`. To install this binary, issue the following command from the source root directory:
```bash
sudo make install
```
> [!IMPORTANT]
> The binary will be installed into the `/usr/local/nginx/` directory.
## Running and testing the installed binary
To run the installed binary, issue the following command:
```bash
sudo /usr/local/nginx/sbin/nginx
```
You may test NGINX operation using `curl`.
```bash
curl localhost
```
The output of which should start with:
```html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
```
# Asking questions and reporting issues
See our [Support](SUPPORT.md) guidelines for information on how discuss the codebase, ask troubleshooting questions, and report issues.
# Contributing code
Please see the [Contributing](CONTRIBUTING.md) guide for information on how to contribute code.
# Additional help and resources
- See the [NGINX Community Blog](https://blog.nginx.org/) for more tips, tricks and HOW-TOs related to NGINX and related projects.
- Access [nginx.org](https://nginx.org/), your go-to source for all documentation, information and software related to the NGINX suite of projects.
# Changelog
See our [changelog](https://nginx.org/en/CHANGES) to keep track of updates.
# License
[2-clause BSD-like license](LICENSE)
---
Additional documentation available at: https://nginx.org/en/docs
+103
View File
@@ -0,0 +1,103 @@
# Security Policy
This document provides an overview of security concerns related to nginx
deployments, focusing on confidentiality, integrity, availability, and the
implications of configurations and misconfigurations.
## Reporting a Vulnerability
Please report any vulnerabilities via one of the following methods
(in order of preference):
1. [Report a vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability)
within this repository. We are using the GitHub workflow that allows us to
manage vulnerabilities in a private manner and interact with reporters
securely.
2. [Report directly to F5](https://www.f5.com/services/support/report-a-vulnerability).
3. Report via email to security-alert@nginx.org.
This method will be deprecated in the future.
### Vulnerability Disclosure and Fix Process
The nginx team expects that all suspected vulnerabilities be reported
privately via the
[Reporting a Vulnerability](SECURITY.md#reporting-a-vulnerability) guidelines.
If a publicly released vulnerability is reported, we
may request to handle it according to the private disclosure process.
If the reporter agrees, we will follow the private disclosure process.
Security fixes will be applied to all supported stable releases, as well
as the mainline version, as applicable. We recommend using the most recent
mainline or stable release of nginx. Fixes are created and tested by the core
team using a GitHub private fork for security. If necessary, the reporter
may be invited to contribute to the fork and assist with the solution.
The nginx team is committed to responsible information disclosure with
sufficient detail, such as the CVSS score and vector. Privately disclosed
vulnerabilities are embargoed by default until the fix is released.
Communications and fixes remain private until made public. As nginx is
supported by F5, we generally follow the
[F5 security vulnerability response policy](https://my.f5.com/manage/s/article/K4602).
### Vulnerability Disclosure and Fix Service Level Objectives
- We will acknowledge all vulnerability reports within 1 to 3 days.
- Fixes will be developed and released within 90 days from the date of
disclosure. If an extension is needed, we will work with the disclosing person.
- Publicly disclosed (i.e., Zero-Day vulnerabilities) will be addressed ASAP.
## Confidentiality, Integrity, and Availability
### Confidentiality and Integrity
Vulnerabilities compromising data confidentiality or integrity are considered
the highest priority. Any issue leading to unauthorized data access, leaks, or
manipulation will trigger the security release process.
### Availability
Availability issues must meet the following criteria to trigger the security
release process:
- Is present in a standard module included with nginx.
- Arises from traffic that the module is designed to handle.
- Resource exhaustion issues are not mitigated by existing timeout, rate
limiting, or buffer size configurations, or applying changes is impractical.
- Results in highly asymmetric, extreme resource consumption.
Availability issues excluded from the security release process:
- Local file content or upstream response content resulting only in worker
process termination.
- Issues with experimental features which result only in availability impact.
## Trusted Configurations and Misconfigurations
In nginx, configuration files, modules, certificate/key pairs, nginx JavaScript,
and local file content are considered trusted sources. Issues arising from
loading or execution of these trusted components are not considered
vulnerabilities. Operators are responsible for securing and maintaining the
integrity of these sources. Misconfigurations can create vulnerabilities, and
operators should implement configurations according to best practices, review
them regularly, and apply security updates.
## Data Plane vs. Control Plane
The data plane handles traffic through nginx, directly interacting with user
data. nginx inherently trusts the content and instructions from upstream
servers. The control plane governs configuration, management, and orchestration.
Misconfigurations or vulnerabilities in the control plane can cause improper
behavior in the data plane.
## Modules Under Scope
The policy applies to all nginx modules included in this repository. Security
considerations and attack vectors for each module will be identified, with
recommended configurations to mitigate risks.
## Debug Logging and Core Files
Debug logs and core files produced by nginx may contain un-sanitized data,
including sensitive information like client requests, server configurations,
and private key material. These artifacts must be handled carefully to avoid
exposing confidential data.
+48
View File
@@ -0,0 +1,48 @@
# Support
## Ask a Question
We use GitHub issues for tracking bugs and feature requests
related to this project.
If you don't know how something in the codebase works, are curious if NGINX
is capable of achieving your desired functionality or want to discuss the
implementation of an existing or in development feature, please start a
GitHub discussion!
## NGINX Specific Questions and/or Issues
This project isn't the right place to get support for NGINX and/or NGINX
troubleshooting questions, but the following resources are available below.
Thanks for your understanding!
### Community Forum
We have a [community forum](https://community.nginx.org/)!
If you have any NGINX specific questions and/or issues,
try checking out the [`NGINX category`](https://community.nginx.org/c/projects/nginx/23).
For general discussions around anything tangentially NGINX related,
check out the [`General Discussion category`](https://community.nginx.org/c/general-discussion/34).
Both fellow community members and NGINXers might be able to help you! :)
### Documentation
For a comprehensive list of all NGINX directives, check out <https://nginx.org>.
For a comprehensive list of administration and deployment guides for all
NGINX products, check out <https://docs.nginx.com>.
## Contributing
Please see the [contributing guide](/CONTRIBUTING.md) for guidelines
on how to best contribute to this project.
## Commercial Support
Commercial support for this project is available.
Please get in touch with [F5 sales](https://www.f5.com/products/get-f5/)
or check your contract details for more information!
## Community Support
Community support is offered on a best effort basis through any of our active communities.
+20
View File
@@ -0,0 +1,20 @@
(C) 1995-2026 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>An error occurred.</h1>
<p>Sorry, the page you are looking for is currently unavailable.<br/>
Please try again later.</p>
<p>If you are the system administrator of this resource then you should check
the error log for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>
+27
View File
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
Further configuration is required for the web server, reverse proxy,
API gateway, load balancer, content cache, or other features.</p>
<p>For online documentation and support please refer to
<a href="https://nginx.org/">nginx.org</a>.<br/>
To engage with the community please visit
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/>
For enterprise grade support, professional services, additional
security features and capabilities please refer to
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Binary file not shown.
Binary file not shown.
+5 -1
View File
@@ -24,7 +24,7 @@ namespace SunlightAggregationManager
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
GlobalLogManager.RegisterTarget(LOG);
GlobalLogManager.RegisterTarget(LOG,LogGing.LogGingDATA);
DataContext = new MainWindowViewModel();
}
@@ -68,6 +68,7 @@ namespace SunlightAggregationManager
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.ServicePage();
}
private void ListViewItem_MouseLeftButtonUp_log(object sender, MouseButtonEventArgs e)
{
@@ -79,11 +80,13 @@ namespace SunlightAggregationManager
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.MachinePage();
}
private void ListViewItem_MouseLeftButtonUp_extend(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.ExtendPage();
}
private void ListViewItem_MouseLeftButtonUp_user(object sender, MouseButtonEventArgs e)
{
@@ -95,6 +98,7 @@ namespace SunlightAggregationManager
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.ActionPage();
}
private void ListViewItem_MouseLeftButtonUp_set(object sender, MouseButtonEventArgs e)
+7 -1
View File
@@ -13,8 +13,10 @@
<PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.5" />
<PackageReference Include="Net.Codecrete.QrCodeGenerator" Version="2.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="System.Data.SqlClient" Version="4.9.1" />
<PackageReference Include="TouchSocket" Version="4.2.3" />
<PackageReference Include="TouchSocket" Version="4.2.10" />
<PackageReference Include="TouchSocket.Http" Version="4.2.10" />
<PackageReference Include="vocaluxe.dependencies.netfwtypelib" Version="1.0.1" />
</ItemGroup>
@@ -36,4 +38,8 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="EX\" />
</ItemGroup>
</Project>
+79
View File
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.Intrinsics.X86;
using System.Security.Cryptography;
using System.Text;
namespace SunlightAggregationManager.UserClass
{
public class AES
{
public static string AesEncipher(string Key, string dat) //加密
{
//压缩
byte[] plainBytes = Compress( Encoding.UTF8.GetBytes(dat));
using var sha256 = System.Security.Cryptography.SHA256.Create();
using var aes = System.Security.Cryptography.Aes.Create();
aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(Key));
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV(); // 生成随机 IV
using var enc = aes.CreateEncryptor();
byte[] cipherBytes = enc.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
//将 IV (16字节) 和 密文 拼接成一个完整的字节数组
byte[] combinedBytes = new byte[aes.IV.Length + cipherBytes.Length];
Buffer.BlockCopy(aes.IV, 0, combinedBytes, 0, aes.IV.Length);
Buffer.BlockCopy(cipherBytes, 0, combinedBytes, aes.IV.Length, cipherBytes.Length);
return Convert.ToBase64String(combinedBytes);
}
public static string AesDecrypt(string Key, string dat)//解密
{
// 解码Base64
byte[] cipherBytes = Convert.FromBase64String(dat);
using var sha256 = System.Security.Cryptography.SHA256.Create();
using var aes = System.Security.Cryptography.Aes.Create();
aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(Key));
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// 从字节数组中提取前 16 字节作为 IV
aes.IV = cipherBytes.AsSpan(0, 16).ToArray();
using var dec = aes.CreateDecryptor();
// 解密
byte[] bytes = dec.TransformFinalBlock(cipherBytes, 16, cipherBytes.Length - 16);
//解压缩并返回
return Encoding.UTF8.GetString(Decompress(bytes));
}
// 3. Brotli 压缩辅助方法
private static byte[] Compress(byte[] data)
{
using var output = new MemoryStream();
using (var brotli = new BrotliStream(output, CompressionLevel.Optimal))
{
brotli.Write(data, 0, data.Length);
}
return output.ToArray();
}
// 4. Brotli 解压辅助方法
private static byte[] Decompress(byte[] data)
{
using var input = new MemoryStream(data);
using var brotli = new BrotliStream(input, CompressionMode.Decompress);
using var output = new MemoryStream();
brotli.CopyTo(output);
return output.ToArray();
}
}
}
+343
View File
@@ -0,0 +1,343 @@
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using TouchSocket.Core;
using TouchSocket.Http;
using TouchSocket.Http.WebSockets;
using TouchSocket.Sockets;
using static SunlightAggregationManager.UserClass.AsyncTcpServer;
namespace SunlightAggregationManager.UserClass
{
public class AsyncHttpServer
{
public static HttpService httpservice = new HttpService();
public static async void Configuration(int P1)
{
await HttpMain(P1);
}
public static async Task HttpMain(int port1)
{
NetFwManger.AllowPort(port1, "TCP");//开放端口
await httpservice.SetupAsync(new TouchSocketConfig()//加载配置
.SetListenIPHosts(port1)
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
a.Add<MyHttpPlug1>();
//default插件应该最后添加,其作用是
//1、为找不到的路由返回404
//2、处理 header 为Option的探视跨域请求。
a.UseDefaultHttpServicePlugin();
}));
await httpservice.StartAsync();
Console.WriteLine("HTTP Port:" + port1.ToString());
}
public class MyHttpPlug1 : PluginBase, IHttpPlugin
{
public async Task OnHttpRequest(IHttpSessionClient client, HttpContextEventArgs e)
{
#region HttpContext生命周期
//var request = e.Context.Request;//http请求体
var response = e.Context.Response;//http响应体
#endregion
var bodyString = await e.Context.Request.GetBodyAsync();
try
{
Person? deserializedPerson = JsonSerializer.Deserialize<Person>(bodyString);
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" +
deserializedPerson?.User + "' and Password ='" + deserializedPerson?.Password + "'");
if (_user != null)
{
string _dat = _user?.ToString() ?? "0";
if (_dat != "99")
{
//行为
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("LinkID", client.Id);
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", deserializedPerson?.Dat ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + deserializedPerson?.User + "'", myDict);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]Note[" + (deserializedPerson?.Dat ?? "unknown") + "]");
deserializedPerson!.Dat = await Command(deserializedPerson!);
var jsdat = JsonSerializer.Serialize(deserializedPerson);
e.Context.Response.Headers.Add("SUNLIGHT", "SUNLIGHT");
e.Context.Response.SetStatus(200, "success");
e.Context.Response.SetContent(jsdat);
await e.Context.Response.AnswerAsync();
}
else
{//停用账号关闭连接
//client.SendAsync("Account Deactivated");
e.Context.Response.Headers.Add("SUNLIGHT", "SUNLIGHT");
e.Context.Response.SetStatus(200, "success");
e.Context.Response.SetContent("Account Deactivated");
await e.Context.Response.AnswerAsync();
}
}
else
{ //无效账号关闭连接
//client.SendAsync("Invalid Account");
e.Context.Response.Headers.Add("SUNLIGHT", "SUNLIGHT");
e.Context.Response.SetStatus(200, "success");
e.Context.Response.SetContent("Invalid Account");
await e.Context.Response.AnswerAsync();
}
}
catch (Exception ex)
{//错误
LogGing.ERRDATA(ex);
Console.WriteLine("Http:" + ex.ToString());
//client.SendAsync("Target instruction parsing error manager will close connection");
}
/* if (request.IsGet() && request.UrlEquals("/success"))
{
//直接响应文字
await response
.SetStatus(200, "success")
.FromText("Success")
.AnswerAsync();//直接回应
Console.WriteLine("处理/success");
return;
}
//无法处理,调用下一个插件
await e.InvokeNext();*/
}
}
public static async Task<string> Command(Person deserializedPerson)//
{
string Command = "", ret = "";
Dictionary<string, object> data_ = new Dictionary<string, object>();
var deserialized = JsonSerializer.Deserialize<Dictionary<string, object>>(deserializedPerson.Dat)!;
if (deserialized.TryGetValue("Command", out var val) && val != null) Command = val.ToString()!;
if (Command == "Log")//回复请求的信息
{
DataRow? _user = MainWindowViewModel.Selet_Row(MainWindowViewModel._userData, "User='" +
deserializedPerson?.User + "' and Password ='" + deserializedPerson?.Password + "'");
data_.Add("Enterprise",MainWindowViewModel.Enterprise);
data_.Add("Department", _user?.Field<object>("Department") ?? "");
data_.Add("Groups", _user?.Field<object>("Groups") ?? "");
data_.Add("UserId", _user?.Field<object>("UserID") ?? "");
data_.Add("UserName", _user?.Field<object>("Name") ?? "");
ret = JsonSerializer.Serialize(data_);
}
if (Command == "SysData")//回复请求的信息
{
ret = JsonSerializer.Serialize(data_);
}
if (Command == "ChemicalStatistics")//回复请求的信息
{
data_.Add("ChemicalStatistics", Newtonsoft.Json.JsonConvert.SerializeObject(MainWindowViewModel.ChemicalStatistics));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Info")//回复info请求的信息
{
var t = ToList(MainWindowViewModel._machines).ToJsonString();
//格式化返回信息
data_.Add("Info", t);
data_.Add("DyeMeasurementNumber", MainWindowViewModel.DyeMeasurementNumber.ToString());
data_.Add("ChemicalNumber", MainWindowViewModel.ChemicalNumber.ToString());
data_.Add("PowderNumber", MainWindowViewModel.PowderNumber.ToString());
data_.Add("DyeDissolveNumber", MainWindowViewModel.DyeDissolveNumber.ToString());
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Query")//回复Query请求的信息
{
string s_ = deserialized.GetValue("StartTime").ToString()!;
string e_ = deserialized.GetValue("EndTime").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE CreationTime>'" + s_ + "'and CreationTime<'" + e_ + "'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "QueryDyelot")//回复QueryDyelot请求的信息
{
string d_ = deserialized.GetValue("DyelotName").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE Dyelot LIKE '" + d_ + "%'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "QueryDetail")//回复QueryDetail请求的信息
{
string d_ = deserialized.GetValue("Dyelot").ToString()!;
string r_ = deserialized.GetValue("ReDye").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyelotsBulkedRecipe] " + "WHERE Dyelot='" + d_ + "'and ReDye='" + r_ + "'");
//格式化返回信息
data_.Add("QueryDetail", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Notification")//回复Notification请求的信息
{
string s_ = deserialized.GetValue("StartTime").ToString()!;
string e_ = deserialized.GetValue("EndTime").ToString()!;
var groups = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData,
"Groups", "User='" + deserializedPerson?.User + "'");
DataTable resultTable = MainWindowViewModel.SQLiteHelpers.ExecuteDataSet("" +
"select * from Notification WHERE Groups='" + groups + "' and Id>'" +
s_ + "'", null)?.Tables[0] ?? new DataTable();
if (resultTable.Rows.Count == 0) resultTable.Rows.Add();
//格式化返回信息
data_.Add("Notification", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachine")//回复InfoMachine请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "10")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitDispenseDyestuff] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "10");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "12")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[ShelfInfo] ");
data_.Add("Type", "12");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "20")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitChemical] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "20");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachine", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachineHistory")//回复InfoMachineHistory请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "80")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3) +
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "80");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "82")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[inOutRecords] WHERE Createtime >'" + DateTime.Now.AddDays(-3) + "'");
data_.Add("Type", "82");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "90")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3) +
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "90");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachineHistory", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachinePipes")//回复Notification请求的信息
{
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Pipes] WHERE Dispenser='" + m_ + "'");
data_.Add("InfoMachinePipes", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "SETUSER")//回复Notification请求的信息
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData,
"User='" + deserialized.GetValue("USER").ToString()! + "'",
deserialized.GetValue("VALUE").ToString(), deserialized.GetValue("KEY").ToString()!);
data_.Add("USER", deserialized.GetValue("USER").ToString()!);
data_.Add("VALUE", deserialized.GetValue("VALUE").ToString()!);
data_.Add("KEY", deserialized.GetValue("KEY").ToString()!);
data_.Add("SETUSER", "OK");
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
return ret;
}
public static List<Dictionary<string, object?>>? ToList(DataTable table)//datatable转list
{
if (table == null) return null;
// 使用 AsEnumerable() 将 DataTable 转换为 IEnumerable<DataRow>
// 然后投影为 Dictionary
return table.AsEnumerable().Select(row =>
table.Columns.Cast<DataColumn>().ToDictionary(
col => col.ColumnName,
col => {
var value = row[col];
// 核心修改:如果是数据库空值 DBNull.Value,则转为 C# 的 null,否则保持原值
return value == DBNull.Value ? null : value;
}
)
).ToList();
}
}
}
+457
View File
@@ -0,0 +1,457 @@
using SunlightAggregationManager.UserWindow;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using TouchSocket.Core;
using TouchSocket.Sockets;
using static SunlightAggregationManager.UserClass.AsyncTcpServer;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SunlightAggregationManager.UserClass
{
public class AsyncTcpClient
{
public static TouchSocket.Sockets.TcpClient tcpClient = new TouchSocket.Sockets.TcpClient();
public static async void Configuration(string ip, string Name, string user, string Password)
{
await TcpClient(tcpClient, "tcp://"+ip);
}
public static async void TcpTransmit(object Dat)
{
//发送字符串数据
try
{
await tcpClient.SendAsync(JsonSerializer.Serialize(Dat));
}
catch (Exception ex)
{
Console.WriteLine("Tcp:" + ex.ToString());
}
}
public static async Task TcpClient(TouchSocket.Sockets.TcpClient tcpClient, string ip)
{
// 自定义心跳首次延迟60秒开始,之后每30秒执行一次
Timer timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(30));
tcpClient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
tcpClient.Connected = (client, e) =>
{
//设定显示状态
System.Data.DataRow targetRow =ViewModel.MainWindowViewModel._service.Select("Service = 'Sunlight_Server_Link'").FirstOrDefault()!;
if (targetRow != null)
{
targetRow.BeginEdit();
targetRow["Status"] = "Connected";
targetRow.EndEdit();
}
//发送本机信息到转发服务器
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("SERVEREnterprise", MainWindowViewModel.Enterprise);
myDict.Add("SERVERMachineName", MainWindowViewModel.MachineName);
myDict.Add("SERVERNAME", MainWindowViewModel.SERVERNAME);
myDict.Add("SERVERUSER", MainWindowViewModel.SERVERUSER);
myDict.Add("SERRVERPASWORD", MainWindowViewModel.SERRVERPASWORD);
myDict.Add("MachineVer", MainWindowViewModel.MachineVer);
TcpTransmit(myDict);
Console.WriteLine("Sunlight_Server_Connected");
return EasyTask.CompletedTask;
};//成功连接到服务器
tcpClient.Closing = (client, e) => {
System.Data.DataRow targetRow = ViewModel.MainWindowViewModel._service.Select("Service = 'Sunlight_Server_Link'").FirstOrDefault()!;
if (targetRow != null)
{
targetRow.BeginEdit();
targetRow["Status"] = "Disconnect";
targetRow.EndEdit();
}
Console.WriteLine("Sunlight_Server_Disconnect");
return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
tcpClient.Closed = (client, e) => {
System.Data.DataRow targetRow = ViewModel.MainWindowViewModel._service.Select("Service = 'Sunlight_Server_Link'").FirstOrDefault()!;
if (targetRow != null)
{
targetRow.BeginEdit();
targetRow["Status"] = "Disconnect";
targetRow.EndEdit();
}
Console.WriteLine("Sunlight_Server_Disconnect");
return EasyTask.CompletedTask; };//从服务器断开连接,当连接不成功时不会触发。
#region Tcp客户端使用Received异步委托接收数据
tcpClient.Received = (client, e) =>
{
//从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
var mes = e.Memory.Span.ToString(Encoding.UTF8);
//信息处理暂停心跳定时
timer.Change(Timeout.Infinite, Timeout.Infinite);
try
{
Person? deserializedPerson = JsonSerializer.Deserialize<Person>(mes);
string password= AES.AesDecrypt(deserializedPerson?.Terminal!, deserializedPerson?.Password!);
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" +
deserializedPerson?.User + "' and Password ='" + password + "'");
if (_user != null)
{
string _dat = _user?.ToString() ?? "0";
if (_dat != "99")
{
//行为
Dictionary<string, object> myDict = new Dictionary<string, object>();
//myDict.Add("LinkID", client.Id);
//AES解密
string dataAES = AES.AesDecrypt(deserializedPerson!.Terminal, deserializedPerson.Dat);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]COMMAND[" +
Regex.Replace(dataAES, @"\\u[0-9A-Fa-f]{4}", match =>
{ return Regex.Unescape(match.Value); }) + "]");
//记录
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", dataAES ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" +
deserializedPerson?.User + "'", myDict);
CommandC(dataAES ?? "NOT", deserializedPerson!);
}
else
{//停用账号关闭连接
client.SendAsync("Account Deactivated");
}
}
else if (password== MainWindowViewModel.SERRVERPASWORD && deserializedPerson?.User== MainWindowViewModel.SERVERUSER)
{
//行为
Dictionary<string, object> myDict = new Dictionary<string, object>();
//myDict.Add("LinkID", client.Id);
//AES解密
string dataAES = AES.AesDecrypt(deserializedPerson!.Terminal, deserializedPerson.Dat);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]COMMAND[" +
Regex.Replace(dataAES, @"\\u[0-9A-Fa-f]{4}", match =>
{ return Regex.Unescape(match.Value); }) + "]");
//记录
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", dataAES ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" +
deserializedPerson?.User + "'", myDict);
CommandC(dataAES ?? "NOT", deserializedPerson!);
}
else
{ //无效账号关闭连接
client.SendAsync("Invalid Account");
}
}
catch (Exception ex)
{//错误
Console.WriteLine("Tcp:" + ex.ToString());
client.SendAsync("Target instruction parsing error manager will close connection");
}
finally
{//继续心跳定时
timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
}
return EasyTask.CompletedTask;
};
#endregion
// while (true)
{
try
{
await tcpClient.SetupAsync(new TouchSocketConfig()
.SetSingleStreamDataHandlingAdapter(() => new PeriodPackageAdapter())//以超时周期和包
.SetRemoteIPHost(ip)
.ConfigurePlugins(a =>
{
a.UseReconnection<TouchSocket.Sockets.TcpClient>(options =>
{
options.PollingInterval = TimeSpan.FromSeconds(5);
});
})
.ConfigureContainer(a =>
{
}));
await tcpClient.ConnectAsync();//调用连接,当连接不成功时,会抛出异常。
// break;
}
catch (Exception ex)
{
// tcpClient.Dispose();//清
LogGing.ERRDATA(ex);
Console.WriteLine("Tcp:" + ex.ToString());
// await Task.Delay(TimeSpan.FromMinutes(1));
// Console.WriteLine("Tcp:重试连接...");
}
}
}
private static void TimerCallback(object? state)
{
try
{
if (tcpClient.Online)
{
tcpClient.SendAsync("SUNLIGHT");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
LogGing.ERRDATA(ex);
}
}
public static async void CommandC(string dat, Person person)//
{
try
{
string Command = "", ret = "";
Dictionary<string, object> data_ = new Dictionary<string, object>();
var deserialized = JsonSerializer.Deserialize<Dictionary<string, object>>(dat)!;
if (deserialized.TryGetValue("Command", out var val) && val != null) Command = val.ToString()!;
if (Command == "SysCom")//回复指令的信息
{
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "Log")//回复请求的信息
{
DataRow? _user = MainWindowViewModel.Selet_Row(MainWindowViewModel._userData, "User='" +
person?.User + "'");
data_.Add("Enterprise", MainWindowViewModel.Enterprise);
data_.Add("Department", _user?.Field<object>("Department") ?? "");
data_.Add("Groups", _user?.Field<object>("Groups") ?? "");
data_.Add("UserId", _user?.Field<object>("UserID") ?? "");
data_.Add("UserName", _user?.Field<object>("Name") ?? "");
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "SysData")//特殊指令数据库查询
{
string com_ = deserialized.GetValue("Comm").ToString()!;
string da_ = deserialized.GetValue("Data").ToString()!;
if (com_ == "SYSDB")//本机sqlite数据库
{
DataTable resultTable = MainWindowViewModel.SQLiteHelpers.ExecuteDataSet(da_, null)?.Tables[0] ?? new DataTable();
data_.Add("DB", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
data_.Add("Comm", "SYSDB");
data_.Add("Enterprise", MainWindowViewModel.Enterprise);
}
else if (com_ == "DBCDB")//系统dbc数据库
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync(da_);
data_.Add("DB", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
data_.Add("Comm", "DBCDB");
data_.Add("Enterprise", MainWindowViewModel.Enterprise);
}
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "ChemicalStatistics")//回复请求的信息
{
data_.Add("ChemicalStatistics", Newtonsoft.Json.JsonConvert.SerializeObject(MainWindowViewModel.ChemicalStatistics));
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "Info")//回复info请求的信息
{
var t = ToList(MainWindowViewModel._machines).ToJsonString();
//格式化返回信息
data_.Add("Info", t);
data_.Add("DyeMeasurementNumber", MainWindowViewModel.DyeMeasurementNumber.ToString());
data_.Add("ChemicalNumber", MainWindowViewModel.ChemicalNumber.ToString());
data_.Add("PowderNumber", MainWindowViewModel.PowderNumber.ToString());
data_.Add("DyeDissolveNumber", MainWindowViewModel.DyeDissolveNumber.ToString());
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "Query")//回复Query请求的信息
{
string s_ = deserialized.GetValue("StartTime").ToString()!;
string e_ = deserialized.GetValue("EndTime").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE CreationTime>'" + s_ + "'and CreationTime<'" + e_ + "'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "QueryDyelot")//回复QueryDyelot请求的信息
{
string d_ = deserialized.GetValue("DyelotName").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE Dyelot LIKE '" + d_ + "%'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "QueryDetail")//回复QueryDetail请求的信息
{
string d_ = deserialized.GetValue("Dyelot").ToString()!;
string r_ = deserialized.GetValue("ReDye").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyelotsBulkedRecipe] " + "WHERE Dyelot='" + d_ + "'and ReDye='" + r_ + "'");
//格式化返回信息
data_.Add("QueryDetail", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "Notification")//回复Notification请求的信息
{
string s_; try { s_ = deserialized.GetValue("StartTime").ToString()!; } catch(Exception) { s_ = "0"; }
string e_ = deserialized.GetValue("EndTime").ToString()!;
var groups = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData,
"Groups", "User='" + person?.User + "'");
var department = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData,
"Department", "User='" + person?.User + "'");
DataTable resultTable = MainWindowViewModel.SQLiteHelpers.ExecuteDataSet("" +
"select * from Notification WHERE Groups='" + groups + "'and Department='" +
department + "' and Id>'" + s_ + "'", null)?.Tables[0] ?? new DataTable();
if(resultTable.Rows.Count==0) resultTable.Rows.Add();
//格式化返回信息
data_.Add("Notification", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "InfoMachine")//回复InfoMachine请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ =null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "10")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitDispenseDyestuff] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "10");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "12")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[ShelfInfo] ");
data_.Add("Type", "12");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "20")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitChemical] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "20");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachine", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "InfoMachineHistory")//回复InfoMachineHistory请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "80")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3)+
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "80");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "82")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[inOutRecords] WHERE Createtime >'" + DateTime.Now.AddDays(-3)+"'");
data_.Add("Type", "82");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "90")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3) +
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "90");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachineHistory", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "InfoMachinePipes")//回复Notification请求的信息
{
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Pipes] WHERE Dispenser='" + m_ + "'");
data_.Add("InfoMachinePipes", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
else if (Command == "SETUSER")//回复请求的信息
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData,
"User='" + deserialized.GetValue("USER").ToString()! + "'" ,
deserialized.GetValue("VALUE").ToString(), deserialized.GetValue("KEY").ToString()!);
data_.Add("USER", deserialized.GetValue("USER").ToString()!);
data_.Add("VALUE", deserialized.GetValue("VALUE").ToString()!);
data_.Add("KEY", deserialized.GetValue("KEY").ToString()!);
data_.Add("SETUSER", "OK");
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
//加密回传
/*Console.WriteLine("[Log on]User[" + person?.User + "]REPLY[" +
Regex.Replace(ret, @"\\u[0-9A-Fa-f]{4}", match =>
{ return Regex.Unescape(match.Value); }) + "]");*/
person!.Dat =AES.AesEncipher( person.Terminal, ret);
var jsdat = JsonSerializer.Serialize(person);
await tcpClient.SendAsync(jsdat);
}
catch (Exception ex)
{
LogGing.ERRDATA(ex);
Console.WriteLine(ex.ToString());
}
}
}
}
+260 -62
View File
@@ -1,11 +1,17 @@
using System;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Data;
using System.Net.Sockets;
using System.Security.Cryptography.Pkcs;
using System.Text;
using System.Text.Json;
using System.Windows;
using System.Windows.Markup;
using System.Xml.Linq;
using TouchSocket.Core;
using TouchSocket.Sockets;
using SunlightAggregationManager.ViewModel;
using System.Security.Cryptography.Pkcs;
using static SunlightAggregationManager.UserClass.AsyncTcpServer;
namespace SunlightAggregationManager.UserClass
{
@@ -15,10 +21,18 @@ namespace SunlightAggregationManager.UserClass
{
public required string User { get; set; }
public required string Password { get; set; }
public required string IP { get; set; }
public required string Terminal { get; set; }
public required string Dat { get; set; }
}
public static async void Configuration(int P1, int P2)
{
await TcpMain(P1, P2);
}
public static TcpService service = new TcpService();
public static async Task TcpMain(int port1 ,int port2)
{
NetFwManger.AllowPort(port1, "TCP");//开放7790端口
@@ -26,7 +40,9 @@ namespace SunlightAggregationManager.UserClass
//TcpService service = new TcpService();
service.Connecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在连接
service.Connected = (client, e) => {return EasyTask.CompletedTask;};//有客户端成功连接
service.Closing = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在断开连接,只有当主动断开时才有效。
service.Closing = (client, e) => {
Console.WriteLine("[Disconnecting]IP[" + client.IP + "]ID[" + client.Id + "]");
return EasyTask.CompletedTask; };//有客户端正在断开连接,只有当主动断开时才有效。
service.Closed = (client, e) => {
//离线记录
Dictionary<string, object> myDictOff = new Dictionary<string, object>();
@@ -44,8 +60,8 @@ namespace SunlightAggregationManager.UserClass
{
Person? deserializedPerson = JsonSerializer.Deserialize<Person>(DAT);
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" + deserializedPerson?.User +
"' and Password ='" + deserializedPerson?.Password + "'");
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" +
deserializedPerson?.User + "' and Password ='" + deserializedPerson?.Password + "'");
if (_user != null)
{
string _dat = _user?.ToString() ?? "0";
@@ -55,27 +71,42 @@ namespace SunlightAggregationManager.UserClass
{//行为
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("LinkID", client.Id);
myDict.Add("LastLoginIP", client.IP);
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", deserializedPerson?.Dat ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + deserializedPerson?.User + "'", myDict);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]Note[" + (deserializedPerson?.Dat ?? "unknown") + "]");
Command(deserializedPerson?.Dat ?? "NOT", client.Id, deserializedPerson!);
}
else
{//首次登录记录
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("State", 20);
myDict.Add("LinkID", client.Id);
myDict.Add("LastLoginIP", client.IP);
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastLoginTime", DateTime.Now);
myDict.Add("LastLoginTerminal", deserializedPerson?.Terminal ?? "unknown device");
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", deserializedPerson?.Dat ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + deserializedPerson?.User + "'", myDict);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]IP[" + client.IP +
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]IP[" + deserializedPerson?.IP ?? client.IP +
"]ID[" + client.Id + "]Terminal[" + (deserializedPerson?.Terminal ?? "unknown device") + "]");
//返回登录信息
Dictionary<string, object> login = new Dictionary<string, object>();
DataRow? dat = MainWindowViewModel.Selet_Row(MainWindowViewModel._userData,"User='" +
deserializedPerson?.User + "' and Password ='" + deserializedPerson?.Password + "'");
login.Add("Enterprise", dat?.Field<object>("Enterprise")??"");
login.Add("Department", dat?.Field<object>("Department") ?? "");
login.Add("Groups", dat?.Field<object>("Groups") ?? "");
login.Add("UserId", dat?.Field<object>("UserID") ?? "");
login.Add("UserName", dat?.Field<object>("Name") ?? "");
deserializedPerson!.Dat = JsonSerializer.Serialize(login);
var jsdat = JsonSerializer.Serialize(deserializedPerson);
client.SendAsync(jsdat);
}
}
else
@@ -109,6 +140,7 @@ namespace SunlightAggregationManager.UserClass
}
catch (Exception ex)
{//错误
LogGing.ERRDATA(ex);
Console.WriteLine("Tcp:" + ex.ToString());
client.SendAsync("Target instruction parsing error manager will close connection");
foreach (var item in AsyncTcpServer.service.Clients)
@@ -121,18 +153,12 @@ namespace SunlightAggregationManager.UserClass
}
}
//string DAT = e.ByteBlock.Span.ToString(Encoding.UTF8).Substring(5);
//string SYSDAT = "";// = e.ByteBlock.Span.ToString(Encoding.ASCII).Substring(5);
// string SYSKEY = "";
// if (DAT.Length >= 16) SYSKEY = DAT.Substring(0, 16);
// if (DAT.Length > 16) SYSDAT = DAT.Substring(16);
return EasyTask.CompletedTask;
};
await service.SetupAsync(new TouchSocketConfig()//载入配置
// .SetMaxBufferSize(1024 * 1024 * 100)
// .SetMaxBufferSize(1024 * 1024 * 100)
//.SetMinBufferSize(1024 * 1024)
.SetListenIPHosts(new IPHost[] { new IPHost(port1), new IPHost(port2) })//同时监听两个地址
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
@@ -142,67 +168,239 @@ namespace SunlightAggregationManager.UserClass
{
})
);
await service.StartAsync();//启动
Console.WriteLine("TCP Port:"+ port1.ToString());
Console.WriteLine("TCP Port:"+ port2.ToString());
Console.WriteLine("TCP SERVER:START");
}
}
class MyTcpService : TcpService<MyTcpSessionClient>
{
protected override MyTcpSessionClient NewClient()
public static async void Command(string dat, string id, Person person)//
{
return new MyTcpSessionClient();
}
}
class MyTcpSessionClient : TcpSessionClient
{
internal void SetDataHandlingAdapter(SingleStreamDataHandlingAdapter adapter)
{
base.SetAdapter(adapter);
}
}
/// <summary>
/// 此插件实现,按照不同端口,使用不同适配器。
/// <list type="bullet">
/// <item>7789端口:使用"**"结尾的数据</item>
/// <item>7790端口:使用"##"结尾的数据</item>
/// </list>
/// </summary>
internal class DifferentProtocolPlugin : PluginBase, ITcpConnectingPlugin, ITcpReceivedPlugin
{
public async Task OnTcpConnecting(ITcpSession client, ConnectingEventArgs e)
{
if (client is MyTcpSessionClient sessionClient)
try
{
if (sessionClient.ServicePort == 7789)
string Command = "", ret = "";
Dictionary<string, object> data_ = new Dictionary<string, object>();
var deserialized = JsonSerializer.Deserialize<Dictionary<string, object>>(dat)!;
if (deserialized.TryGetValue("Command", out var val) && val != null) Command = val.ToString()!;
if (Command == "Log")//回复请求的信息
{
sessionClient.SetDataHandlingAdapter(new TerminatorPackageAdapter("**"));
DataRow? _user = MainWindowViewModel.Selet_Row(MainWindowViewModel._userData, "User='" +
person?.User + "' and Password ='" + person?.Password + "'");
data_.Add("Enterprise", _user?.Field<object>("Enterprise") ?? "");
data_.Add("Department", _user?.Field<object>("Department") ?? "");
data_.Add("Groups", _user?.Field<object>("Groups") ?? "");
data_.Add("UserId", _user?.Field<object>("UserID") ?? "");
data_.Add("UserName", _user?.Field<object>("Name") ?? "");
ret = JsonSerializer.Serialize(data_);
}
else
if (Command == "SysData")//回复请求的信息
{
sessionClient.SetDataHandlingAdapter(new TerminatorPackageAdapter("##"));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "ChemicalStatistics")//回复请求的信息
{
data_.Add("ChemicalStatistics", Newtonsoft.Json.JsonConvert.SerializeObject(MainWindowViewModel.ChemicalStatistics));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Info")//回复info请求的信息
{
var t = ToList(MainWindowViewModel._machines).ToJsonString();
//格式化返回信息
data_.Add("Info", t);
data_.Add("DyeMeasurementNumber", MainWindowViewModel.DyeMeasurementNumber.ToString());
data_.Add("ChemicalNumber", MainWindowViewModel.ChemicalNumber.ToString());
data_.Add("PowderNumber", MainWindowViewModel.PowderNumber.ToString());
data_.Add("DyeDissolveNumber", MainWindowViewModel.DyeDissolveNumber.ToString());
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Query")//回复Query请求的信息
{
string s_ = deserialized.GetValue("StartTime").ToString()!;
string e_ = deserialized.GetValue("EndTime").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE CreationTime>'" + s_ + "'and CreationTime<'" + e_ + "'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "QueryDyelot")//回复QueryDyelot请求的信息
{
string d_ = deserialized.GetValue("DyelotName").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Dyelots] " + "WHERE Dyelot LIKE '" + d_ + "%'");
//格式化返回信息
data_.Add("Query", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "QueryDetail")//回复QueryDetail请求的信息
{
string d_ = deserialized.GetValue("Dyelot").ToString()!;
string r_ = deserialized.GetValue("ReDye").ToString()!;
string f_ = deserialized.GetValue("Field").ToString()!;
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyelotsBulkedRecipe] " + "WHERE Dyelot='" + d_ + "'and ReDye='" + r_ + "'");
//格式化返回信息
data_.Add("QueryDetail", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "Notification")//回复Notification请求的信息
{
string s_ = deserialized.GetValue("StartTime").ToString()!;
string e_ = deserialized.GetValue("EndTime").ToString()!;
var groups = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData,
"Groups", "User='" + person?.User + "'");
DataTable resultTable = MainWindowViewModel.SQLiteHelpers.ExecuteDataSet("" +
"select * from Notification WHERE Groups='" + groups + "' and Id>'" +
s_ + "'", null)?.Tables[0] ?? new DataTable();
if (resultTable.Rows.Count == 0) resultTable.Rows.Add();
//格式化返回信息
data_.Add("Notification", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachine")//回复InfoMachine请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "10")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitDispenseDyestuff] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "10");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "12")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[ShelfInfo] ");
data_.Add("Type", "12");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "20")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[WaitChemical] WHERE DispenseMachine='" + m_ + "'");
data_.Add("Type", "20");
data_.Add("InfoMachine", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachine", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachineHistory")//回复InfoMachineHistory请求的信息
{
string t_ = deserialized.GetValue("Type").ToString()!;
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
if (t_ == "80")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3) +
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "80");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "82")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[inOutRecords] WHERE Createtime >'" + DateTime.Now.AddDays(-3) + "'");
data_.Add("Type", "82");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else if (t_ == "90")
{
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[DyeSolutionHistory] WHERE DispenseStartTime >'" + DateTime.Now.AddDays(-3) +
"' and DispenseMachine='" + m_ + "'");
data_.Add("Type", "90");
data_.Add("InfoMachineHistory", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
}
else
{
data_.Add("InfoMachineHistory", "");
}
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "InfoMachinePipes")//回复Notification请求的信息
{
string? m_ = null, f_ = "*";
if (deserialized.TryGetValue("MachinName", out var MachinName) && MachinName != null) m_ = MachinName.ToString();
if (deserialized.TryGetValue("Field", out var Field) && Field != null) f_ = Field.ToString();
DataTable resultTable = await MainWindowViewModel.dataBase.ExecuteQueryAsync("SELECT " +
f_ + " FROM [dbo].[Pipes] WHERE Dispenser='" + m_ + "'");
data_.Add("InfoMachinePipes", Newtonsoft.Json.JsonConvert.SerializeObject(resultTable));
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
if (Command == "SETUSER")//回复Notification请求的信息
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData,
"User='" + deserialized.GetValue("USER").ToString()! + "'",
deserialized.GetValue("VALUE").ToString(), deserialized.GetValue("KEY").ToString()!);
data_.Add("USER", deserialized.GetValue("USER").ToString()!);
data_.Add("VALUE", deserialized.GetValue("VALUE").ToString()!);
data_.Add("KEY", deserialized.GetValue("KEY").ToString()!);
data_.Add("SETUSER", "OK");
//格式化返回信息
ret = JsonSerializer.Serialize(data_);
}
person!.Dat = ret.ToString();
var jsdat = JsonSerializer.Serialize(person);
await service.SendAsync(id, jsdat);
}
await e.InvokeNext();
}
public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e)
{
//如果是自定义适配器,此处解析时,可以判断e.RequestInfo的类型
if (client is ITcpSessionClient sessionClient)
catch (Exception ex)
{
sessionClient.Logger.Info($"{sessionClient.GetIPPort()}收到数据,服务器端口:{sessionClient.ServicePort},数据:{e.Memory.Span.ToString(Encoding.UTF8)}");
LogGing.ERRDATA(ex);
Console.WriteLine(ex.ToString());
}
await e.InvokeNext();
}
public static List<Dictionary<string, object?>>? ToList(DataTable table)//datatable转list
{
if (table == null) return null;
// 使用 AsEnumerable() 将 DataTable 转换为 IEnumerable<DataRow>
// 然后投影为 Dictionary
return table.AsEnumerable().Select(row =>
table.Columns.Cast<DataColumn>().ToDictionary(
col => col.ColumnName,
col => {
var value = row[col];
// 核心修改:如果是数据库空值 DBNull.Value,则转为 C# 的 null,否则保持原值
return value == DBNull.Value ? null : value;
}
)
).ToList();
}
}
}
+95 -4
View File
@@ -2,6 +2,7 @@
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
@@ -17,8 +18,7 @@ namespace SunlightAggregationManager.UserClass
private string DB_IP = null!;
private string DB_PASSWORD = null!;
public void Config(string ip, string name, string type, string id, string password)
public async void Config(string ip, string name, string type, string id, string password)
{
DB_IP = ip;
DB_ID = id;
@@ -26,7 +26,7 @@ namespace SunlightAggregationManager.UserClass
DB_TYPE = type;
DB_PASSWORD = password;
_= ConfigAsync();
await ConfigAsync();
}
public async Task ConfigAsync()
@@ -63,7 +63,8 @@ namespace SunlightAggregationManager.UserClass
}
catch (Exception ex)
{
Console.WriteLine("DataBase Link timeout\n"+ex.ToString());
LogGing.ERRDATA(ex);
Console.WriteLine("DataBase Link timeout\n"+ ex.Message.ToString());
// 失败处理
return; // 直接返回,不执行后续代码
}
@@ -71,6 +72,96 @@ namespace SunlightAggregationManager.UserClass
});
}
public async Task<DataTable> ExecuteQueryAsync(string sql)
{
// 创建一个空的 DataTable 用于存放查询结果
DataTable dataTable = new DataTable();
// 数据库连接字符串构建逻辑
var builder = new SqlConnectionStringBuilder
{
DataSource = DB_IP,
InitialCatalog = DB_NAME,
IntegratedSecurity = DB_TYPE == "Windows Authentication",
TrustServerCertificate = true,
ConnectTimeout = 5
};
if (!builder.IntegratedSecurity)
{
builder.UserID = DB_ID;
builder.Password = DB_PASSWORD;
}
try
{
using var conn = new SqlConnection(builder.ConnectionString);
await conn.OpenAsync(); // 使用异步方式打开连接<websource>source_group_web_2</websource>
using (var cmd = new SqlCommand(sql, conn))
{
// 执行查询并将结果直接加载到 DataTable 中
using (var reader = await cmd.ExecuteReaderAsync())
{
dataTable.Load(reader);
}
}
}
catch (Exception ex)
{
LogGing.ERRDATA(ex);
Console.WriteLine("DataBase Query failed\n" + ex.Message.ToString());
}
return dataTable;
}
public async Task<int> ExecuteQueryAsyncCount(string sql)
{
// 创建一个空的 DataTable 用于存放查询结果
DataTable dataTable = new DataTable();
// 数据库连接字符串构建逻辑
var builder = new SqlConnectionStringBuilder
{
DataSource = DB_IP,
InitialCatalog = DB_NAME,
IntegratedSecurity = DB_TYPE == "Windows Authentication",
TrustServerCertificate = true,
ConnectTimeout = 5
};
if (!builder.IntegratedSecurity)
{
builder.UserID = DB_ID;
builder.Password = DB_PASSWORD;
}
try
{
using var conn = new SqlConnection(builder.ConnectionString);
await conn.OpenAsync(); // 使用异步方式打开连接<websource>source_group_web_2</websource>
using (var cmd = new SqlCommand(sql, conn))
{
// 执行查询并将结果直接加载到 DataTable 中
using (var reader = await cmd.ExecuteReaderAsync())
{
dataTable.Load(reader);
}
}
}
catch (Exception ex)
{
LogGing.ERRDATA(ex);
Console.WriteLine("DataBase Query failed\n" + ex.Message.ToString());
}
return dataTable.Rows.Count;
}
public void Database(string dat)
{
+52
View File
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace SunlightAggregationManager.UserClass
{
public class GetLocalIP
{
public static string GetLocalIPv4Address()
{
// 获取所有网络接口
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var ni in networkInterfaces)
{
// 筛选条件:
// 1. 网卡状态为 Up (已连接)
// 2. 排除虚拟网卡、回环网卡、隧道网卡
// 3. 支持 IPv4
if (ni.OperationalStatus == OperationalStatus.Up &&
ni.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel &&
!ni.Description.Contains("Virtual") && // 排除常见的虚拟网卡描述
ni.Supports(NetworkInterfaceComponent.IPv4))
{
var ipProperties = ni.GetIPProperties();
// 获取单播地址(即分配的 IP 地址)
var unicastAddresses = ipProperties.UnicastAddresses;
foreach (var ua in unicastAddresses)
{
// 筛选出 IPv4 地址,且排除 127.0.0.1 回环地址
if (ua.Address.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(ua.Address))
{
// 优先返回有默认网关的地址(通常是当前正在上网的主网卡)
if (ipProperties.GatewayAddresses.Any(g => g.Address.AddressFamily == AddressFamily.InterNetwork))
{
return ua.Address.ToString();
}
}
}
}
}
return "未找到有效的局域网IPv4地址";
}
}
}
+166
View File
@@ -0,0 +1,166 @@
using SunlightAggregationManager.View;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SunlightAggregationManager.UserClass
{
public class LogGing
{
public class LOGinf
{
public required string Logpath { get; set; }
public required string LogPath { get; set; }
public required string Log_time { get; set; }
public required object DAT { get; set; }
}
static Queue<LOGinf> LogGingQueue = new Queue<LOGinf>();
static Queue<LOGinf> ERRQueue = new Queue<LOGinf>();
static Queue<LOGinf> ExchangeQueue = new Queue<LOGinf>();
public static void LogGingDATA(string dat)
{
LOGinf ginf = new LOGinf
{
Logpath = System.Environment.CurrentDirectory + "\\Log",//日志文件目录
LogPath = "" + System.Environment.CurrentDirectory + "\\Log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt",//日志文件
Log_time = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]:",
DAT = dat
};
LogGingQueue.Enqueue(ginf);
if(LogGingQueue.Count==1) LogGingQueueW();
}
public static async void LogGingQueueW()
{
while (true)
{
try
{
LOGinf inf = LogGingQueue.Dequeue();
if (Directory.Exists(inf.Logpath))//检查日志路径
{
if (!File.Exists(inf.LogPath))//检查日志文件并写入启动日志
{
FileStream fs = new FileStream(inf.LogPath, FileMode.CreateNew, FileAccess.Write);//创建写入文件
StreamWriter wr = new StreamWriter(fs);//创建文件
wr.WriteLine(inf.Log_time + inf.DAT);
wr.Close();
}
else
{
FileStream fs = new FileStream(inf.LogPath, FileMode.Append, FileAccess.Write);
StreamWriter wr = new StreamWriter(fs);//创建文件
wr.WriteLine(inf.Log_time + inf.DAT);
wr.Close();
}
}
else
{
DirectoryInfo directoryInfo = new DirectoryInfo(inf.Logpath);
directoryInfo.Create();//创建日志路径
}
}
catch (Exception ) { }
if (LogGingQueue.Count == 0) break;
}
}
public static void ERRDATA(System.Exception dat)
{
LOGinf ginf = new LOGinf
{
Logpath = System.Environment.CurrentDirectory + "\\ERR",//日志文件目录
LogPath = "" + System.Environment.CurrentDirectory + "\\ERR\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt",//日志文件
Log_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
DAT = dat
};
ERRQueue.Enqueue(ginf);
if (ERRQueue.Count == 1) ERRQueueW();
}
public static async void ERRQueueW()
{
while (true)
{
try
{
LOGinf inf = ERRQueue.Dequeue();
Exception dat = (Exception)inf.DAT;
if (Directory.Exists(inf.Logpath))//检查日志路径
{
if (!File.Exists(inf.LogPath))//检查文件并写入
{
// FileStream fs = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建文件
// StreamWriter wr = new StreamWriter(fs);//创建文件
// wr.Close();
FileStream fil = new FileStream(inf.LogPath, FileMode.CreateNew, FileAccess.Write);//创建写入文件
StreamWriter wfil = new StreamWriter(fil);//创建文件
wfil.WriteLine("[" + inf.Log_time + "];[Error] ||" + Environment.NewLine.ToString());
wfil.WriteLine("[" + inf.Log_time + "];[Error source] ||" + dat.Source.ToString() + Environment.NewLine.ToString());
wfil.WriteLine("[" + inf.Log_time + "];[Error message] ||" + dat.Message.ToString() + Environment.NewLine.ToString());
wfil.WriteLine("[" + inf.Log_time + "];[Error area] ||" + dat.StackTrace.ToString());
wfil.Close();
}
else
{
FileStream fs = new FileStream(inf.LogPath, FileMode.Append, FileAccess.Write);//创建写入文件
StreamWriter wr = new StreamWriter(fs);//创建文件
wr.WriteLine("[" + inf.Log_time + "];[Error] ||" + Environment.NewLine.ToString());
wr.WriteLine("[" + inf.Log_time + "];[Error source] ||" + dat.ToString() + Environment.NewLine.ToString());
wr.WriteLine("[" + inf.Log_time + "];[Error message] ||" + dat.Message.ToString() + Environment.NewLine.ToString());
wr.WriteLine("[" + inf.Log_time + "];[Error area] ||" + dat.ToString());
wr.Close();
}
}
else
{
DirectoryInfo directoryInfo = new DirectoryInfo(inf.Logpath);
directoryInfo.Create();
}
}
catch (Exception) { }
if (ERRQueue.Count == 0) break;
}
}
public static void ExchangeDATA(string dat)
{
string Log_time = DateTime.Now.ToString("yyyy-MM-dd");
string logpath = System.Environment.CurrentDirectory + "\\Exchange";//日志文件目录
// string logPathtxt = "" + System.Environment.CurrentDirectory + "\\Log\\"+ Log_time + "Log.txt";//日志文件
// System.IO.DirectoryInfo log = new System.IO.DirectoryInfo();//生成日志文件目录
string log_path = logpath + "\\Exchange" + Log_time + ".txt";
string Log_timehms = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
if (Directory.Exists(logpath))//检查日志路径
{
if (!File.Exists(log_path))//检查文件并写入
{
// FileStream fs = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建文件
// StreamWriter wr = new StreamWriter(fs);//创建文件
// wr.Close();
FileStream fil = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建写入文件
StreamWriter wfil = new StreamWriter(fil);//创建文件
wfil.WriteLine("[" + Log_timehms + "];[Exchange] ||" + dat);
wfil.Close();
}
else
{
FileStream fs = new FileStream(log_path, FileMode.Append, FileAccess.Write);//创建写入文件
StreamWriter wr = new StreamWriter(fs);//创建文件
wr.WriteLine("[" + Log_timehms + "];[Exchange] ||" + dat);
wr.Close();
}
}
else
{
DirectoryInfo directoryInfo = new DirectoryInfo(logpath);
directoryInfo.Create();
}
}
}
}
+55 -41
View File
@@ -15,61 +15,75 @@ namespace SunlightAggregationManager.UserClass
public static void AllowPort(int port, string protocol)
{
DelPort(port, protocol);
//创建一个INetFwRule对象
Type type = Type.GetTypeFromProgID("HNetCfg.FwRule") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwRule? rule = (INetFwRule?)Activator.CreateInstance(type);
//设置规则的属性
rule?.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; //允许连接
rule?.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; //入站规则
rule?.Enabled = true; //启用规则
rule?.InterfaceTypes = "All"; //适用于所有网络接口
rule?.Name = GetName(port, protocol); //规则名称
if (protocol.ToLower() == "tcp")
try
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP; //TCP协议
DelPort(port, protocol);
//创建一个INetFwRule对象
Type type = Type.GetTypeFromProgID("HNetCfg.FwRule") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwRule? rule = (INetFwRule?)Activator.CreateInstance(type);
//设置规则的属性
rule?.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; //允许连接
rule?.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; //入站规则
rule?.Enabled = true; //启用规则
rule?.InterfaceTypes = "All"; //适用于所有网络接口
rule?.Name = GetName(port, protocol); //规则名称
if (protocol.ToLower() == "tcp")
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP; //TCP协议
}
else
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP; //UDP协议
}
rule?.LocalPorts = "" + port; //本地端口号
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//将规则添加到防火墙策略中
policy?.Rules.Add(rule);
Console.WriteLine("Add firewall port:" + port);
}
else
catch (Exception ex)
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP; //UDP协议
Console.WriteLine(ex.ToString());
}
rule?.LocalPorts = "" + port; //本地端口号
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//将规则添加到防火墙策略中
policy?.Rules.Add(rule);
}
public static void DelPort(int port, string protocol)
{
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//获取现有的规则集合
INetFwRules? rules = policy?.Rules;
if (rules != null)
try
{
//查找名称的规则并删除它
foreach (INetFwRule rule in rules)
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//获取现有的规则集合
INetFwRules? rules = policy?.Rules;
if (rules != null)
{
if (rule.Name == GetName(port, protocol))
//查找名称的规则并删除它
foreach (INetFwRule rule in rules)
{
rules.Remove(rule.Name);
Console.WriteLine(@"Firewall rule deleted successfully.");
break;
if (rule.Name == GetName(port, protocol))
{
rules.Remove(rule.Name);
//Console.WriteLine(@"Firewall rule deleted successfully.");
break;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
+15 -8
View File
@@ -10,25 +10,32 @@ namespace SunlightAggregationManager.UserClass
public class ControlWriter : TextWriter
{
private readonly TextBox _textbox;
private readonly Action<string> _logGingDataAction;
public ControlWriter(TextBox textbox)
public ControlWriter(TextBox textbox,Action<string> logGingDataAction)
{
_textbox = textbox;
_logGingDataAction = logGingDataAction;
}
public override void Write(char value) => AppendText(DateTime.Now + ": " + value.ToString());
public override void Write(string? value) => AppendText(DateTime.Now + ": " + value);
public override void WriteLine(string? value) => AppendText(DateTime.Now + ": "+value + Environment.NewLine);
public override void Write(char value) => AppendText(DateTime.Now + ": " + value.ToString(), true);
public override void Write(string? value) => AppendText(DateTime.Now + ": " + value, true);
public override void WriteLine(string? value) => AppendText(DateTime.Now + ": "+value + Environment.NewLine, true);
private void AppendText(string text)
private void AppendText(string text, bool invokeExternalLog)
{
if (!_textbox.Dispatcher.CheckAccess())
{
_textbox.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => AppendText(text)));
_textbox.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => AppendText(text, true)));
return;
}
_textbox.AppendText(text);
_textbox.ScrollToEnd();
if (invokeExternalLog)
{
_logGingDataAction?.Invoke(text);
}
}
public override Encoding Encoding => Encoding.UTF8;
@@ -41,10 +48,10 @@ namespace SunlightAggregationManager.UserClass
// 【核心功能】注册目标 TextBox
// 子页面加载时调用这个方法
public static void RegisterTarget(TextBox logBox)
public static void RegisterTarget(TextBox logBox ,Action<string> logGingDataAction)
{
// 创建新的 Writer
_currentWriter = new ControlWriter(logBox);
_currentWriter = new ControlWriter(logBox, logGingDataAction);
// 【关键】将 Console 的输出重定向到这个 Writer
// 这样 Console.WriteLine("...") 就会自动写入到 logBox 中
+144
View File
@@ -0,0 +1,144 @@
<Window x:Class="SunlightAggregationManager.UserWindow.MachineSet"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SunlightAggregationManager.UserWindow"
xmlns:ConvertMoels="clr-namespace:SunlightAggregationManager.ConvertMoels"
xmlns:lang="clr-namespace:SunlightAggregationManager"
xmlns:viewmodel="clr-namespace:SunlightAggregationManager.ViewModel"
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
mc:Ignorable="d"
Title="MachineSet"
Loaded="Window_Loaded"
ResizeMode="NoResize"
Height="900" Width="1440" MinHeight="900" MinWidth="1440">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="5"/>
<RowDefinition/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" Background="#FFCECECE"/>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" Background="#FFCECECE"/>
<Grid Grid.Column="0">
<!--用户-->
<TextBox x:Name="_Name" Height="30" Margin="105,10,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,10,0,100" TextWrapping="Wrap"
Text="归属信息" VerticalAlignment="Top" Width="85" FontSize="20"/>
<TextBox x:Name="_Machine" Height="30" Margin="105,55,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,55,0,100" TextWrapping="Wrap"
Text="设备名称" VerticalAlignment="Top" Width="85" FontSize="20"/>
<ComboBox x:Name="GROUP" Height="30" Margin="105,100,10,100" VerticalAlignment="Top" FontSize="16" IsReadOnly="True">
<ComboBoxItem Content="200"></ComboBoxItem>
<ComboBoxItem Content="202"></ComboBoxItem>
<ComboBoxItem Content="242W"></ComboBoxItem>
<ComboBoxItem Content="252"></ComboBoxItem>
<ComboBoxItem Content="252-2T"></ComboBoxItem>
<ComboBoxItem Content="252RB"></ComboBoxItem>
<ComboBoxItem Content="252RDRM"></ComboBoxItem>
<ComboBoxItem Content="252-2T"></ComboBoxItem>
<ComboBoxItem Content="301"></ComboBoxItem>
<ComboBoxItem Content="301P"></ComboBoxItem>
<ComboBoxItem Content="302"></ComboBoxItem>
<ComboBoxItem Content="303"></ComboBoxItem>
<ComboBoxItem Content="303PDW"></ComboBoxItem>
</ComboBox>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,100,0,50" TextWrapping="Wrap"
Text="系列型号" VerticalAlignment="Top" Width="80" FontSize="20"/>
<TextBox x:Name="_IP" Height="30" Margin="105,145,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,145,0,100" TextWrapping="Wrap"
Text="连接IP" VerticalAlignment="Top" Width="85" FontSize="20"/>
<TextBox x:Name="_MachineUser" Height="30" Margin="105,190,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,190,0,100" TextWrapping="Wrap"
Text="连接用户" VerticalAlignment="Top" Width="85" FontSize="20"/>
<TextBox x:Name="_MachinePassword" Height="30" Margin="105,235,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,235,0,100" TextWrapping="Wrap"
Text="连接密码" VerticalAlignment="Top" Width="85" FontSize="20"/>
<TextBox x:Name="_inf" Height="90" Margin="105,280,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1"/>
</Grid>
<Grid Grid.Column="2" Margin="0">
<ScrollViewer Margin="0" VerticalScrollBarVisibility="Auto">
<WrapPanel Orientation="Horizontal" x:Name="Capacity" >
</WrapPanel>
</ScrollViewer>
</Grid>
</Grid>
<!--表-->
<DataGrid Grid.Row="2" x:Name="DataGridm" MouseDoubleClick="DataGridm_MouseDoubleClick"
SelectionMode="Single" AlternationCount="2" IsReadOnly="True"
ItemsSource="{Binding Machines.DefaultView}"
AutoGenerateColumns="False" MinColumnWidth="30"
HorizontalGridLinesBrush="#FFC9C9C9" VerticalGridLinesBrush="#FFC9C9C9"
GridLinesVisibility="All" BorderBrush="{x:Null}"
BorderThickness="1,1,1,1" ColumnHeaderHeight="40"
HorizontalContentAlignment="Right" Grid.ColumnSpan="2"
CanUserResizeRows="False" CanUserAddRows="False"
CanUserDeleteRows="False" CanUserReorderColumns="False"
CanUserResizeColumns="False" CanUserSortColumns="False"
HeadersVisibility ="Column" Background="{x:Null}">
<DataGrid.RowStyle >
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FFFFFFFF" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF0F0F0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinWidth" Value="20"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFC0C0C0"/>
<Setter Property="BorderBrush" Value="#FFC0C0C0"/>
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Width="0" FontSize="26" Binding="{Binding ID}" MaxWidth="0" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="200" FontSize="26"
Binding="{Binding Name}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.machine}" Width="200" FontSize="26"
Binding="{Binding Machine}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.state}" Width="150" FontSize="26"
Binding="{Binding State}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Mode}" Width="150" FontSize="26"
Binding="{Binding Model}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="IP" Width="150" FontSize="26"
Binding="{Binding IP}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="用户" Width="150" FontSize="26"
Binding="{Binding MachineUser}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="密码" Width="150" FontSize="26"
Binding="{Binding MachinePassword}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="*" FontSize="26"
Binding="{Binding Information}" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
<!--存储按钮-->
<Button Grid.Row="3" Content="存储" HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="100" FontSize="30"
Click="Button_Preservation" Margin="0,0,200,0">
</Button>
<!--删除按钮-->
<Button Grid.Row="3" Content="删除" HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="100" FontSize="30"
Click="Button_Delete" Margin="0,0,50,0">
</Button>
</Grid>
</Window>
+96
View File
@@ -0,0 +1,96 @@
using Microsoft.VisualBasic;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SunlightAggregationManager.UserWindow
{
/// <summary>
/// MachineSet.xaml 的交互逻辑
/// </summary>
public partial class MachineSet : Window
{
private string _id = "";
public MachineSet()
{
InitializeComponent();
}
private void Button_Preservation(object sender, RoutedEventArgs e)
{
Dictionary<string, object> _new = new Dictionary<string, object>();//缓存函数
_new.Add("Name", _Name.Text);
_new.Add("Machine", _Machine.Text);
_new.Add("Model", GROUP.Text);
_new.Add("IP", _IP.Text);
_new.Add("MachineUser", _MachineUser.Text);
_new.Add("MachinePassword", _MachinePassword.Text);
_new.Add("Information", _inf.Text);
_new.Add("State", 0);
var rowdata = MainWindowViewModel.Selet_Memory(MainWindowViewModel._machines, "ID", "ID='" + _id + "'");
if (rowdata != null)
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._machines, "ID='" + _id + "'", _new);
}
else
{
MainWindowViewModel.Insert_Memory(MainWindowViewModel._machines, _new);// 执行插入
}
DataGridm.ItemsSource = MainWindowViewModel._machines.DefaultView;
_Name.Text = null;
_Machine.Text = null;
_id = "";
}
private void Button_Delete(object sender, RoutedEventArgs e)
{
try
{
MainWindowViewModel.Delete_Memory(MainWindowViewModel._machines, "ID='" + _id + "'");
}
catch (Exception) { }
finally
{
DataGridm.ItemsSource = MainWindowViewModel._machines.DefaultView;
_Name.Text = null;
_Machine.Text = null;
_id = "";
}
}
private void DataGridm_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
int rownum = DataGridm.SelectedIndex;//获取鼠标选中行并定义变量
if (rownum != -1)//判断鼠标定位是否有效
{
/*定位选中行及指定列单元格文本信息*/
_id = (DataGridm.Columns[0].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();//定位第列
_Name.Text = (DataGridm.Columns[1].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();//定位第列
_Machine.Text = (DataGridm.Columns[2].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();//定位第列
GROUP.Text = (DataGridm.Columns[4].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();
_IP.Text = (DataGridm.Columns[5].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();
_MachineUser.Text = (DataGridm.Columns[6].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();
_MachinePassword.Text = (DataGridm.Columns[7].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();
_inf.Text = (DataGridm.Columns[8].GetCellContent(DataGridm.Items[rownum]) as TextBlock)!.Text.Trim();
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataGridm.ItemsSource = MainWindowViewModel._machines.DefaultView;
}
}
}
+126
View File
@@ -0,0 +1,126 @@
<Window x:Class="SunlightAggregationManager.UserWindow.User"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SunlightAggregationManager.UserWindow"
xmlns:viewmodel="clr-namespace:SunlightAggregationManager.ViewModel"
xmlns:lang="clr-namespace:SunlightAggregationManager"
mc:Ignorable="d"
Loaded="user_Loaded"
ResizeMode="NoResize"
Title="MAC_SET"
Height="900" Width="1440" MinHeight="900" MinWidth="1440"
BorderBrush="White" Background="White">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="5"/>
<RowDefinition/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" Background="#FFCECECE"/>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="200" MaxWidth="500"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" Background="#FFCECECE"/>
<Grid Grid.Column="0">
<!--用户-->
<TextBox x:Name="_User" Height="30" Margin="105,10,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1" InputMethod.IsInputMethodEnabled="False" />
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,10,0,100" TextWrapping="Wrap"
Text="{x:Static lang:ResourceLanguage.user}" VerticalAlignment="Top" Width="85" FontSize="20"/>
<!--名-->
<TextBox x:Name="_Name" Height="30" Margin="105,55,10,100" VerticalAlignment="Top" FontSize="16" MaxLines="1" />
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,55,0,100" TextWrapping="Wrap"
Text="{x:Static lang:ResourceLanguage.Name}" VerticalAlignment="Top" Width="85" FontSize="20"/>
<!--密码-->
<TextBox x:Name="Pasword" Height="30" Margin="105,100,10,50" VerticalAlignment="Top" FontSize="16" MaxLines="1" InputMethod.IsInputMethodEnabled="False" />
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,100,0,50" TextWrapping="Wrap"
Text="{x:Static lang:ResourceLanguage.Password}" VerticalAlignment="Top" Width="80" FontSize="20"/>
<!--部门-->
<TextBox x:Name="_Department" Height="30" Margin="105,145,10,50" VerticalAlignment="Top" FontSize="16" MaxLines="1" />
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,145,0,50" TextWrapping="Wrap"
Text="{x:Static lang:ResourceLanguage.Department}" VerticalAlignment="Top" Width="80" FontSize="20"/>
<!--组-->
<ComboBox x:Name="GROUP" Height="30" Margin="105,190,10,100" VerticalAlignment="Top" FontSize="16" IsReadOnly="True">
<ComboBoxItem Content="CHIEF"></ComboBoxItem>
<ComboBoxItem Content="ENGINEER"></ComboBoxItem>
<ComboBoxItem Content="POWERUSER"></ComboBoxItem>
<ComboBoxItem Content="USER"></ComboBoxItem>
</ComboBox>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="15,190,0,50" TextWrapping="Wrap"
Text="{x:Static lang:ResourceLanguage.Groups}" VerticalAlignment="Top" Width="80" FontSize="20"/>
</Grid>
<Grid Grid.Column="2" Margin="0">
<ScrollViewer Margin="0" VerticalScrollBarVisibility="Auto">
<WrapPanel Orientation="Horizontal" x:Name="Capacity" >
</WrapPanel>
</ScrollViewer>
</Grid>
</Grid>
<!--表-->
<DataGrid Grid.Row="2" x:Name="DataGriduser" MouseDoubleClick="DataGridMac_MouseDoubleClick" SelectionMode="Single" AlternationCount="2" IsReadOnly="True"
d:ItemsSource="{d:SampleData ItemCount=999}" AutoGenerateColumns="False" MinColumnWidth="30"
HorizontalGridLinesBrush="#FFC9C9C9" VerticalGridLinesBrush="#FFC9C9C9" GridLinesVisibility="All" BorderBrush="{x:Null}"
BorderThickness="1,1,1,1" ColumnHeaderHeight="40" HorizontalContentAlignment="Right" Grid.ColumnSpan="2"
CanUserResizeRows="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False"
CanUserResizeColumns="False" CanUserSortColumns="False" HeadersVisibility ="Column" Background="{x:Null}">
<DataGrid.RowStyle >
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FFFFFFFF" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF0F0F0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinWidth" Value="20"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFC0C0C0"/>
<Setter Property="BorderBrush" Value="#FFC0C0C0"/>
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.user}" Binding="{Binding User}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Name}" Binding="{Binding Name}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Password}" Binding="{Binding Password}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Department}" Binding="{Binding Department}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Groups}" Binding="{Binding Groups}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Binding="{Binding Capacity}" Width="0" MaxWidth="0" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastLoginIP}" Binding="{Binding LastLoginIP}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastLoginTime}" Binding="{Binding LastLoginTime}"
Width="200" FontSize="15" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
<!--存储按钮-->
<Button Grid.Row="3" Content="存储" HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="100" FontSize="30"
Click="Button_Preservation" Margin="0,0,200,0">
</Button>
<!--删除按钮-->
<Button Grid.Row="3" Content="删除" HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="100" FontSize="30"
Click="Button_Delete" Margin="0,0,50,0">
</Button>
</Grid>
</Window>
+152
View File
@@ -0,0 +1,152 @@
using SunlightAggregationManager.View;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml.Linq;
namespace SunlightAggregationManager.UserWindow
{
/// <summary>
/// Machine.xaml 的交互逻辑
/// </summary>
public partial class User : Window
{
CheckBox[] checkBoxes = new CheckBox[99];
string[] strings = new string[8] {"修改系统设置", "修改用户设置",
"设备监控","设备控制","远程设置","远程查询","输送信息","历史查询"};
public User()
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
}
private void user_Loaded(object sender, RoutedEventArgs e)//打开页面执行
{
for (int i = 0; i < strings.Length; i++)
{
checkBoxes[i] = new CheckBox();
checkBoxes[i].Content = strings[i].ToString();
checkBoxes[i].FontSize = 20;
checkBoxes[i].Width = 200;
checkBoxes[i].Height = 50;
Capacity.Children.Add(checkBoxes[i]);
}
DataGriduser.ItemsSource = MainWindowViewModel._userData.DefaultView;
}
private void Tb_KeyFloating(object sender, TextCompositionEventArgs e)//输入事件
{
//Regex re = new Regex("[^0-9.-]+");
Regex re = new Regex(@"^[.][0-9]+$|^[0-9]*[.]{0,1}[0-9]*$");// 非负浮点数
e.Handled = !re.IsMatch(e.Text);
}
private void DataGridMac_MouseDoubleClick(object sender, MouseButtonEventArgs e)//数据表双击事件
{
string Capacity_;
int rownum = DataGriduser.SelectedIndex;//获取鼠标选中行并定义变量
if (rownum != -1)//判断鼠标定位是否有效
{
/*定位选中行及指定列单元格文本信息*/
_Name.Text = (DataGriduser.Columns[1].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();//定位第列
_User.Text = (DataGriduser.Columns[0].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();//定位第列
GROUP.Text = (DataGriduser.Columns[4].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();
Capacity_ = (DataGriduser.Columns[5].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();
_Department.Text = (DataGriduser.Columns[3].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();
Pasword.Text = (DataGriduser.Columns[2].GetCellContent(DataGriduser.Items[rownum]) as TextBlock)!.Text.Trim();
if (strings.Length > Capacity_.Length)
{
for (int i = 0; i < Capacity_.Length; i++)
{
if (Capacity_.Substring(i, 1) == "1")
{
checkBoxes[i].IsChecked = true;
}
else
{
checkBoxes[i].IsChecked = false;
}
}
}
else
{
for (int i = 0; i < strings.Length; i++)
{
if (Capacity_.Substring(i, 1) == "1")
{
checkBoxes[i].IsChecked = true;
}
else
{
checkBoxes[i].IsChecked = false;
}
}
}
}
}
private void Button_Preservation(object sender, RoutedEventArgs e)//保存按钮事件
{
Regex re_number = new Regex(@"^[0-9]+(.[0-9]{1,2})?$");//校验用正则表达式有1~2位小数的正实数
Regex re_char = new Regex(@"^[A-Za-z0-9\s@()()/+!!_-]+$");//校验用正则表达式由数字,26个英文字母,空白字符和@()()/+!!_-组成的字符串
string user = _User.Text;
string name = _Name.Text;
string password = Pasword.Text;
string Group = GROUP.Text;
string Cap = "";
string department = _Department.Text;
for (int i = 0; i < strings.Length; i++)
{
if ((bool)checkBoxes[i].IsChecked!)
{
Cap = Cap + "1";
}
else { Cap = Cap + "0"; }
}
Dictionary<string, object> USER_new = new Dictionary<string, object>();//缓存函数
USER_new.Add("User", user);
USER_new.Add("Name", name);
USER_new.Add("Password", password);
USER_new.Add("Groups", Group);
USER_new.Add("Capacity", Cap);
USER_new.Add("Department", department);
USER_new.Add("State", 0);
USER_new.Add("Enterprise", MainWindowViewModel.Enterprise);
var rowdata = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "UserID", "User='" + user + "'");
if (rowdata != null)
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + user + "'", USER_new);
}
else
{
MainWindowViewModel.Insert_Memory(MainWindowViewModel._userData, USER_new);// 执行插入
}
DataGriduser.ItemsSource = MainWindowViewModel._userData.DefaultView;
_Name.Text = null;
}
private void Button_Delete(object sender, RoutedEventArgs e)//删除按钮事件
{
try
{
MainWindowViewModel.Delete_Memory(MainWindowViewModel._userData, "User='" + _User.Text + "'");
}
catch (Exception) { }
finally
{
DataGriduser.ItemsSource = MainWindowViewModel._userData.DefaultView;
_Name.Text = null;
}
}
}
}
@@ -1,11 +1,11 @@
<Window x:Class="SunlightAggregationManager.Window.UserSet"
<Window x:Class="SunlightAggregationManager.UserWindow.UserSet"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SunlightAggregationManager.Window"
xmlns:local="clr-namespace:SunlightAggregationManager.UserWindow"
mc:Ignorable="d"
Title="UserSet" Height="450" Width="800" WindowStyle="None" >
Title="UserSet" Height="450" Width="800">
<Grid>
</Grid>
@@ -10,14 +10,14 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace SunlightAggregationManager.Window
namespace SunlightAggregationManager.UserWindow
{
/// <summary>
/// UserSet.xaml 的交互逻辑
/// </summary>
public partial class UserSet : Window
{
public UserSet()
public UserSet(string id)
{
InitializeComponent();
}
+20
View File
@@ -0,0 +1,20 @@
<UserControl x:Class="SunlightAggregationManager.View.ActionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SunlightAggregationManager.View"
mc:Ignorable="d"
Loaded="UserControl_Loaded"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<DataGrid x:Name="CurrentData"
IsReadOnly="True"
AutoGenerateColumns="True"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel" />
</Grid>
</UserControl>
+36
View File
@@ -0,0 +1,36 @@
using SunlightAggregationManager.UserClass;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SunlightAggregationManager.View
{
/// <summary>
/// ActionPage.xaml 的交互逻辑
/// </summary>
public partial class ActionPage : UserControl
{
public ActionPage()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
var data =MainWindowViewModel.SQLiteHelpers.ExecuteDataSet(
"select * from ActionLog order by Time DESC", null)?.Tables[0] ?? new DataTable();
CurrentData.ItemsSource=data.AsDataView();
}
}
}
+12
View File
@@ -0,0 +1,12 @@
<UserControl x:Class="SunlightAggregationManager.View.ExtendPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SunlightAggregationManager.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SunlightAggregationManager.View
{
/// <summary>
/// ExtendPage.xaml 的交互逻辑
/// </summary>
public partial class ExtendPage : UserControl
{
public ExtendPage()
{
InitializeComponent();
}
}
}
+95
View File
@@ -0,0 +1,95 @@
<UserControl x:Class="SunlightAggregationManager.View.MachinePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SunlightAggregationManager.View"
xmlns:ConvertMoels="clr-namespace:SunlightAggregationManager.ConvertMoels"
xmlns:lang="clr-namespace:SunlightAggregationManager"
xmlns:viewmodel="clr-namespace:SunlightAggregationManager.ViewModel"
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<DataGrid x:Name="DataGridmachines"
ItemsSource="{Binding Machines.DefaultView}"
SelectionChanged="DataGridmachines_SelectionChanged"
SelectionMode="Single"
AlternationCount="2"
IsReadOnly="True"
FontSize="26"
Margin="5,5,5,5"
AutoGenerateColumns="False"
MinColumnWidth="30"
HorizontalGridLinesBrush="#FFC9C9C9"
VerticalGridLinesBrush="#FFC9C9C9"
GridLinesVisibility="All"
BorderBrush="#CCCCCC"
BorderThickness="1,1,1,1"
ColumnHeaderHeight="40"
HorizontalContentAlignment="Right"
CanUserReorderColumns="False"
VerticalContentAlignment="Center">
<DataGrid.RowStyle >
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF0F0F0" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinWidth" Value="20"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFC0C0C0"/>
<Setter Property="BorderBrush" Value="#FFC0C0C0"/>
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="{x:Static lang:ResourceLanguage.information}" Click="MenuItem_information"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<!--列信息绑定-->
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="200" FontSize="26"
Binding="{Binding Name}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.machine}" Width="200" FontSize="26"
Binding="{Binding Machine}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.state}" Width="150" FontSize="26"
Binding="{Binding State}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Mode}" Width="150" FontSize="26"
Binding="{Binding Model}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="A" Width="150" FontSize="26"
Binding="{Binding ModelA}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="B" Width="150" FontSize="26"
Binding="{Binding ModelB}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="C" Width="150" FontSize="26"
Binding="{Binding ModelC}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="D" Width="150" FontSize="26"
Binding="{Binding ModelD}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="E" Width="150" FontSize="26"
Binding="{Binding ModelE}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="F" Width="150" FontSize="26"
Binding="{Binding ModelF}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="*" FontSize="26"
Binding="{Binding Information}" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
+49
View File
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SunlightAggregationManager.UserWindow;
namespace SunlightAggregationManager.View
{
/// <summary>
/// MachinePage.xaml 的交互逻辑
/// </summary>
public partial class MachinePage : UserControl
{
public MachinePage()
{
InitializeComponent();
}
private string id = "";
private void DataGridmachines_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int rownum = DataGridmachines.SelectedIndex;//获取鼠标选中行并定义变量
if (rownum != -1)//判断鼠标定位是否有效
{
var row_ = DataGridmachines.Columns[0].GetCellContent(DataGridmachines.Items[rownum]);
if (row_ is TextBlock textBlock)
{
id = textBlock.Text;//定位第0列,
}
}
}
private void MenuItem_information(object sender, RoutedEventArgs e)
{
MachineSet machineSet = new MachineSet();
machineSet.Show();
}
}
}
+72
View File
@@ -0,0 +1,72 @@
<UserControl x:Class="SunlightAggregationManager.View.ServicePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SunlightAggregationManager.View"
xmlns:viewmodel="clr-namespace:SunlightAggregationManager.ViewModel"
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<DataGrid x:Name="DataGridmachinesdata"
ItemsSource="{Binding Service.DefaultView}"
SelectionMode="Single"
AlternationCount="2"
IsReadOnly="True"
FontSize="26"
Margin="5,5,5,5"
AutoGenerateColumns="False"
MinColumnWidth="30"
HorizontalGridLinesBrush="#FFC9C9C9"
VerticalGridLinesBrush="#FFC9C9C9"
GridLinesVisibility="All"
BorderBrush="#CCCCCC"
BorderThickness="1,1,1,1"
ColumnHeaderHeight="40"
HorizontalContentAlignment="Right"
CanUserReorderColumns="False"
VerticalContentAlignment="Center">
<DataGrid.RowStyle >
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF0F0F0" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinWidth" Value="20"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFC0C0C0"/>
<Setter Property="BorderBrush" Value="#FFC0C0C0"/>
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<!--列信息绑定-->
<DataGridTextColumn Header="ID" Width="100" FontSize="26"
Binding="{Binding ID}" MaxWidth="100" MinWidth="100" CanUserReorder="False"/>
<DataGridTextColumn Header="Status" Width="200" FontSize="26"
Binding="{Binding Status}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="Service" Width="*" FontSize="26"
Binding="{Binding Service}" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
+27
View File
@@ -0,0 +1,27 @@
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SunlightAggregationManager.View
{
/// <summary>
/// ServicePage.xaml 的交互逻辑
/// </summary>
public partial class ServicePage : UserControl
{
public ServicePage()
{
InitializeComponent();
}
}
}
-1
View File
@@ -24,7 +24,6 @@
<Button Content="{x:Static lang:ResourceLanguage.Test}" HorizontalAlignment="Left" Height="35" Margin="370,335,0,0" VerticalAlignment="Top" Width="80" Click="test_Click"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,335,0,0" x:Name="textlog" TextWrapping="Wrap" Text="------------" VerticalAlignment="Top" Width="140" FontSize="20"/>
<CheckBox x:Name="EnableTCP" Content="{x:Static lang:ResourceLanguage.EnableTCP}" HorizontalAlignment="Left" Margin="600,10,0,0" VerticalAlignment="Top" Height="40" Width="300" FontSize="24"
Checked="EnableTCP_Checked" Unchecked="EnableTCP_Unchecked"/>
<CheckBox x:Name="EnableHTTP" Content="{x:Static lang:ResourceLanguage.EnableHTTP}" HorizontalAlignment="Left" Margin="600,60,0,0" VerticalAlignment="Top" Height="40" Width="300" FontSize="24"
+29
View File
@@ -39,6 +39,35 @@ namespace SunlightAggregationManager.View
TEXT_SQMOD.Text = Configini.IniReadvalue("SQL_SERVER", "SQL3");
TEXT_SQLUSER.Text = Configini.IniReadvalue("SQL_SERVER", "SQL4");
TEXT_SQLPASWORD.Text = Configini.IniReadvalue("SQL_SERVER", "SQL5");
var tcp = Configini.IniReadvalue("NETWORK", "TCP");
if (tcp == "1")
{
EnableTCP.IsChecked = true;
}
else
{
EnableTCP.IsChecked = false;
}
var http = Configini.IniReadvalue("NETWORK", "HTTP");
if (http == "1")
{
EnableHTTP.IsChecked = true;
}
else
{
EnableHTTP.IsChecked = false;
}
var tls = Configini.IniReadvalue("NETWORK", "TLS");
if (tls == "1")
{
EnableTLS.IsChecked = true;
}
else
{
EnableTLS.IsChecked = false;
}
}
catch (Exception) { }
}
+1 -1
View File
@@ -105,7 +105,7 @@
Binding="{Binding LastOfflineTime}" MinWidth="300" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Groups}" Width="200" FontSize="26"
Binding="{Binding Groups}" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="*" FontSize="26"
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="auto" FontSize="26"
Binding="{Binding Note}" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
+6 -10
View File
@@ -1,4 +1,5 @@
using SunlightAggregationManager.UserClass;
using SunlightAggregationManager.UserWindow;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
@@ -40,17 +41,15 @@ namespace SunlightAggregationManager.View
if (row_ is TextBlock textBlock)
{
user_id = textBlock.Text;//定位第0列,
}
}
}
}
}
private void MenuItem_Information(object sender, RoutedEventArgs e)//信息
{
User userSet =new User();
userSet.Show();
}
private async void MenuItem_Offine(object sender, RoutedEventArgs e)//下线
@@ -82,9 +81,6 @@ namespace SunlightAggregationManager.View
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + user_id + "'", "99", "State");
}
}
}
+7 -3
View File
@@ -1,8 +1,10 @@
using Net.Codecrete.QrCodeGenerator;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Windows;
using System.Windows.Controls;
@@ -94,9 +96,11 @@ namespace SunlightAggregationManager.View
}
private void imgQR_Loaded(object sender, RoutedEventArgs e)
{
string text_APP = "TEST"; // 要生成二维码的内容
string text_LINK = Configini.IniReadvalue("SYS", "LINK"); // 要生成二维码的内容
{
string text_APP = "TEST"; //
string text_LINK = MainWindowViewModel.MachineIP + ":"+ MainWindowViewModel.MachineIPP1 +
"," + MainWindowViewModel.SERVERIP + ":7791/"+ MainWindowViewModel.Enterprise;
// 要生成二维码的内容
imgQR_CREATE(text_APP, imgQR_app);
imgQR_CREATE(text_LINK, imgQR_link);
+252 -26
View File
@@ -2,6 +2,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SunlightAggregationManager.UserClass;
using SunlightAggregationManager.View;
using System;
using System.Collections.Generic;
using System.Data;
@@ -10,6 +11,7 @@ using System.Reflection.PortableExecutable;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Xml.Linq;
@@ -25,19 +27,34 @@ namespace SunlightAggregationManager.ViewModel
public static string SQLUSER = "";
public static string SQLPASWORD = "";
public static string MachineName = "SERVER";
public static string MachineVer = "1.0.0";
public static string MachineIP = "";
public static int MachineIPP1 = 7789;
public static int MachineIPP2 = 7790;
public static int MachineHTTPP = 7791;
public static string Enterprise = "";
public static string TCP_E = "0";
public static string HTTP_E = "0";
public static string TLS_E = "0";
public static string SERVERIP = "";
public static string SERVERNAME = "";
public static string SERVERUSER = "";
public static string SERRVERPASWORD = "";
public static int ChemicalNumber, DyeMeasurementNumber, DyeDissolveNumber, PowderNumber;
private static Timer? _timer;
public static DataTable ChemicalStatistics = new DataTable();
public static DataTable DBC_Machines = new DataTable();
public static DataBase dataBase = new DataBase();
public static UserClass.SqliteHelper SQLiteHelpers = null!; //定义数据库
private readonly string DBAddress = Environment.CurrentDirectory + "\\DataBase\\SunlightAggregationManager.db"; //数据库路径
public static DataTable ActionLog = new DataTable();
[ObservableProperty]
public static DataTable _machines = new DataTable(); //设备表缓存
[ObservableProperty]
public static DataTable _userData = new DataTable();
[ObservableProperty]
public static DataTable _service = new DataTable();
public MainWindowViewModel()
{
@@ -46,12 +63,15 @@ namespace SunlightAggregationManager.ViewModel
SQMOD = Configini.IniReadvalue("SQL_SERVER", "SQL3");
SQLUSER = Configini.IniReadvalue("SQL_SERVER", "SQL4");
SQLPASWORD = Configini.IniReadvalue("SQL_SERVER", "SQL5");
MachineName = Configini.IniReadvalue("SYS", "Name");
Enterprise = Configini.IniReadvalue("SYS", "Enterprise");
TCP_E = Configini.IniReadvalue("NETWORK", "TCP");
HTTP_E = Configini.IniReadvalue("NETWORK", "HTTP");
TLS_E = Configini.IniReadvalue("NETWORK", "TLS");
SERVERIP = Configini.IniReadvalue("SERVER", "SERVERIP");
SERVERNAME = Configini.IniReadvalue("SERVER", "SERVERNAME");
SERVERUSER = Configini.IniReadvalue("SERVER", "SERVERUSER");
SERRVERPASWORD = Configini.IniReadvalue("SERVER", "SERRVERPASWORD");
//本地数据库(sqlite)
try
@@ -62,11 +82,6 @@ namespace SunlightAggregationManager.ViewModel
Machines = SQLiteHelpers.ExecuteDataSet("select * from Machines order by ID asc", null)?.Tables[0] ?? new DataTable();
ActionLog = (SQLiteHelpers.ExecuteDataSet("select * from ActionLog", null)?.Tables[0] ?? new DataTable()).Clone();
// SQLiteHelpers.Close();
if (UserData.Columns.Contains("UserID"))
{
UserData.Columns.Remove("UserID");
}
DataRow[] dataRows = UserData.Select("State<90");
foreach (DataRow row in dataRows)
{
@@ -74,38 +89,125 @@ namespace SunlightAggregationManager.ViewModel
row["LinkID"] = 0;
}
Machines.RowChanged += Machines_Updata;
Machines.RowDeleting += Machines_Updata;
UserData.RowChanged += UserData_Updata;//注册userdata表更新事件
UserData.RowDeleting += UserData_Updata;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
//运行数据库
DataBase dataBase = new DataBase();
dataBase.Config(SQLIP, SQLNAME, SQMOD, SQLUSER, SQLPASWORD);
//服务信息表
//DataTable Service = new DataTable();
Service.BeginInit();
Service.Columns.Add("ID", typeof(int));
Service.Columns.Add("Status", typeof(string));
Service.Columns.Add("Service", typeof(string));
//运行数据库
Service.Rows.Add(0, "RUN", "SQL_DataBase_Link");
dataBase.Config(SQLIP, SQLNAME, SQMOD, SQLUSER, SQLPASWORD);
if (TCP_E == "1")//启动tcp(内网直连)
{
int P1, P2;
try
{
P1 =int.Parse( Configini.IniReadvalue("NETWORK", "TCP_PORT1"));
MachineIPP1 = int.Parse(Configini.IniReadvalue("NETWORK", "TCP_PORT1"));
}
catch (Exception) { P1 = 7789; }
catch (Exception) { MachineIPP1 = 7789; }
try
{
P2 = int.Parse(Configini.IniReadvalue("NETWORK", "TCP_PORT2"));
MachineIPP2 = int.Parse(Configini.IniReadvalue("NETWORK", "TCP_PORT2"));
}
catch (Exception) { P2 = 7790; }
catch (Exception) { MachineIPP2 = 7790; }
using var _ = AsyncTcpServer.TcpMain(P1,P2);
Service.Rows.Add(1, "RUN", "TCP");
AsyncTcpServer.Configuration(MachineIPP1, MachineIPP2);
}
else
{
Service.Rows.Add(1, "STOP", "TCP");
}
if (HTTP_E == "1")//启动tcp(内网直连)
{
try
{
MachineHTTPP = int.Parse(Configini.IniReadvalue("NETWORK", "HTTP_PORT"));
}
catch (Exception) { MachineHTTPP = 7791; }
Service.Rows.Add(2, "RUN", "HTTP");
AsyncHttpServer.Configuration(MachineHTTPP);
}
else
{
Service.Rows.Add(2, "STOP", "HTTP");
}
//获取当前IP
MachineIP = GetLocalIP.GetLocalIPv4Address().ToString();
Console.WriteLine(MachineIP);
//连接sunlight服务器
Service.Rows.Add(3, "RUN", "Sunlight_Server_Link");
AsyncTcpClient.Configuration(SERVERIP + ":7795", SERVERNAME, SERVERUSER, SERRVERPASWORD);
Service.EndInit();
_timer = new Timer(TimeTask, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30));
}
//Machines操作数据库
private void Machines_Updata(object sender, DataRowChangeEventArgs e)
{
Dictionary<string, object> row_entity = new Dictionary<string, object>();
Dictionary<string, object> userlog = new Dictionary<string, object>();
if (e.Action == DataRowAction.Change)
{
//修改的行回传
foreach (DataColumn col in Machines.Columns)
{
row_entity.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
if (ActionLog.Columns.Contains(col.ColumnName))//添加到行为记录表
{
userlog.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
}
}
SQLiteHelpers.Update("Machines", row_entity, "ID='" + e.Row.Field<object>("ID") + "'", null);
userlog.Add("Action", "Command");
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
userlog.Add("Note", "Machine = " + e.Row.Field<object>("Machine"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
if (e.Action == DataRowAction.Add)
{
//添加的行回传
foreach (DataColumn col in Machines.Columns)
{
row_entity.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
}
SQLiteHelpers.InsertData("Machines", row_entity);
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
userlog.Add("Action", "New Account");
userlog.Add("Note", "Machine = " + e.Row.Field<object>("Machine"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
if (e.Action == DataRowAction.Delete)
{
//删除的行回传
SQLiteHelpers.Delete("Machines", "ID='" + e.Row.Field<object>("ID") + "'", null);
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
userlog.Add("Action", "Delete Account");
userlog.Add("Note", "Machine = " + e.Row.Field<object>("Machine"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
}
//UserData操作数据库
private void UserData_Updata(object sender, DataRowChangeEventArgs e)
{
Dictionary<string, object> row_entity = new Dictionary<string, object>();
@@ -159,21 +261,82 @@ namespace SunlightAggregationManager.ViewModel
SQLiteHelpers.InsertData("ActionLog", userlog);
}
}
//数据表操作
public static void Insert_Memory(DataTable DB, Dictionary<string, object> Value)//插入数据
{
try
{
lock (DB)
{
DataRow drEmployee = DB.NewRow();
drEmployee.BeginEdit();
public static object? Selet_Memory(DataTable DB, string name, string? key)//查询
foreach (KeyValuePair<string, object> kvp in Value)
{
drEmployee[kvp.Key] = kvp.Value;
}
drEmployee.EndEdit();
DB.Rows.Add(drEmployee);
drEmployee.AcceptChanges();
// drEmployee.ClearErrors();
}
}
catch (Exception ex)
{
Console.WriteLine("Insert_Row:" + ex.ToString());
}
}
public static void Delete_Memory(DataTable DB, string? key)//删除数据
{
try
{
lock (DB)
{
DataRow drEmployee = DB.Select(key).First();
object? index = drEmployee.Field<object>(name);
return index;
drEmployee.Delete();
}
}
catch (Exception ex)
{
Console.WriteLine("SDTD:" + ex.ToString());
Console.WriteLine("Delete_Row:" + ex.ToString());
}
}
public static DataRow? Selet_Row(DataTable DB, string? key)//查询
{
try
{
lock (DB)
{
DataRow drEmployee = DB.Select(key).First();
return drEmployee;
}
}
catch (Exception ex)
{
Console.WriteLine("Selet_Row:" + ex.ToString());
return null;
}
}
public static object? Selet_Memory(DataTable DB, string name, string? key)//查询
{
try
{
lock (DB)
{
DataRow[] dataRows = DB.Select(key);
if (dataRows.Count() > 0)
{
DataRow drEmployee = dataRows.First();
object? index = drEmployee.Field<object>(name);
return index;
}
else { return null; }
}
}
catch (Exception ex)
{
Console.WriteLine("Selet_Memory:" + ex.ToString());
return null;
}
}
@@ -227,5 +390,68 @@ namespace SunlightAggregationManager.ViewModel
Console.WriteLine("SDTD:" + ex.ToString());
}
}
private static int EXTime = 120;
private static async void TimeTask(object? state)
{
if (EXTime == 120)//1小时
{
EXTask();//统计配送消息
EXTime = 0;
}
DBC_Machines = await dataBase.ExecuteQueryAsync("SELECT *FROM [BatchDyeingCentral].[dbo].[Machines]");
EXTime++;
}
private static async void EXTask()
{
try
{
string DyelotsBulkedRecipe_sql = "SELECT [ProductCode],[ProductName],SUM(DispenseGrams)" +
"as TotalDispenseGrams FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] " +
"where DispenseEndTime > '" + DateTime.Now.ToString("yyyy-MM-dd") + "' AND DispenseEndTime < '" +
DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "' GROUP BY [ProductCode],[ProductName] " +
"ORDER BY TotalDispenseGrams DESC ";
string Dye_sql =
"SELECT [Dyelot],[ReDye],[StepNumber] FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] " +
"where ((DispenseEndTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") + "' AND DispenseEndTime < '" +
DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "') OR (DispenseTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") +
"' AND DispenseTime < '" + DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "')) " +
"AND ProductType = 1 GROUP BY [Dyelot],[ReDye],[StepNumber];";
string Chemical_sql =
"SELECT [Dyelot],[ReDye],[StepNumber] FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] " +
"where ((DispenseEndTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") + "' AND DispenseEndTime < '" +
DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "') OR (DispenseTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") +
"' AND DispenseTime < '" + DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "')) " +
"AND ProductType = 2 GROUP BY [Dyelot],[ReDye],[StepNumber];";
string Powder_sql =
"SELECT [Dyelot],[ReDye],[StepNumber] FROM [BatchDyeingCentral].[dbo].[DyelotsBulkedRecipe] " +
"where ((DispenseEndTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") + "' AND DispenseEndTime < '" +
DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "') OR (DispenseTime >= '" + DateTime.Now.ToString("yyyy-MM-dd") +
"' AND DispenseTime < '" + DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "')) " +
"AND ProductType = 3 GROUP BY [Dyelot],[ReDye],[StepNumber];";
string DyeDissolve =
"SELECT *FROM [BatchDyeingCentral].[dbo].[DyeSolutionHistory] " + "where DispenseEndTime >= '" +
DateTime.Now.ToString("yyyy-MM-dd") + "' AND DispenseEndTime < '" + DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") + "'";
ChemicalStatistics = await dataBase.ExecuteQueryAsync(DyelotsBulkedRecipe_sql);
DyeMeasurementNumber = await dataBase.ExecuteQueryAsyncCount(Dye_sql);
ChemicalNumber = await dataBase.ExecuteQueryAsyncCount(Chemical_sql);
PowderNumber = await dataBase.ExecuteQueryAsyncCount(Powder_sql);
DyeDissolveNumber = await dataBase.ExecuteQueryAsyncCount(DyeDissolve);
}
catch (Exception ex)
{//错误处理
LogGing.ERRDATA(ex);
Console.WriteLine(ex.ToString());
}
finally {
Console.WriteLine("当日染料称量["+ DyeMeasurementNumber+ "]染料输送["+ DyeDissolveNumber + "]" +
"助剂输送["+ ChemicalNumber + "]粉体输送["+ PowderNumber + "]");
}
}
}
}
}