Skip to content

Commit fd8edb7

Browse files
committed
first commit
0 parents  commit fd8edb7

12 files changed

+832
-0
lines changed

build.sh

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
packr2
4+
5+
GOOS=windows GOARCH=amd64 go build -ldflags "-w -s" -o result/webssh_windows_amd64.exe .
6+
GOOS=windows GOARCH=386 go build -ldflags "-w -s" -o result/webssh_windows_386.exe .
7+
GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -o result/webssh_linux_amd64 .
8+
GOOS=linux GOARCH=arm64 go build -ldflags "-w -s" -o result/webssh_linux_arm64 .
9+
GOOS=darwin GOARCH=amd64 go build -ldflags "-w -s" -o result/webssh_darwin_amd64 .
10+
11+
packr2 clean

controller/common.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package controller
2+
3+
import "time"
4+
5+
type ResponseBody struct {
6+
Duration string
7+
Data interface{}
8+
Msg string
9+
}
10+
11+
func TimeCost(start time.Time, body *ResponseBody) {
12+
body.Duration = time.Since(start).String()
13+
}

controller/file.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package controller
2+
3+
import (
4+
"fmt"
5+
"github.com/gin-gonic/gin"
6+
"io"
7+
"net/http"
8+
"strings"
9+
"time"
10+
"webssh/core"
11+
)
12+
13+
type File struct {
14+
Name string
15+
Size string
16+
ModifyTime string
17+
// 0: 文件 1: 文件夹
18+
FType uint8
19+
}
20+
21+
func UploadFile(c *gin.Context) *ResponseBody {
22+
var (
23+
sshClient core.SSHClient
24+
err error
25+
)
26+
responseBody := ResponseBody{Msg: "success"}
27+
defer TimeCost(time.Now(), &responseBody)
28+
path := strings.TrimSpace(c.DefaultPostForm("path", "/root"))
29+
sshInfo := c.PostForm("sshInfo")
30+
if sshClient, err = core.DecodedMsgToSSHClient(sshInfo); err != nil {
31+
fmt.Println(err)
32+
responseBody.Msg = err.Error()
33+
return &responseBody
34+
}
35+
if err := sshClient.CreateSftp(); err != nil {
36+
fmt.Println(err)
37+
responseBody.Msg = err.Error()
38+
return &responseBody
39+
}
40+
file, header, err := c.Request.FormFile("file")
41+
if err != nil {
42+
responseBody.Msg = err.Error()
43+
return &responseBody
44+
}
45+
defer file.Close()
46+
filename := header.Filename
47+
if path[len(path)-1:] == "/" {
48+
path = path + filename
49+
} else {
50+
path = path + "/" + filename
51+
}
52+
err = sshClient.Upload(file, path)
53+
if err != nil {
54+
fmt.Println(err)
55+
responseBody.Msg = err.Error()
56+
}
57+
return &responseBody
58+
}
59+
60+
func DownloadFile(c *gin.Context) *ResponseBody {
61+
var (
62+
sshClient core.SSHClient
63+
err error
64+
)
65+
responseBody := ResponseBody{Msg: "success"}
66+
defer TimeCost(time.Now(), &responseBody)
67+
path := strings.TrimSpace(c.DefaultQuery("path", "/root"))
68+
sshInfo := c.DefaultQuery("sshInfo", "")
69+
if sshClient, err = core.DecodedMsgToSSHClient(sshInfo); err != nil {
70+
fmt.Println(err)
71+
responseBody.Msg = err.Error()
72+
return &responseBody
73+
}
74+
if err := sshClient.CreateSftp(); err != nil {
75+
fmt.Println(err)
76+
responseBody.Msg = err.Error()
77+
return &responseBody
78+
}
79+
if sftpFile, err := sshClient.Download(path); err != nil {
80+
fmt.Println(err)
81+
responseBody.Msg = err.Error()
82+
return &responseBody
83+
} else {
84+
defer sftpFile.Close()
85+
c.Writer.WriteHeader(http.StatusOK)
86+
fileMeta := strings.Split(path, "/")
87+
c.Header("Content-Disposition", "attachment; filename=" + fileMeta[len(fileMeta)-1])
88+
_, _ = io.Copy(c.Writer, sftpFile)
89+
}
90+
return &responseBody
91+
}
92+
93+
func FileList(c *gin.Context) *ResponseBody {
94+
responseBody := ResponseBody{Msg: "success"}
95+
defer TimeCost(time.Now(), &responseBody)
96+
path := c.DefaultQuery("path", "/root")
97+
sshInfo := c.DefaultQuery("sshInfo", "")
98+
sshClient, err := core.DecodedMsgToSSHClient(sshInfo)
99+
if err != nil {
100+
fmt.Println(err)
101+
responseBody.Msg = err.Error()
102+
return &responseBody
103+
}
104+
result, err := sshClient.ExecRemoteCommand(fmt.Sprintf("ls -lh %s|grep -v ^l|awk 'NR>1'|sort", path))
105+
if err != nil {
106+
fmt.Println(err)
107+
responseBody.Msg = err.Error()
108+
return &responseBody
109+
}
110+
if strings.Contains(result, "ls:") {
111+
fmt.Println(result)
112+
responseBody.Msg = result
113+
return &responseBody
114+
}
115+
lineList := strings.Split(result, "\n")
116+
var fileList []*File
117+
for _, line := range lineList {
118+
if line == "" {
119+
continue
120+
}
121+
//多个空格合并为一个
122+
line = strings.Join(strings.Fields(line), " ")
123+
metaList := strings.Split(line, " ")
124+
file := File{Name: metaList[len(metaList)-1], FType: 0, Size: metaList[4], ModifyTime: strings.Join(metaList[5:len(metaList)-1], " ")}
125+
if strings.Contains(metaList[0], "d") {
126+
file.FType = 1
127+
}
128+
fileList = append(fileList, &file)
129+
}
130+
responseBody.Data = map[string]interface{}{
131+
"path": path,
132+
"list": fileList,
133+
}
134+
return &responseBody
135+
}

