master
Evan Chen 2021-11-16 15:33:05 +08:00
parent 6b307111df
commit 37eafbe7d8
28 changed files with 9288 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

15
go.mod Normal file
View File

@ -0,0 +1,15 @@
module kumoly.io/tools/goshell
go 1.17
require (
github.com/creack/pty v1.1.17
github.com/gorilla/websocket v1.4.2
kumoly.io/lib/klog v0.0.8
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298
)
require (
github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
)

13
go.sum Normal file
View File

@ -0,0 +1,13 @@
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
kumoly.io/lib/klog v0.0.8 h1:6hTfDlZh7KGnPrd2tUrauCKRImSnyyN9DHXpey3Czn8=
kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M=
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI=
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298/go.mod h1:pwd+NspxnoxPJAETRY2V4i2qZc+orKLxvWzGUBiqBW8=

1
index.html Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>{{.AppName}}</title><link href="css/app.0e433876.css" rel="preload" as="style"><link href="css/chunk-vendors.78de0e90.css" rel="preload" as="style"><link href="js/app.5bd01a68.js" rel="preload" as="script"><link href="js/chunk-vendors.3d58276e.js" rel="preload" as="script"><link href="css/chunk-vendors.78de0e90.css" rel="stylesheet"><link href="css/app.0e433876.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but {{.AppName}} doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.3d58276e.js"></script><script src="js/app.5bd01a68.js"></script></body></html>

95
main.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
_ "embed"
"flag"
"net/http"
"os"
"os/exec"
"strings"
"github.com/creack/pty"
"github.com/gorilla/websocket"
"kumoly.io/lib/klog"
"kumoly.io/lib/ksrv"
"kumoly.io/lib/ksrv/engine"
"kumoly.io/tools/goshell/public"
)
//go:embed index.html
var index string
var tmpl *engine.Engine
var servePublic = http.FileServer(http.FS(public.FS))
var (
flagAppName string
flagAddr string
flagShell string
)
func init() {
flag.StringVar(&flagAddr, "addr", ":8000", "address to bind")
flag.StringVar(&flagShell, "shell", "bash", "the shell behind")
}
func main() {
flag.Parse()
server := ksrv.New()
mux := http.NewServeMux()
tmpl = engine.Must(engine.New("").Parse(index))
mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
if r.URL.String() == "/" {
tmpl.Execute(rw, App{flagAppName})
return
}
file, err := public.FS.Open(strings.TrimPrefix(r.URL.String(), "/"))
if err != nil {
klog.Debug(err)
tmpl.Execute(rw, App{flagAppName})
return
}
stat, err := file.Stat()
if err != nil || stat.IsDir() {
klog.Debug(err)
tmpl.Execute(rw, App{flagAppName})
return
}
servePublic.ServeHTTP(rw, r)
})
server.Handle(mux).Listen(flagAddr).Serve()
}
type App struct {
AppName string
}
type windowSize struct {
Rows uint16 `json:"rows"`
Cols uint16 `json:"cols"`
X uint16
Y uint16
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func handleWebsocket(w http.ResponseWriter, r *http.Request) {
l := klog.Sub(ksrv.GetIP(r))
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
l.Error("Unable to upgrade connection, err: ", err)
return
}
cmd := exec.Command("/bin/bash", "-l")
cmd.Env = append(os.Environ(), "TERM=xterm")
pty.Winsize
}

View File

View File

@ -0,0 +1 @@
.xterm{position:relative;-moz-user-select:none;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm{cursor:text}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline{text-decoration:underline}.xterm-strikethrough{text-decoration:line-through}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

6
public/fs.go Normal file
View File

@ -0,0 +1,6 @@
package public
import "embed"
//go:embed js favicon.ico
var FS embed.FS

View File

@ -0,0 +1,2 @@
(function(e){function t(t){for(var r,c,a=t[0],i=t[1],p=t[2],l=0,s=[];l<a.length;l++)c=a[l],Object.prototype.hasOwnProperty.call(o,c)&&o[c]&&s.push(o[c][0]),o[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);f&&f(t);while(s.length)s.shift()();return u.push.apply(u,p||[]),n()}function n(){for(var e,t=0;t<u.length;t++){for(var n=u[t],r=!0,a=1;a<n.length;a++){var i=n[a];0!==o[i]&&(r=!1)}r&&(u.splice(t--,1),e=c(c.s=n[0]))}return e}var r={},o={app:0},u=[];function c(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,c),n.l=!0,n.exports}c.m=e,c.c=r,c.d=function(e,t,n){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},c.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(c.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)c.d(n,r,function(t){return e[t]}.bind(null,r));return n},c.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="";var a=window["webpackJsonp"]=window["webpackJsonp"]||[],i=a.push.bind(a);a.push=t,a=a.slice();for(var p=0;p<a.length;p++)t(a[p]);var f=i;u.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("56d7")},"0ae4":function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23");function o(e,t,n,o,u,c){var a=Object(r["e"])("XTerm");return Object(r["d"])(),Object(r["b"])(a)}function u(e,t,n,o,u,c){return Object(r["d"])(),Object(r["c"])("h1",null,"TEST")}var c={},a=(n("9a49"),n("6b0d")),i=n.n(a);const p=i()(c,[["render",u]]);var f=p,l={name:"App",components:{XTerm:f}};const s=i()(l,[["render",o]]);var d=s;Object(r["a"])(d).mount("#app")},"9a49":function(e,t,n){"use strict";n("0ae4")}});
//# sourceMappingURL=app.5bd01a68.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3
src/.browserslistrc Normal file
View File

@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

17
src/.eslintrc.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}

23
src/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

24
src/README.md Normal file
View File

@ -0,0 +1,24 @@
# src
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

5
src/babel.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

29
src/package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "src",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"xterm": "^4.15.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-cli-plugin-pug": "~2.0.0"
}
}

BIN
src/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

6
src/public/fs.go Normal file
View File

@ -0,0 +1,6 @@
package public
import "embed"
//go:embed css js favicon.ico
var FS embed.FS

17
src/public/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>{{.AppName}}</title>
</head>
<body>
<noscript>
<strong>We're sorry but {{.AppName}} doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

17
src/src/App.vue Normal file
View File

@ -0,0 +1,17 @@
<template lang="pug">
XTerm
</template>
<script>
import XTerm from './components/XTerm.vue'
export default {
name: 'App',
components: {
XTerm
}
}
</script>
<style lang="scss">
</style>

BIN
src/src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,46 @@
<template lang="pug">
.console#terminal
</template>
<script>
import {Terminal} from 'xterm'
import {FitAddon} from 'xterm-addon-fit'
export default {
data () {
return {
term: null,
terminalSocket: null,
fitaddon: null
}
},
mounted(){
console.log("mounted")
let terminalContainer = document.getElementById('terminal')
this.term = new Terminal()
this.fitaddon = new FitAddon()
this.term.loadAddon(this.fitaddon)
this.term.open(terminalContainer)
this.fitaddon.fit()
this.term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
console.log(this.term)
},
Unmounted () {
this.term.dispose()
},
methods:{
}
}
</script>
<style lang="scss">
@import '~xterm/css/xterm.css';
.console {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>

4
src/src/main.js Normal file
View File

@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

8
src/vue.config.js Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
publicPath: "",
outputDir: "../public",
indexPath: "../index.html",
devServer: {
proxy: 'http://localhost:8000'
}
}

8951
src/yarn.lock Normal file

File diff suppressed because it is too large Load Diff