mirror of
https://github.com/sorenisanerd/gotty.git
synced 2025-04-02 17:10:29 +00:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c69d11d17d | ||
|
e9bc3f0131 | ||
|
f719846bf3 | ||
|
adfc112d1a | ||
|
ba9326e417 | ||
|
e9887233c0 | ||
|
09c61da056 | ||
|
721607826e | ||
|
113b502abb | ||
|
ddca6a4663 | ||
|
8dd044c7cf | ||
|
4b7715e6b3 | ||
|
546ac8d62b | ||
|
3557ea60a6 | ||
|
bf3eae1d9a | ||
|
2204b28af9 | ||
|
b63b83b3ae | ||
|
8c8f4d36d0 | ||
|
338566985b | ||
|
b87a2ba840 | ||
|
5b6a8fa028 | ||
|
63c17b7d51 | ||
|
e0ee2822cd | ||
|
41f09daf42 | ||
|
5b8ba12cb3 | ||
|
48c794023a | ||
|
a7160c58c8 | ||
|
c7263e39bc | ||
|
31530f8a43 | ||
|
df86da4964 | ||
|
9bab150922 | ||
|
a1cadb5846 | ||
|
e51731714f | ||
|
16c534e1a9 | ||
|
87c10e562e | ||
|
f426ca26f2 | ||
|
d92d17c15d | ||
|
e8f5de568d | ||
|
936288058d | ||
|
26c419f564 | ||
|
1b7cb8c9cb | ||
|
b283514f9e | ||
|
7ffe343767 | ||
|
3913c1c91e | ||
|
77ac0b8e58 |
23
.github/workflows/main.yaml
vendored
23
.github/workflows/main.yaml
vendored
@ -7,7 +7,26 @@ on:
|
||||
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
bundle-up-to-date:
|
||||
runs-on: "ubuntu-latest"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- run: "make clean"
|
||||
- run: "make assets"
|
||||
- name: "Make sure gotty.js bundle is up-to-date"
|
||||
run: "diffsize=$(git diff bindata/static/js/gotty.js | wc -l); test $diffsize == 0"
|
||||
|
||||
|
||||
cross-compile-test:
|
||||
runs-on: "ubuntu-latest"
|
||||
|
||||
steps:
|
||||
@ -23,7 +42,7 @@ jobs:
|
||||
- name: "Build & test"
|
||||
run: "make tools test cross_compile"
|
||||
|
||||
- name: Upload build artifacts
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: binaries
|
||||
|
42
.github/workflows/pre-release.yaml
vendored
Normal file
42
.github/workflows/pre-release.yaml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
name: "pre-release"
|
||||
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
pre-release-docker:
|
||||
name: "Pre Release Docker"
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,format=long
|
||||
type=sha
|
||||
type=semver,pattern=v{{major}}.{{minor}}.{{patch}}
|
||||
type=semver,pattern=v{{major}}.{{minor}}
|
||||
type=semver,pattern=v{{major}}
|
||||
type=ref,event=tag
|
||||
type=ref,event=branch
|
||||
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/login-action@v2
|
||||
with:
|
||||
username: "${{ secrets.DOCKER_HUB_USER }}"
|
||||
password: "${{ secrets.DOCKER_HUB_TOKEN }}"
|
||||
- name: "Build and push docker image"
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
30
.github/workflows/quick-build.yaml
vendored
Normal file
30
.github/workflows/quick-build.yaml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
name: "Quick build test"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
|
||||
jobs:
|
||||
quick-build-test:
|
||||
runs-on: "ubuntu-latest"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
|
||||
- name: "Build"
|
||||
run: "touch bindata/* bindata/*/* ; make"
|
||||
|
||||
- name: Upload linux/amd64 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: gotty-linux-amd64
|
||||
path: gotty
|
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"amodio.tsl-problem-matcher"
|
||||
]
|
||||
}
|
15
.vscode/launch.json
vendored
15
.vscode/launch.json
vendored
@ -7,10 +7,21 @@
|
||||
{
|
||||
"name": "Launch GoTTY",
|
||||
"type": "go",
|
||||
"buildFlags": "-tags=dev",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${workspaceFolder}",
|
||||
"args": ["-a", "127.0.0.1", "-w", "bash"]
|
||||
}
|
||||
"args": ["-a", "127.0.0.1", "-w", "${env:SHELL}"]
|
||||
},
|
||||
{
|
||||
"name": "Launch Chrome",
|
||||
"type": "chrome",
|
||||
"url": "http://127.0.0.1:8080",
|
||||
"webRoot": "${workspaceFolder}/js",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/**/*.js",
|
||||
"!**/node_modules/**"
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
16
.vscode/tasks.json
vendored
Normal file
16
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "webpack watch",
|
||||
"type": "shell",
|
||||
"command": "cd ${workspaceFolder}/js;DEV=1 npx webpack --watch --mode=development",
|
||||
"problemMatcher": [
|
||||
"$ts-webpack-watch"
|
||||
],
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
15
Dockerfile
15
Dockerfile
@ -1,15 +1,20 @@
|
||||
FROM golang:1.16
|
||||
FROM node:16 as js-build
|
||||
WORKDIR /gotty
|
||||
COPY js /gotty/js
|
||||
COPY Makefile /gotty/
|
||||
RUN make bindata/static/js/gotty.js.map
|
||||
|
||||
FROM golang:1.20 as go-build
|
||||
WORKDIR /gotty
|
||||
COPY . /gotty
|
||||
COPY --from=js-build /gotty/js/node_modules /gotty/js/node_modules
|
||||
COPY --from=js-build /gotty/bindata/static/js /gotty/bindata/static/js
|
||||
RUN CGO_ENABLED=0 make
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk --no-cache add ca-certificates && \
|
||||
apk add bash
|
||||
apk --no-cache add ca-certificates bash
|
||||
WORKDIR /root
|
||||
COPY --from=0 /gotty/gotty /usr/bin/
|
||||
COPY --from=go-build /gotty/gotty /usr/bin/
|
||||
CMD ["gotty", "-w", "bash"]
|
||||
|
15
Makefile
15
Makefile
@ -2,13 +2,20 @@ OUTPUT_DIR = ./builds
|
||||
GIT_COMMIT = `git rev-parse HEAD | cut -c1-7`
|
||||
VERSION = $(shell git describe --tags)
|
||||
BUILD_OPTIONS = -ldflags "-X main.Version=$(VERSION)"
|
||||
WEBPACK_MODE = production
|
||||
|
||||
ifeq ($(DEV), 1)
|
||||
BUILD_OPTIONS += -tags dev
|
||||
WEBPACK_MODE = development
|
||||
else
|
||||
WEBPACK_MODE = production
|
||||
endif
|
||||
|
||||
export CGO_ENABLED=0
|
||||
|
||||
gotty: main.go assets server/*.go webtty/*.go backend/*.go Makefile
|
||||
go build ${BUILD_OPTIONS}
|
||||
|
||||
docker:
|
||||
docker:
|
||||
docker build . -t gotty-bash:$(VERSION)
|
||||
|
||||
.PHONY: all docker assets
|
||||
@ -81,5 +88,5 @@ clean:
|
||||
rm -fr gotty builds js/dist bindata/static js/node_modules
|
||||
|
||||
addcontributors:
|
||||
gh issue list -s all -L 1000 --json author -t "$$(echo '{{ range . }}{{ .author.login }}\n{{ end }}')" | sort | uniq | xargs -Ifoo all-contributors add foo bug
|
||||
gh pr list -s all -L 1000 --json author -t "$$(echo '{{ range . }}{{ .author.login }}\n{{ end }}')" | sort | uniq | xargs -Ifoo all-contributors add foo code
|
||||
gh issue list -s all -L 1000 --json author -t "$$(echo '{{ range . }}{{ .author.login }}\n{{ end }}')" | sort | uniq | xargs -Ifoo all-contributors add foo bug --commitTemplate '<%= (newContributor ? "Add" : "Update") %> @<%= username %> as a contributor'
|
||||
gh pr list -s all -L 1000 --json author -t "$$(echo '{{ range . }}{{ .author.login }}\n{{ end }}')" | sort | uniq | xargs -Ifoo all-contributors add foo code --commitTemplate '<%= (newContributor ? "Add" : "Update") %> @<%= username %> as a contributor'
|
40
NEWS.md
40
NEWS.md
@ -1,3 +1,43 @@
|
||||
## 1.5.0 (2022-09-01)
|
||||
|
||||
* Add @ahmetb as a contributor ([276767a](https://github.com/sorenisanerd/gotty/commit/276767a))
|
||||
* Add @CoconutMacaroon as a contributor ([74c1318](https://github.com/sorenisanerd/gotty/commit/74c1318))
|
||||
* Add @DannyBen as a contributor ([fcfa161](https://github.com/sorenisanerd/gotty/commit/fcfa161))
|
||||
* Add @dmartin as a contributor ([6b2ae89](https://github.com/sorenisanerd/gotty/commit/6b2ae89))
|
||||
* Add @Fan-SJ as a contributor ([c2428c8](https://github.com/sorenisanerd/gotty/commit/c2428c8))
|
||||
* Add @flechaig as a contributor ([2c4004d](https://github.com/sorenisanerd/gotty/commit/2c4004d))
|
||||
* Add @George-NG as a contributor ([270ae45](https://github.com/sorenisanerd/gotty/commit/270ae45))
|
||||
* Add @ghthor as a contributor ([1a6bccd](https://github.com/sorenisanerd/gotty/commit/1a6bccd))
|
||||
* Add @jpillora as a contributor ([f52fbd7](https://github.com/sorenisanerd/gotty/commit/f52fbd7))
|
||||
* Add @kaisawind as a contributor ([accff3a](https://github.com/sorenisanerd/gotty/commit/accff3a))
|
||||
* Add @linyinli as a contributor ([8014af3](https://github.com/sorenisanerd/gotty/commit/8014af3))
|
||||
* Add @LucaMarconato as a contributor ([3bd9836](https://github.com/sorenisanerd/gotty/commit/3bd9836))
|
||||
* Add @masterkain as a contributor ([369e2f7](https://github.com/sorenisanerd/gotty/commit/369e2f7))
|
||||
* Add @Nexuist as a contributor ([ca691bc](https://github.com/sorenisanerd/gotty/commit/ca691bc))
|
||||
* Add @qigj as a contributor ([5a052e7](https://github.com/sorenisanerd/gotty/commit/5a052e7))
|
||||
* Add @shuaiyy as a contributor ([95e1bbd](https://github.com/sorenisanerd/gotty/commit/95e1bbd))
|
||||
* Add @v20z as a contributor ([d594bef](https://github.com/sorenisanerd/gotty/commit/d594bef))
|
||||
* Add @xgdgsc as a contributor ([c197990](https://github.com/sorenisanerd/gotty/commit/c197990))
|
||||
* Add @Yann-Qiu as a contributor ([7b994ec](https://github.com/sorenisanerd/gotty/commit/7b994ec))
|
||||
* Update @flechaig as a contributor ([9877e9c](https://github.com/sorenisanerd/gotty/commit/9877e9c))
|
||||
* Update @flechaig as a contributor ([e03ea9c](https://github.com/sorenisanerd/gotty/commit/e03ea9c))
|
||||
* Update @prusnak as a contributor ([3c45888](https://github.com/sorenisanerd/gotty/commit/3c45888))
|
||||
* Update @prusnak as a contributor ([8d7f5fc](https://github.com/sorenisanerd/gotty/commit/8d7f5fc))
|
||||
* Update @sorenisanerd as a contributor ([34f516b](https://github.com/sorenisanerd/gotty/commit/34f516b))
|
||||
* Update @sorenisanerd as a contributor ([89a04d1](https://github.com/sorenisanerd/gotty/commit/89a04d1))
|
||||
* Update @xgdgsc as a contributor ([b3c5d03](https://github.com/sorenisanerd/gotty/commit/b3c5d03))
|
||||
* Update @xgdgsc as a contributor ([09f7e95](https://github.com/sorenisanerd/gotty/commit/09f7e95))
|
||||
* Add make target to add contributors ([1bbfd5e](https://github.com/sorenisanerd/gotty/commit/1bbfd5e))
|
||||
* Add missing import "strings" ([d0e3ffb](https://github.com/sorenisanerd/gotty/commit/d0e3ffb))
|
||||
* add slash ([7706bf2](https://github.com/sorenisanerd/gotty/commit/7706bf2))
|
||||
* Always disable CGO ([7a96f37](https://github.com/sorenisanerd/gotty/commit/7a96f37)), closes [#39](https://github.com/sorenisanerd/gotty/issues/39)
|
||||
* Bump terser from 5.12.1 to 5.14.2 in /js ([3ae13e0](https://github.com/sorenisanerd/gotty/commit/3ae13e0))
|
||||
* Create a release when a new tag is pushed ([d8fe975](https://github.com/sorenisanerd/gotty/commit/d8fe975))
|
||||
* Ensure --quiet flag is honored ([7d431a7](https://github.com/sorenisanerd/gotty/commit/7d431a7)), closes [#45](https://github.com/sorenisanerd/gotty/issues/45)
|
||||
* Refresh dependencies, drop node-sass ([94e5873](https://github.com/sorenisanerd/gotty/commit/94e5873))
|
||||
* Run tests on pull requests ([316d5ff](https://github.com/sorenisanerd/gotty/commit/316d5ff))
|
||||
|
||||
|
||||
## 1.4.0 (2022-05-30)
|
||||
|
||||
* Add @hardliner66 as a contributor ([1ca998e](https://github.com/sorenisanerd/gotty/commit/1ca998e))
|
||||
|
@ -5,9 +5,11 @@
|
||||
|
||||
[][release]
|
||||
[][license]
|
||||
[][twitch]
|
||||
|
||||
[release]: https://github.com/sorenisanerd/gotty/releases
|
||||
[license]: https://github.com/sorenisanerd/gotty/blob/master/LICENSE
|
||||
[twitch]: https://twitch.tv/sorencodes
|
||||
|
||||
GoTTY is a simple command line tool that turns your CLI tools into web applications.
|
||||
|
||||
@ -73,6 +75,7 @@ By default, GoTTY starts a web server at port 8080. Open the URL on your web bro
|
||||
--width value Static width of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_WIDTH]
|
||||
--height value Static height of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_HEIGHT]
|
||||
--ws-origin value A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default [$GOTTY_WS_ORIGIN]
|
||||
--ws-query-args value Querystring arguments to append to the websocket instantiation [$GOTTY_WS_QUERY_ARGS]
|
||||
--enable-webgl Enable WebGL renderer (default: true) [$GOTTY_ENABLE_WEBGL]
|
||||
--close-signal value Signal sent to the command process when gotty close it (default: SIGHUP) (default: 1) [$GOTTY_CLOSE_SIGNAL]
|
||||
--close-timeout value Time in seconds to force kill process after client is disconnected (default: -1) (default: -1) [$GOTTY_CLOSE_TIMEOUT]
|
||||
|
@ -37,12 +37,12 @@ func (factory *Factory) Name() string {
|
||||
return "local command"
|
||||
}
|
||||
|
||||
func (factory *Factory) New(params map[string][]string) (server.Slave, error) {
|
||||
func (factory *Factory) New(params map[string][]string, headers map[string][]string) (server.Slave, error) {
|
||||
argv := make([]string, len(factory.argv))
|
||||
copy(argv, factory.argv)
|
||||
if params["arg"] != nil && len(params["arg"]) > 0 {
|
||||
argv = append(argv, params["arg"]...)
|
||||
}
|
||||
|
||||
return New(factory.command, argv, factory.opts...)
|
||||
return New(factory.command, argv, headers, factory.opts...)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package localcommand
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -27,11 +28,22 @@ type LocalCommand struct {
|
||||
ptyClosed chan struct{}
|
||||
}
|
||||
|
||||
func New(command string, argv []string, options ...Option) (*LocalCommand, error) {
|
||||
func New(command string, argv []string, headers map[string][]string, options ...Option) (*LocalCommand, error) {
|
||||
cmd := exec.Command(command, argv...)
|
||||
|
||||
cmd.Env = append(os.Environ(), "TERM=xterm-256color")
|
||||
|
||||
// Combine headers into key=value pairs to set as env vars
|
||||
// Prefix the headers with "http_" so we don't overwrite any other env vars
|
||||
// which potentially has the same name and to bring these closer to what
|
||||
// a (F)CGI server would proxy to a backend service
|
||||
// Replace hyphen with underscore and make them all upper case
|
||||
for key, values := range headers {
|
||||
h := "HTTP_" + strings.Replace(strings.ToUpper(key), "-", "_", -1) + "=" + strings.Join(values, ",")
|
||||
// log.Printf("Adding header: %s", h)
|
||||
cmd.Env = append(cmd.Env, h)
|
||||
}
|
||||
|
||||
pty, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
// todo close cmd?
|
||||
|
@ -23,7 +23,7 @@ func TestNewFactory(t *testing.T) {
|
||||
t.Errorf("factory.options = %v, expected %v", factory.options, &Options{})
|
||||
}
|
||||
|
||||
slave, _ := factory.New(nil)
|
||||
slave, _ := factory.New(nil, nil)
|
||||
lcmd := slave.(*LocalCommand)
|
||||
if lcmd.closeSignal != 123 {
|
||||
t.Errorf("lcmd.closeSignal = %v, expected %v", lcmd.closeSignal, 123)
|
||||
@ -40,7 +40,7 @@ func TestFactoryNew(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
slave, err := factory.New(nil)
|
||||
slave, err := factory.New(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("factory.New() returned error")
|
||||
return
|
||||
|
@ -1,3 +1,5 @@
|
||||
//go:build !dev
|
||||
|
||||
package bindata
|
||||
|
||||
import "embed"
|
||||
|
28
bindata/bindata_dev.go
Normal file
28
bindata/bindata_dev.go
Normal file
@ -0,0 +1,28 @@
|
||||
//go:build dev
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
type GottyFS struct {
|
||||
fs.FS
|
||||
}
|
||||
|
||||
var Fs GottyFS
|
||||
|
||||
func (gfs *GottyFS) ReadFile(name string) ([]byte, error) {
|
||||
fp, err := gfs.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return io.ReadAll(fp)
|
||||
}
|
||||
|
||||
func init() {
|
||||
Fs = GottyFS{os.DirFS("bindata")}
|
||||
}
|
@ -149,6 +149,7 @@
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.xterm .live-region {
|
||||
@ -160,13 +161,27 @@
|
||||
}
|
||||
|
||||
.xterm-dim {
|
||||
opacity: 0.5;
|
||||
/* Dim should not apply to background, so the opacity of the foreground color is applied
|
||||
* explicitly in the generated class and reset to 1 here */
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.xterm-underline {
|
||||
text-decoration: underline;
|
||||
.xterm-underline-1 { text-decoration: underline; }
|
||||
.xterm-underline-2 { text-decoration: double underline; }
|
||||
.xterm-underline-3 { text-decoration: wavy underline; }
|
||||
.xterm-underline-4 { text-decoration: dotted underline; }
|
||||
.xterm-underline-5 { text-decoration: dashed underline; }
|
||||
|
||||
.xterm-overline {
|
||||
text-decoration: overline;
|
||||
}
|
||||
|
||||
.xterm-overline.xterm-underline-1 { text-decoration: overline underline; }
|
||||
.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; }
|
||||
.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; }
|
||||
.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; }
|
||||
.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; }
|
||||
|
||||
.xterm-strikethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
@ -176,8 +191,12 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer {
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
.xterm-decoration-overview-ruler {
|
||||
z-index: 7;
|
||||
z-index: 8;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap v5.2.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -26,8 +26,7 @@ bootstrap
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2022 Twitter, Inc.
|
||||
Copyright (c) 2011-2022 The Bootstrap Authors
|
||||
Copyright (c) 2011-2023 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
13
go.mod
13
go.mod
@ -1,15 +1,22 @@
|
||||
module github.com/sorenisanerd/gotty
|
||||
|
||||
go 1.16
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/creack/pty v1.1.11
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -30,7 +30,7 @@ github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552 h1:tjsK9T2IA3d2FFNxzDP7AJf+EXhyuPd7PB4Z2HrtAoc=
|
||||
github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552/go.mod h1:hg0ZaCmQL3rze1cH8Fh2g0a9q8vQs0uN8ESpePEwSEw=
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c h1:6L+uOeS3OQt/f4eFHXZcTxeZrGCuz+CLElgEBjbcTA4=
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
4569
js/package-lock.json
generated
4569
js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,31 +3,32 @@
|
||||
"version": "1.4.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bootstrap": "^5.1.9",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
"compression-webpack-plugin": "^9.2.0",
|
||||
"license-loader": "^0.5.0",
|
||||
"license-webpack-plugin": "^4.0.2",
|
||||
"purgecss": "^4.1.3",
|
||||
"sass": "^1.54.5",
|
||||
"sass": "^1.70.0",
|
||||
"sass-loader": "^12.6.0",
|
||||
"terser-webpack-plugin": "^5.3.1",
|
||||
"ts-loader": "^8.3.0",
|
||||
"typescript": "^4.3.2",
|
||||
"webpack": "^5.72.0",
|
||||
"webpack-cli": "^4.7.0"
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"ts-loader": "^8.4.0",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "^5.90.1",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.15.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"bootstrap": "^5.1.3",
|
||||
"css-loader": "^5.2.6",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"bootstrap": "^5.3.2",
|
||||
"css-loader": "^5.2.7",
|
||||
"debounce": "^1.2.1",
|
||||
"preact": "^10.7.1",
|
||||
"react-bootstrap": "^2.2.3",
|
||||
"preact": "^10.19.4",
|
||||
"react-bootstrap": "^2.10.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"xterm": "^4.12.0",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"xterm-addon-web-links": "^0.4.0",
|
||||
"xterm-addon-webgl": "^0.10.0",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
"xterm-addon-web-links": "^0.9.0",
|
||||
"xterm-addon-webgl": "^0.16.0",
|
||||
"zmodem.js": "^0.1.10"
|
||||
}
|
||||
}
|
||||
|
1
js/src/bootstrap.scss
vendored
1
js/src/bootstrap.scss
vendored
@ -6,6 +6,7 @@
|
||||
// Configuration
|
||||
@import "functions";
|
||||
@import "variables";
|
||||
@import "variables-dark";
|
||||
@import "maps";
|
||||
@import "mixins";
|
||||
@import "utilities";
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { OurXterm } from "./xterm";
|
||||
import { Terminal, WebTTY, protocols } from "./webtty";
|
||||
import { ConnectionFactory } from "./websocket";
|
||||
import { Terminal, WebTTY, protocols } from "./webtty";
|
||||
import { OurXterm } from "./xterm";
|
||||
|
||||
// @TODO remove these
|
||||
declare var gotty_auth_token: string;
|
||||
declare var gotty_term: string;
|
||||
declare var gotty_ws_query_args: string;
|
||||
|
||||
const elem = document.getElementById("terminal")
|
||||
|
||||
@ -13,7 +14,8 @@ if (elem !== null) {
|
||||
term = new OurXterm(elem);
|
||||
|
||||
const httpsEnabled = window.location.protocol == "https:";
|
||||
const url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname + 'ws';
|
||||
const queryArgs = (gotty_ws_query_args === "") ? "" : "?" + gotty_ws_query_args;
|
||||
const url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname + 'ws' + queryArgs;
|
||||
const args = window.location.search;
|
||||
const factory = new ConnectionFactory(url, protocols);
|
||||
const wt = new WebTTY(term, factory, args, gotty_auth_token);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Terminal, IDisposable } from "xterm";
|
||||
import { IDisposable, Terminal } from "xterm";
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { WebglAddon } from 'xterm-addon-webgl';
|
||||
@ -104,9 +104,9 @@ export class OurXterm {
|
||||
if (key == "EnableWebGL" && key) {
|
||||
this.term.loadAddon(new WebglAddon());
|
||||
} else if (key == "font-size") {
|
||||
this.term.setOption("fontSize", value[key])
|
||||
this.term.options.fontSize = value[key]
|
||||
} else if (key == "font-family") {
|
||||
this.term.setOption("fontFamily", value[key])
|
||||
this.term.options.fontFamily = value[key]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, ComponentChildren, createRef, render } from "preact";
|
||||
import { ITerminalAddon, Terminal } from "xterm";
|
||||
import { Browser, Detection, Offer, Sentry, Session } from 'zmodem.js/src/zmodem_browser';
|
||||
import { MyModal, Button } from "./MyModal";
|
||||
import { Component, ComponentChildren, createRef, render } from "preact";
|
||||
import { Button, MyModal } from "./MyModal";
|
||||
|
||||
export class ZModemAddon implements ITerminalAddon {
|
||||
term: Terminal;
|
||||
|
@ -18,6 +18,7 @@
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
@ -2,6 +2,14 @@ const path = require('path');
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const LicenseWebpackPlugin = require('license-webpack-plugin').LicenseWebpackPlugin;
|
||||
|
||||
var devtool;
|
||||
|
||||
if (process.env.DEV === '1') {
|
||||
devtool = 'inline-source-map';
|
||||
} else {
|
||||
devtool = 'source-map';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/main.ts",
|
||||
entry: {
|
||||
@ -10,7 +18,7 @@ module.exports = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../bindata/static/js/'),
|
||||
},
|
||||
devtool: "source-map",
|
||||
devtool: devtool,
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"],
|
||||
},
|
||||
|
4
main.go
4
main.go
@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
@ -68,7 +68,7 @@ func main() {
|
||||
|
||||
if appOptions.Quiet {
|
||||
log.SetFlags(0)
|
||||
log.SetOutput(ioutil.Discard)
|
||||
log.SetOutput(io.Discard)
|
||||
}
|
||||
|
||||
if c.IsSet("credential") {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@ -72,7 +73,11 @@ func (server *Server) generateHandleWS(ctx context.Context, cancel context.Cance
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
err = server.processWSConn(ctx, conn)
|
||||
if server.options.PassHeaders {
|
||||
err = server.processWSConn(ctx, conn, r.Header)
|
||||
} else {
|
||||
err = server.processWSConn(ctx, conn, nil)
|
||||
}
|
||||
|
||||
switch err {
|
||||
case ctx.Err():
|
||||
@ -87,7 +92,7 @@ func (server *Server) generateHandleWS(ctx context.Context, cancel context.Cance
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) processWSConn(ctx context.Context, conn *websocket.Conn) error {
|
||||
func (server *Server) processWSConn(ctx context.Context, conn *websocket.Conn, headers map[string][]string) error {
|
||||
typ, initLine, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to authenticate websocket connection")
|
||||
@ -116,7 +121,7 @@ func (server *Server) processWSConn(ctx context.Context, conn *websocket.Conn) e
|
||||
}
|
||||
params := query.Query()
|
||||
var slave Slave
|
||||
slave, err = server.factory.New(params)
|
||||
slave, err = server.factory.New(params, headers)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to create backend")
|
||||
}
|
||||
@ -229,7 +234,12 @@ func (server *Server) handleAuthToken(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (server *Server) handleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
w.Write([]byte("var gotty_term = 'xterm';"))
|
||||
lines := []string{
|
||||
"var gotty_term = 'xterm';",
|
||||
"var gotty_ws_query_args = '" + server.options.WSQueryArgs + "';",
|
||||
}
|
||||
|
||||
w.Write([]byte(strings.Join(lines, "\n")))
|
||||
}
|
||||
|
||||
// titleVariables merges maps in a specified order.
|
||||
|
@ -26,9 +26,11 @@ type Options struct {
|
||||
Once bool `hcl:"once" flagName:"once" flagDescribe:"Accept only one client and exit on disconnection" default:"false"`
|
||||
Timeout int `hcl:"timeout" flagName:"timeout" flagDescribe:"Timeout seconds for waiting a client(0 to disable)" default:"0"`
|
||||
PermitArguments bool `hcl:"permit_arguments" flagName:"permit-arguments" flagDescribe:"Permit clients to send command line arguments in URL (e.g. http://example.com:8080/?arg=AAA&arg=BBB)" default:"false"`
|
||||
PassHeaders bool `hcl:"pass_headers" flagName:"pass-headers" flagDescribe:"Pass HTTP request headers as environment variables (e.g. Cookie becomes HTTP_COOKIE)" default:"false"`
|
||||
Width int `hcl:"width" flagName:"width" flagDescribe:"Static width of the screen, 0(default) means dynamically resize" default:"0"`
|
||||
Height int `hcl:"height" flagName:"height" flagDescribe:"Static height of the screen, 0(default) means dynamically resize" default:"0"`
|
||||
WSOrigin string `hcl:"ws_origin" flagName:"ws-origin" flagDescribe:"A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default" default:""`
|
||||
WSQueryArgs string `hcl:"ws_query_args" flagName:"ws-query-args" flagDescribe:"Querystring arguments to append to the websocket instantiation" default:""`
|
||||
EnableWebGL bool `hcl:"enable_webgl" flagName:"enable-webgl" flagDescribe:"Enable WebGL renderer" default:"true"`
|
||||
Quiet bool `hcl:"quiet" flagName:"quiet" flagDescribe:"Don't log" default:"false"`
|
||||
|
||||
|
@ -6,10 +6,10 @@ import (
|
||||
"crypto/x509"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
noesctmpl "text/template"
|
||||
@ -45,7 +45,7 @@ func New(factory Factory, options *Options) (*Server, error) {
|
||||
}
|
||||
if options.IndexFile != "" {
|
||||
path := homedir.Expand(options.IndexFile)
|
||||
indexData, err = ioutil.ReadFile(path)
|
||||
indexData, err = os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read custom index file at `%s`", path)
|
||||
}
|
||||
@ -253,7 +253,7 @@ func (server *Server) setupHTTPServer(handler http.Handler) (*http.Server, error
|
||||
|
||||
func (server *Server) tlsConfig() (*tls.Config, error) {
|
||||
caFile := homedir.Expand(server.options.TLSCACrtFile)
|
||||
caCert, err := ioutil.ReadFile(caFile)
|
||||
caCert, err := os.ReadFile(caFile)
|
||||
if err != nil {
|
||||
return nil, errors.New("could not open CA crt file " + caFile)
|
||||
}
|
||||
|
@ -13,5 +13,5 @@ type Slave interface {
|
||||
|
||||
type Factory interface {
|
||||
Name() string
|
||||
New(params map[string][]string) (Slave, error)
|
||||
New(params map[string][]string, headers map[string][]string) (Slave, error)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
@ -31,7 +31,7 @@ func (wsw *wsWrapper) Read(p []byte) (n int, err error) {
|
||||
continue
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(reader)
|
||||
b, err := io.ReadAll(reader)
|
||||
if len(b) > len(p) {
|
||||
return 0, errors.Wrapf(err, "Client message exceeded buffer size")
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
@ -114,7 +113,7 @@ func ApplyConfigFile(filePath string, options ...interface{}) error {
|
||||
|
||||
fileString := []byte{}
|
||||
log.Printf("Loading config file at: %s", filePath)
|
||||
fileString, err := ioutil.ReadFile(filePath)
|
||||
fileString, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -72,7 +72,12 @@ func (wt *WebTTY) Run(ctx context.Context) error {
|
||||
errs <- func() error {
|
||||
buffer := make([]byte, wt.bufferSize)
|
||||
for {
|
||||
n, err := wt.slave.Read(buffer)
|
||||
//base64 length
|
||||
effectiveBufferSize := wt.bufferSize - 1
|
||||
//max raw data length
|
||||
maxChunkSize := int(effectiveBufferSize/4) * 3
|
||||
|
||||
n, err := wt.slave.Read(buffer[:maxChunkSize])
|
||||
if err != nil {
|
||||
return ErrSlaveClosed
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user