controller/terminal.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package controller
2+
3+
import (
4+
"fmt"
5+
"github.com/gin-gonic/gin"
6+
"github.com/gorilla/websocket"
7+
"net/http"
8+
"strconv"
9+
"time"
10+
"webssh/core"
11+
)
12+
13+
var upgrader = websocket.Upgrader{
14+
ReadBufferSize: 1024,
15+
WriteBufferSize: 1024,
16+
CheckOrigin: func(r *http.Request) bool {
17+
return true
18+
},
19+
}
20+
21+
func TermWs(c *gin.Context, d time.Duration) *ResponseBody {
22+
responseBody := ResponseBody{Msg: "success"}
23+
defer TimeCost(time.Now(), &responseBody)
24+
sshInfo := c.DefaultQuery("sshInfo", "")
25+
cols := c.DefaultQuery("cols", "150")
26+
rows := c.DefaultQuery("rows", "35")
27+
col, _ := strconv.Atoi(cols)
28+
row, _ := strconv.Atoi(rows)
29+
terminal := core.Terminal{
30+
Columns: uint32(col),
31+
Rows: uint32(row),
32+
}
33+
sshClient, err := core.DecodedMsgToSSHClient(sshInfo)
34+
if err != nil {
35+
fmt.Println(err)
36+
responseBody.Msg = err.Error()
37+
return &responseBody
38+
}
39+
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
40+
if err != nil {
41+
fmt.Println(err)
42+
responseBody.Msg = err.Error()
43+
return &responseBody
44+
}
45+
err = sshClient.GenerateClient()
46+
if err != nil {
47+
conn.WriteMessage(1, []byte(err.Error()))
48+
conn.Close()
49+
fmt.Println(err)
50+
responseBody.Msg = err.Error()
51+
return &responseBody
52+
}
53+
sshClient.InitTerminal(terminal)
54+
sshClient.Connect(conn, d)
55+
return &responseBody
56+
}

core/models.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package core
2+
3+
import (
4+
"github.com/pkg/sftp"
5+
"golang.org/x/crypto/ssh"
6+
)
7+
8+
type ptyRequestMsg struct {
9+
Term string
10+
Columns uint32
11+
Rows uint32
12+
Width uint32
13+
Height uint32
14+
Modelist string
15+
}
16+
17+
type Terminal struct {
18+
Columns uint32 `json:"cols"`
19+
Rows uint32 `json:"rows"`
20+
}
21+
22+
type SSHClient struct {
23+
Username string `json:"username"`
24+
Password string `json:"password"`
25+
IpAddress string `json:"ipaddress"`
26+
Port int `json:"port"`
27+
Session *ssh.Session
28+
Client *ssh.Client
29+
Sftp *sftp.Client
30+
channel ssh.Channel
31+
}
32+
33+
func NewSSHClient() SSHClient {
34+
client := SSHClient{}
35+
client.Username = "root"
36+
client.Port = 22
37+
return client
38+
}

core/sftpclient.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package core
2+
3+
import (
4+
"github.com/pkg/sftp"
5+
"io"
6+
"mime/multipart"
7+
)
8+
9+
func (sclient *SSHClient) CreateSftp() error {
10+
err := sclient.GenerateClient()
11+
if err != nil {
12+
return err
13+
}
14+
client, err := sftp.NewClient(sclient.Client)
15+
if err != nil {
16+
return err
17+
}
18+
sclient.Sftp = client
19+
return nil
20+
}
21+
22+
func (sclient *SSHClient) Download(srcPath string) (*sftp.File, error) {
23+
return sclient.Sftp.Open(srcPath)
24+
}
25+
26+
func (sclient *SSHClient) Upload(file multipart.File, dstPath string) error {
27+
dstFile, err := sclient.Sftp.Create(dstPath)
28+
if err != nil {
29+
return err
30+
}
31+
defer dstFile.Close()
32+
_, err = io.Copy(dstFile, file)
33+
if err != nil {
34+
return err
35+
}
36+
return nil
37+
}
38+

0 commit comments

Comments
 (0)