diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c5564f..53daf7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,4 +76,11 @@ 3. 修正windows下的配置文件include问题 4. 支持linux远程桌面 -**注:linux受控端需使用np-cli.vnc程序进行启动,且目前无法以systemd等方式运行** \ No newline at end of file +**注:linux受控端需使用np-cli.vnc程序进行启动,且目前无法以systemd等系统服务方式运行** + +# v0.7.3 + +1. vnc支持\键 +2. 全面迁移到[https://github.com/lwch/rdesktop](https://github.com/lwch/rdesktop),并去除robotgo库的依赖 +3. linux下统一到同一个可执行文件,并支持systemd方式启动 +4. 简化部署流程 \ No newline at end of file diff --git a/build b/build index 0880598..5d22e0a 100755 --- a/build +++ b/build @@ -1,6 +1,6 @@ #!/bin/sh -VERSION=0.7.2 +VERSION=0.7.3 DOCKER_BUILDKIT=1 docker build -t natpass -f contrib/build/Dockerfile . docker run --rm \ diff --git a/build_all b/build_all index a7c79bd..73d210c 100755 --- a/build_all +++ b/build_all @@ -1,6 +1,6 @@ #!/bin/sh -VERSION=0.7.2 +VERSION=0.7.3 DOCKER_BUILDKIT=1 docker build -t natpass -f contrib/build/Dockerfile . docker run --rm \ diff --git a/code/client/global/conf.go b/code/client/global/conf.go index 14cbf44..7c11535 100644 --- a/code/client/global/conf.go +++ b/code/client/global/conf.go @@ -4,6 +4,8 @@ import ( "crypto/md5" "fmt" "natpass/code/utils" + "os" + "path/filepath" "time" "github.com/lwch/runtime" @@ -82,6 +84,11 @@ func LoadConf(dir string) *Configure { if cfg.Link.WriteTimeout <= 0 { cfg.Link.WriteTimeout = 5 * time.Second } + if !filepath.IsAbs(cfg.Log.Dir) { + dir, err := os.Executable() + runtime.Assert(err) + cfg.Log.Dir = filepath.Join(filepath.Dir(dir), cfg.Log.Dir) + } return &Configure{ ID: cfg.ID, Server: cfg.Server, diff --git a/code/client/main.go b/code/client/main.go index 3f67044..70fa808 100644 --- a/code/client/main.go +++ b/code/client/main.go @@ -99,6 +99,7 @@ func main() { switch *act { case "install": runtime.Assert(sv.Install()) + utils.BuildLogDir(cfg.LogDir, *user) case "uninstall": runtime.Assert(sv.Uninstall()) default: diff --git a/code/client/rule/vnc/worker/event.go b/code/client/rule/vnc/worker/event.go index 471d360..d20c9b7 100644 --- a/code/client/rule/vnc/worker/event.go +++ b/code/client/rule/vnc/worker/event.go @@ -1,22 +1,100 @@ -//go:build !vnc -// +build !vnc - package worker import ( "natpass/code/client/rule/vnc/vncnetwork" "github.com/gorilla/websocket" + "github.com/lwch/logging" + "github.com/lwch/rdesktop" + "google.golang.org/protobuf/proto" ) -func runMouse(data *vncnetwork.MouseData) { +func (worker *Worker) runMouse(data *vncnetwork.MouseData) { + detach, err := attachDesktop() + if err != nil { + logging.Error("attach desktop: %v", err) + return + } + defer detach() + worker.cli.MouseMove(int(data.GetX()), int(data.GetY())) + var button rdesktop.MouseButton + switch data.GetBtn() { + case vncnetwork.MouseData_left: + button = rdesktop.MouseLeft + case vncnetwork.MouseData_right: + button = rdesktop.MouseRight + case vncnetwork.MouseData_middle: + button = rdesktop.MouseMiddle + } + switch data.GetType() { + case vncnetwork.Status_down: + worker.cli.ToggleMouse(button, true) + case vncnetwork.Status_up: + worker.cli.ToggleMouse(button, false) + } } -func runKeyboard(data *vncnetwork.KeyboardData) { +func (worker *Worker) runKeyboard(data *vncnetwork.KeyboardData) { + detach, err := attachDesktop() + if err != nil { + logging.Error("attach desktop: %v", err) + return + } + defer detach() + switch data.Type { + case vncnetwork.Status_down: + worker.cli.ToggleKey(data.Key, true) + case vncnetwork.Status_up: + worker.cli.ToggleKey(data.Key, false) + } } -func runScroll(data *vncnetwork.ScrollData) { +func (worker *Worker) runScroll(data *vncnetwork.ScrollData) { + detach, err := attachDesktop() + if err != nil { + logging.Error("attach desktop: %v", err) + return + } + defer detach() + worker.cli.Scroll(int(data.X), int(data.Y)) } -func runClipboard(conn *websocket.Conn, data *vncnetwork.ClipboardData) { +func (worker *Worker) runClipboard(conn *websocket.Conn, data *vncnetwork.ClipboardData) { + detach, err := attachDesktop() + if err != nil { + logging.Error("attach desktop: %v", err) + return + } + defer detach() + if data.GetSet() { + worker.setClipboard(data) + } else { + worker.getClipboard(conn) + } +} + +func (worker *Worker) setClipboard(data *vncnetwork.ClipboardData) { + switch data.GetXType() { + case vncnetwork.ClipboardData_file: + case vncnetwork.ClipboardData_image: + case vncnetwork.ClipboardData_text: + worker.cli.ClipboardSet(data.GetData()) + } +} + +func (worker *Worker) getClipboard(conn *websocket.Conn) { + data, _ := worker.cli.ClipboardGet() + var msg vncnetwork.VncMsg + msg.XType = vncnetwork.VncMsg_clipboard_event + msg.Payload = &vncnetwork.VncMsg_Clipboard{ + Clipboard: &vncnetwork.ClipboardData{ + Set: true, + XType: vncnetwork.ClipboardData_text, + Payload: &vncnetwork.ClipboardData_Data{ + Data: data, + }, + }, + } + enc, _ := proto.Marshal(&msg) + conn.WriteMessage(websocket.BinaryMessage, enc) } diff --git a/code/client/rule/vnc/worker/event_auto.go b/code/client/rule/vnc/worker/event_auto.go deleted file mode 100644 index bc4ed4e..0000000 --- a/code/client/rule/vnc/worker/event_auto.go +++ /dev/null @@ -1,103 +0,0 @@ -//go:build vnc -// +build vnc - -package worker - -import ( - "natpass/code/client/rule/vnc/vncnetwork" - - "github.com/go-vgo/robotgo" - "github.com/gorilla/websocket" - "github.com/lwch/logging" - "google.golang.org/protobuf/proto" -) - -func runMouse(data *vncnetwork.MouseData) { - detach, err := attachDesktop() - if err != nil { - logging.Error("attach desktop: %v", err) - return - } - defer detach() - robotgo.MoveMouse(int(data.GetX()), int(data.GetY())) - var key string - switch data.GetBtn() { - case vncnetwork.MouseData_left: - key = "left" - case vncnetwork.MouseData_right: - key = "right" - case vncnetwork.MouseData_middle: - key = "center" - } - switch data.GetType() { - case vncnetwork.Status_down: - robotgo.MouseToggle("down", key) - case vncnetwork.Status_up: - robotgo.MouseToggle("up", key) - } -} - -func runKeyboard(data *vncnetwork.KeyboardData) { - detach, err := attachDesktop() - if err != nil { - logging.Error("attach desktop: %v", err) - return - } - defer detach() - switch data.Type { - case vncnetwork.Status_down: - robotgo.KeyToggle(data.Key, "down") - case vncnetwork.Status_up: - robotgo.KeyToggle(data.Key, "up") - } -} - -func runScroll(data *vncnetwork.ScrollData) { - detach, err := attachDesktop() - if err != nil { - logging.Error("attach desktop: %v", err) - return - } - defer detach() - robotgo.Scroll(int(data.X), int(data.Y), 1) -} - -func runClipboard(conn *websocket.Conn, data *vncnetwork.ClipboardData) { - detach, err := attachDesktop() - if err != nil { - logging.Error("attach desktop: %v", err) - return - } - defer detach() - if data.GetSet() { - setClipboard(data) - } else { - getClipboard(conn) - } -} - -func setClipboard(data *vncnetwork.ClipboardData) { - switch data.GetXType() { - case vncnetwork.ClipboardData_file: - case vncnetwork.ClipboardData_image: - case vncnetwork.ClipboardData_text: - robotgo.WriteAll(data.GetData()) - } -} - -func getClipboard(conn *websocket.Conn) { - data, _ := robotgo.ReadAll() - var msg vncnetwork.VncMsg - msg.XType = vncnetwork.VncMsg_clipboard_event - msg.Payload = &vncnetwork.VncMsg_Clipboard{ - Clipboard: &vncnetwork.ClipboardData{ - Set: true, - XType: vncnetwork.ClipboardData_text, - Payload: &vncnetwork.ClipboardData_Data{ - Data: data, - }, - }, - } - enc, _ := proto.Marshal(&msg) - conn.WriteMessage(websocket.BinaryMessage, enc) -} diff --git a/code/client/rule/vnc/worker/worker.go b/code/client/rule/vnc/worker/worker.go index 9463750..e46c4c1 100644 --- a/code/client/rule/vnc/worker/worker.go +++ b/code/client/rule/vnc/worker/worker.go @@ -23,6 +23,7 @@ func NewWorker(showCursor bool) *Worker { worker := &Worker{} cli, err := rdesktop.New() if err != nil { + logging.Error("create rdesktop: %v", err) return nil } worker.cli = cli @@ -57,15 +58,15 @@ func (worker *Worker) Do(conn *websocket.Conn) { enc, _ := proto.Marshal(&msg) conn.WriteMessage(websocket.BinaryMessage, enc) case vncnetwork.VncMsg_mouse_event: - runMouse(msg.GetMouse()) + worker.runMouse(msg.GetMouse()) case vncnetwork.VncMsg_keyboard_event: - runKeyboard(msg.GetKeyboard()) + worker.runKeyboard(msg.GetKeyboard()) case vncnetwork.VncMsg_set_cursor: worker.cli.ShowCursor(msg.GetShowCursor()) case vncnetwork.VncMsg_scroll_event: - runScroll(msg.GetScroll()) + worker.runScroll(msg.GetScroll()) case vncnetwork.VncMsg_clipboard_event: - runClipboard(conn, msg.GetClipboard()) + worker.runClipboard(conn, msg.GetClipboard()) } } } diff --git a/code/server/global/conf.go b/code/server/global/conf.go index 7dfde98..7ddba0d 100644 --- a/code/server/global/conf.go +++ b/code/server/global/conf.go @@ -3,6 +3,8 @@ package global import ( "crypto/md5" "natpass/code/utils" + "os" + "path/filepath" "time" "github.com/lwch/runtime" @@ -42,6 +44,11 @@ func LoadConf(dir string) *Configure { } `yaml:"tls"` } runtime.Assert(yaml.Decode(dir, &cfg)) + if !filepath.IsAbs(cfg.Log.Dir) { + dir, err := os.Executable() + runtime.Assert(err) + cfg.Log.Dir = filepath.Join(filepath.Dir(dir), cfg.Log.Dir) + } return &Configure{ Listen: cfg.Listen, Enc: md5.Sum([]byte(cfg.Secret)), diff --git a/code/server/main.go b/code/server/main.go index edc5ffe..efee3d4 100644 --- a/code/server/main.go +++ b/code/server/main.go @@ -6,6 +6,7 @@ import ( "fmt" "natpass/code/server/global" "natpass/code/server/handler" + "natpass/code/utils" "net" "os" "path/filepath" @@ -102,6 +103,7 @@ func main() { switch *act { case "install": runtime.Assert(sv.Install()) + utils.BuildLogDir(cfg.LogDir, *user) case "uninstall": runtime.Assert(sv.Uninstall()) default: diff --git a/code/utils/utils.go b/code/utils/utils.go new file mode 100644 index 0000000..e263e2e --- /dev/null +++ b/code/utils/utils.go @@ -0,0 +1,21 @@ +package utils + +import ( + "os" + "os/user" + "strconv" + + "github.com/lwch/runtime" +) + +// BuildLogDir mkdir for log and chown +func BuildLogDir(dir, u string) { + runtime.Assert(os.MkdirAll(dir, 0755)) + if len(u) > 0 { + us, err := user.Lookup(u) + runtime.Assert(err) + uid, _ := strconv.ParseInt(us.Uid, 10, 64) + gid, _ := strconv.ParseInt(us.Gid, 10, 64) + runtime.Assert(os.Chown(dir, int(uid), int(gid))) + } +} diff --git a/conf/client.yaml b/conf/client.yaml index 43738c9..ce5915b 100644 --- a/conf/client.yaml +++ b/conf/client.yaml @@ -4,6 +4,6 @@ dashboard: # web面板 enabled: true # 是否开放dashboard listen: 0.0.0.0 # 监听地址 port: 8080 # 监听端口号 -#include conf.d/*.yaml +#include common.yaml rules: # rule列表 #include rule.d/*.yaml \ No newline at end of file diff --git a/conf/common.yaml b/conf/common.yaml new file mode 100644 index 0000000..064d65f --- /dev/null +++ b/conf/common.yaml @@ -0,0 +1,9 @@ +secret: 0123456789 # 预共享密钥,否则握手失败 +link: + connections: 3 # 连接数,仅client有效 + read_timeout: 1s # 读取数据包超时时间 + write_timeout: 1s # 发送数据包超时时间 +log: + dir: ./logs # 路径,相对于可执行文件所在目录的相对路径 + size: 50M # 单个文件大小 + rotate: 7 # 保留数量 \ No newline at end of file diff --git a/conf/conf.d/conn.yaml b/conf/conf.d/conn.yaml deleted file mode 100644 index c1eb316..0000000 --- a/conf/conf.d/conn.yaml +++ /dev/null @@ -1,5 +0,0 @@ -secret: 0123456789 # 预共享密钥,否则握手失败 -link: - connections: 3 # 连接数,仅client有效 - read_timeout: 1s # 读取数据包超时时间 - write_timeout: 1s # 发送数据包超时时间 \ No newline at end of file diff --git a/conf/conf.d/log.yaml b/conf/conf.d/log.yaml deleted file mode 100644 index 836bfd7..0000000 --- a/conf/conf.d/log.yaml +++ /dev/null @@ -1,4 +0,0 @@ -log: - dir: ./logs # 路径 - size: 50M # 单个文件大小 - rotate: 7 # 保留数量 \ No newline at end of file diff --git a/conf/server.yaml b/conf/server.yaml index 36a9d5c..051eb90 100644 --- a/conf/server.yaml +++ b/conf/server.yaml @@ -1,5 +1,5 @@ listen: 6154 # 监听端口号 -#include conf.d/*.yaml +#include common.yaml tls: key: /dir/to/tls/key/file # tls密钥 crt: /dir/to/tls/crt/file # tls证书 \ No newline at end of file diff --git a/contrib/build/Dockerfile b/contrib/build/Dockerfile index 6ad67d3..e08fb1f 100644 --- a/contrib/build/Dockerfile +++ b/contrib/build/Dockerfile @@ -1,6 +1,6 @@ ARG APT_MIRROR=mirrors.ustc.edu.cn ARG LIBPNG_VERSION=1.6.37 -ARG GO_VERSION=1.17.4 +ARG GO_VERSION=1.17.5 ARG GO_PROXY=https://goproxy.cn,direct # build libpng diff --git a/contrib/build/build_all.go b/contrib/build/build_all.go index d3b2abc..b6ddabe 100644 --- a/contrib/build/build_all.go +++ b/contrib/build/build_all.go @@ -167,8 +167,8 @@ func build(t target) { ldflags := "-X 'main.gitHash=" + gitHash() + "' " + "-X 'main.gitReversion=" + gitReversion() + "' " + "-X 'main.buildTime=" + buildTime() + "' " + - "-X 'main.version=" + version + "' " + - "--extldflags '-static -fpic -lssp'" + "-X 'main.version=" + version + "' " + // "--extldflags '-static -fpic -lssp'" logging.Info("build server...") cmd := exec.Command("go", "build", "-o", path.Join(buildDir, "np-svr"+t.ext), @@ -190,7 +190,8 @@ func build(t target) { fmt.Sprintf("CXX=%s", t.cxx)) args := []string{"build", "-o", path.Join(buildDir, "np-cli"+t.ext), "-ldflags", ldflags} if t.os == "windows" && !strings.Contains(t.arch, "arm") { - args = append(args, "-tags", "vnc") + env = append(env, "CGO_ENABLED=1") + } else if t.os == "linux" && !strings.Contains(t.arch, "arm") { env = append(env, "CGO_ENABLED=1") } args = append(args, @@ -201,27 +202,6 @@ func build(t target) { cmd.Env = env runtime.Assert(cmd.Run()) - if t.os == "linux" && !strings.Contains(t.arch, "arm") { - ldflags := "-X 'main.gitHash=" + gitHash() + "' " + - "-X 'main.gitReversion=" + gitReversion() + "' " + - "-X 'main.buildTime=" + buildTime() + "' " + - "-X 'main.version=" + version + "'" - logging.Info("build client.vnc...") - env := append(os.Environ(), - fmt.Sprintf("GOOS=%s", t.os), - fmt.Sprintf("GOARCH=%s", t.arch)) - args := []string{"build", "-o", path.Join(buildDir, "np-cli.vnc"), "-ldflags", ldflags} - args = append(args, "-tags", "vnc") - env = append(env, "CGO_ENABLED=1") - args = append(args, - path.Join("code", "client", "main.go")) - cmd = exec.Command("go", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Env = env - runtime.Assert(cmd.Run()) - } - logging.Info("packing...") pack(buildDir, path.Join(releaseDir, "natpass_"+version+"_"+t.os+"_"+t.arch+t.packExt)) } diff --git a/docs/startup.md b/docs/startup.md index f18cff4..fe88a70 100644 --- a/docs/startup.md +++ b/docs/startup.md @@ -9,20 +9,14 @@ 1. 在服务器上[下载](https://github.com/lwch/natpass/releases)并解压到任意目录 2. 修改server.yaml配置文件,设置*key*和*crt*参数到你的证书所在路径 -3. 修改conf.d/conn.yaml配置文件,修改*secret*密钥,建议使用以下命令生成随机16位密钥 +3. 修改common.yaml配置文件,修改*secret*密钥,建议使用以下命令生成随机16位密钥 tr -dc A-Za-z0-9 < /dev/urandom|dd bs=16 count=1 2>/dev/null -4. 修改conf.d/log.yaml配置文件,将log目录设置为一个绝对路径 -5. 使用以下命令将np-svr注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动) +4. 使用以下命令将np-svr注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动) sudo ./np-svr -conf server.yaml -action install -user nobody -6. 手动创建第4步中设置的log目录,并将其属主设置为nobody +5. 启动服务 - sudo mkdir -p - sudo chown -R nobody -7. 将该服务设置为系统启动项,并启动服务 - - sudo systemctl enable np-svr sudo systemctl start np-svr ## 受控端部署 @@ -31,43 +25,26 @@ 2. 修改client.yaml配置文件,设置*id*为remote,设置*server*地址,并删除以下配置 #include rule.d/*.yaml -3. 修改conf.d/conn.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致 -4. 修改conf.d/log.yaml配置文件,将log目录设置为一个绝对路径 -5. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动) +3. 修改common.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致 +4. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份 + sudo ./np-cli -conf client.yaml -action install -user `whoami` +5. 启动服务 - sudo ./np-cli -conf client.yaml -action install -user nobody -6. 手动创建第4步中设置的log目录,并将其属主设置为nobody - - sudo mkdir -p - sudo chown -R nobody -7. 将该服务设置为系统启动项,并启动服务 - - sudo systemctl enable np-cli sudo systemctl start np-cli -**注:当受控端为linux操作系统时,请使用np-cli.vnc程序进行启动,暂不支持系统服务方式启动,手工启动命令如下** - - ./np-cli -conf client.yaml - ## 控制端部署 1. 在本地控制机上[下载](https://github.com/lwch/natpass/releases)并解压到任意目录 2. 修改client.yaml配置文件,设置*id*为local,设置*server*地址 -3. 修改conf.d/conn.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致 -4. 修改conf.d/log.yaml配置文件,将log目录设置为一个绝对路径 -5. 修改rule.d目录下的规则配置文件,[rule配置方法](rules.md) -6. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动) +3. 修改common.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致 +4. 修改rule.d目录下的规则配置文件,[rule配置方法](rules.md) +5. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动) sudo ./np-cli -conf client.yaml -action install -user nobody -7. 手动创建第4步中设置的log目录,并将其属主设置为nobody +6. 启动服务 - sudo mkdir -p - sudo chown -R nobody -8. 将该服务设置为系统启动项,并启动服务 - - sudo systemctl enable np-cli sudo systemctl start np-cli -9. 在以上操作成功后即可在浏览器中通过client.yaml中配置的端口号进行访问,默认地址: +7. 在以上操作成功后即可在浏览器中通过client.yaml中配置的端口号进行访问,默认地址: http://127.0.0.1:8080 diff --git a/go.mod b/go.mod index 9d4f2f0..e64f257 100644 --- a/go.mod +++ b/go.mod @@ -6,20 +6,16 @@ require ( github.com/creack/pty v1.1.17 github.com/dustin/go-humanize v1.0.0 github.com/go-bindata/go-bindata/v3 v3.1.3 - github.com/go-vgo/robotgo v0.100.9 github.com/gorilla/websocket v1.4.2 github.com/kardianos/service v1.2.0 github.com/kisielk/errcheck v1.6.0 // indirect github.com/lwch/logging v0.0.0-20211203094902-ecb971ed7cdc - github.com/lwch/rdesktop v0.0.0-20211207101551-b892a4a5e2b5 + github.com/lwch/rdesktop v0.0.0-20211229040606-1ab25b15434c github.com/lwch/runtime v0.0.0-20190520054850-8c97e19e0c6d github.com/lwch/yaml v0.0.0-20211206085137-772f80e85a26 - github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.5.1 // indirect - golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e golang.org/x/text v0.3.7 - golang.org/x/tools v0.1.7 // indirect + golang.org/x/tools v0.1.8 // indirect google.golang.org/protobuf v1.27.1 ) diff --git a/go.sum b/go.sum index d159254..6e6537c 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,9 @@ -github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= -github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-vgo/robotgo v0.100.9 h1:dgt4qaxBw6+vg4P5tUeH26VsL5M0v/IRwRmkingZ2YU= -github.com/go-vgo/robotgo v0.100.9/go.mod h1:7QeIpSHX7bjeXWRPxvQeKSx9mHI+3l80Ahq+CQF0C68= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -28,88 +17,48 @@ github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/lwch/logging v0.0.0-20211115073745-0db19179db17/go.mod h1:aXQui5bsF/d4I+z6szuiBWY5m4y9t6pyZ2Q/sLgkBBg= github.com/lwch/logging v0.0.0-20211203094902-ecb971ed7cdc h1:QHC/AggBsu39IWcbzjgIc2ApNXuWhZhD1ieCkFgWfeM= github.com/lwch/logging v0.0.0-20211203094902-ecb971ed7cdc/go.mod h1:aXQui5bsF/d4I+z6szuiBWY5m4y9t6pyZ2Q/sLgkBBg= -github.com/lwch/rdesktop v0.0.0-20211207101551-b892a4a5e2b5 h1:RF5uIUO37p6WVgqd3mrkPLYNvJCBHs9sOpBsbTYdzO4= -github.com/lwch/rdesktop v0.0.0-20211207101551-b892a4a5e2b5/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= +github.com/lwch/rdesktop v0.0.0-20211229023040-e12f4166b311 h1:myjL50IJ8WXVOLlNnrZU/Dj1D0g8DQrT4N36axMccYg= +github.com/lwch/rdesktop v0.0.0-20211229023040-e12f4166b311/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= +github.com/lwch/rdesktop v0.0.0-20211229032819-c130bc8f29af h1:RDKhLIR9CpjuJebkYMja9Zj4RlESJ7WVxba5r3KFhWo= +github.com/lwch/rdesktop v0.0.0-20211229032819-c130bc8f29af/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= +github.com/lwch/rdesktop v0.0.0-20211229035251-e2ccadf35f97 h1:LuszXjKntydv39X2afm9aK0dLiUGSu9jqC0HcMZqtYI= +github.com/lwch/rdesktop v0.0.0-20211229035251-e2ccadf35f97/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= +github.com/lwch/rdesktop v0.0.0-20211229035721-f527d0bcd64c h1:jIoEdoB+hBeH6Xo7cS3jcJF9ed0l+b8wM06TGVSBV2U= +github.com/lwch/rdesktop v0.0.0-20211229035721-f527d0bcd64c/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= +github.com/lwch/rdesktop v0.0.0-20211229040606-1ab25b15434c h1:P8L8xYlrQx7mUuWnQpnUeWNabqwQYMyhNtrSmLdGRTE= +github.com/lwch/rdesktop v0.0.0-20211229040606-1ab25b15434c/go.mod h1:vZtkNUaG1bDuzJavu8OQQoBbHVS6cYJE7y4oxtmhYYM= github.com/lwch/runtime v0.0.0-20190520054850-8c97e19e0c6d h1:Xg+zzPtvX22DaoJD5Bp0tqPdB8gn5WypghIJ4fluqiQ= github.com/lwch/runtime v0.0.0-20190520054850-8c97e19e0c6d/go.mod h1:uEt0zu1MDC7WnVvodPBGSYAD/KMKk0v36xE8UE5veM8= github.com/lwch/yaml v0.0.0-20211206085137-772f80e85a26 h1:sR3nbPhdfstDxYLp7c1EnsKH3z8+u+wgnhC3AI9/qf0= github.com/lwch/yaml v0.0.0-20211206085137-772f80e85a26/go.mod h1:Dz0eixDQvioB5pqCXGQJ6sTJetbS6TCHegLuRh2Bw2U= -github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= -github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I= -github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE= -github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.31.3 h1:kGX8iukJ9ensVRwRKnTtdojAMQOpa6KFnXDi4OA4RaI= -github.com/robotn/gohook v0.31.3/go.mod h1:wyGik0yb4iwCfJjDprtNkTyxkgQWuKoVPQ3hkz6+6js= -github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= -github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= -github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= -github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= -github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= -github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= -github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/vcaesar/gops v0.21.3 h1:VR7amkxVv9CQfsotkXrmMyT19dVuNTa1PM/oopJeIc0= -github.com/vcaesar/gops v0.21.3/go.mod h1:3e2EnlZTI9/44bqzRwkeZ3s0ZQwK2Cn4QPLx8Ii8Agk= -github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= -github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= -github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= -github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= -github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= -github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -119,8 +68,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -131,6 +80,5 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/html/vnc/index.js b/html/vnc/index.js index 42669c2..cdbf6eb 100644 --- a/html/vnc/index.js +++ b/html/vnc/index.js @@ -201,6 +201,8 @@ var page = { key = '['; } else if (e.which == 221) { key = ']'; + } else if (e.which == 220) { + key = '\\'; } else if (e.which == 186) { key = ';'; } else if (e.which == 222) {