fix
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
parent
0b1f88c1aa
commit
b5879bc146
55
info.go
Normal file
55
info.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
name string
|
||||||
|
bytes int64
|
||||||
|
links int64
|
||||||
|
mode os.FileMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) Name() string {
|
||||||
|
return info.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) Size() int64 {
|
||||||
|
return info.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) Mode() os.FileMode {
|
||||||
|
return info.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) ModTime() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) IsDir() bool {
|
||||||
|
return (info.mode | os.ModeDir) == os.ModeDir
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *FileInfo) Sys() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDirItem(name string, bytes int64, links int64) os.FileInfo {
|
||||||
|
d := new(FileInfo)
|
||||||
|
d.name = name
|
||||||
|
d.bytes = int64(bytes)
|
||||||
|
d.links = int64(links)
|
||||||
|
d.mode = os.ModeDir | 0777
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileItem(name string, bytes int64, links int64) os.FileInfo {
|
||||||
|
f := new(FileInfo)
|
||||||
|
f.name = name
|
||||||
|
f.bytes = int64(bytes)
|
||||||
|
f.links = int64(links)
|
||||||
|
f.mode = 0666
|
||||||
|
return f
|
||||||
|
}
|
39
list.go
Normal file
39
list.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/jehiah/go-strftime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type listFormatter struct {
|
||||||
|
files []os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func newListFormatter(files []os.FileInfo) *listFormatter {
|
||||||
|
f := new(listFormatter)
|
||||||
|
f.files = files
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short returns a string that lists the collection of files by name only,
|
||||||
|
// one per line
|
||||||
|
func (formatter *listFormatter) Short() string {
|
||||||
|
output := ""
|
||||||
|
for _, file := range formatter.files {
|
||||||
|
output += file.Name() + "\r\n"
|
||||||
|
}
|
||||||
|
output += "\r\n"
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detailed returns a string that lists the collection of files with extra
|
||||||
|
// detail, one per line
|
||||||
|
func (formatter *listFormatter) Detailed() string {
|
||||||
|
output := ""
|
||||||
|
for _, file := range formatter.files {
|
||||||
|
output += fmt.Sprintf("%-13s %s %-8s %-8s %8d %s %s\r\n", file.Mode().String(), "1", "1000", "1000", int(file.Size()), strftime.Format("%b %m %Y", file.ModTime()), file.Name())
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
211
main.go
211
main.go
@ -3,12 +3,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ncw/swift"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
l, err := net.Listen("tcp", ":8021")
|
l, err := net.Listen("tcp4", ":21")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
||||||
@ -23,6 +27,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
go handle(conn)
|
go handle(conn)
|
||||||
}
|
}
|
||||||
|
//56652e9028ded5ea5d4772ba80e578ce
|
||||||
|
//storage_21_1
|
||||||
|
//https://api.clodo.ru/
|
||||||
}
|
}
|
||||||
|
|
||||||
func handle(c net.Conn) {
|
func handle(c net.Conn) {
|
||||||
@ -64,10 +71,20 @@ func handle(c net.Conn) {
|
|||||||
return
|
return
|
||||||
case "SIZE":
|
case "SIZE":
|
||||||
s.cmdServerSize(params)
|
s.cmdServerSize(params)
|
||||||
case "CWD":
|
case "CWD", "XCWD":
|
||||||
s.cmdServerCwd(params)
|
s.cmdServerCwd(params)
|
||||||
case "RETR":
|
case "RETR":
|
||||||
s.cmdServerRetr(params)
|
s.cmdServerRetr(params)
|
||||||
|
case "PORT":
|
||||||
|
s.cmdServerPort(params)
|
||||||
|
case "EPRT":
|
||||||
|
s.cmdServerEprt(params)
|
||||||
|
case "LPRT":
|
||||||
|
s.cmdServerLprt(params)
|
||||||
|
case "LPSV":
|
||||||
|
s.cmdServerLpsv(params)
|
||||||
|
case "FEAT":
|
||||||
|
s.cmdServerFeat(params)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("%s\n", line)
|
fmt.Printf("%s\n", line)
|
||||||
}
|
}
|
||||||
@ -76,58 +93,104 @@ func handle(c net.Conn) {
|
|||||||
|
|
||||||
func (s *Conn) cmdServerUser(args []string) {
|
func (s *Conn) cmdServerUser(args []string) {
|
||||||
fmt.Printf("cmdServerUser: %s\n", args)
|
fmt.Printf("cmdServerUser: %s\n", args)
|
||||||
|
// s.user = args[0]
|
||||||
s.ctrl.PrintfLine("331 Password required for %s", args[0])
|
s.ctrl.PrintfLine("331 Password required for %s", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerPass(args []string) {
|
func (s *Conn) cmdServerPass(args []string) {
|
||||||
fmt.Printf("cmdServerPass: %s\n", args)
|
fmt.Printf("cmdServerPass: %s\n", args)
|
||||||
|
// s.token = args[0]
|
||||||
|
s.sw = &swift.Connection{UserName: s.user, ApiKey: s.token, AuthUrl: s.api, AuthVersion: 1}
|
||||||
|
err := s.sw.Authenticate()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
s.ctrl.PrintfLine("530 Login incorrect")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
s.ctrl.PrintfLine("230 Logged on")
|
s.ctrl.PrintfLine("230 Logged on")
|
||||||
//530 Login incorrect.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerPwd(args []string) {
|
func (s *Conn) cmdServerPwd(args []string) {
|
||||||
fmt.Printf("cmdServerPwd: %s\n", args)
|
fmt.Printf("cmdServerPwd: %s\n", args)
|
||||||
s.ctrl.PrintfLine(`257 "/" is current directory.`)
|
if s.path == "" {
|
||||||
|
s.path = "/"
|
||||||
|
}
|
||||||
|
s.ctrl.PrintfLine(`257 "%s" is current directory.`, s.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerEpsv(args []string) {
|
func (s *Conn) cmdServerEpsv(args []string) {
|
||||||
fmt.Printf("cmdServerEpsv: %s\n", args)
|
fmt.Printf("cmdServerEpsv: %s\n", args)
|
||||||
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
if s.ln == nil {
|
||||||
if err != nil {
|
ln, err := net.Listen("tcp4", fmt.Sprintf(":%d", s.port))
|
||||||
|
if err != nil {
|
||||||
}
|
fmt.Printf(err.Error())
|
||||||
s.ln = ln
|
s.ctrl.PrintfLine("425 Data connection failed")
|
||||||
_, port, _ := net.SplitHostPort(ln.Addr().String())
|
|
||||||
s.ctrl.PrintfLine("229 Entering Extended Passive Mode (|||%s|)", port)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
conn, err := s.ln.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.data = conn
|
|
||||||
}
|
}
|
||||||
}()
|
s.ln = ln
|
||||||
|
}
|
||||||
|
if s.port == 0 {
|
||||||
|
_, port, _ := net.SplitHostPort(s.ln.Addr().String())
|
||||||
|
s.port, _ = strconv.Atoi(port)
|
||||||
|
}
|
||||||
|
s.ctrl.PrintfLine("229 Entering Extended Passive Mode (|||%d|)", s.port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerType(args []string) {
|
func (s *Conn) cmdServerType(args []string) {
|
||||||
fmt.Printf("cmdServerType: %s\n", args)
|
fmt.Printf("cmdServerType: %s\n", args)
|
||||||
switch args[0] {
|
s.mode = args[0]
|
||||||
default:
|
s.ctrl.PrintfLine("200 Type set to %s", s.mode)
|
||||||
s.ctrl.PrintfLine("200 Type set to %s", args[0])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerList(args []string) {
|
func (s *Conn) cmdServerList(args []string) {
|
||||||
fmt.Printf("cmdServerList: %s\n", args)
|
fmt.Printf("cmdServerList: %s\n", args)
|
||||||
s.ctrl.PrintfLine(`150 Opening data channel for directory listing of "%s"`, args[0])
|
s.ctrl.PrintfLine(`150 Opening data channel for directory listing of "%s"`, strings.Join(args, ""))
|
||||||
n, err := s.data.Write([]byte("-rw-r--r-- 1 ftp ftp 4 Apr 16 2008 TEST\n"))
|
c, err := s.newPassiveSocket()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
s.ctrl.PrintfLine("425 Data connection failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var n int
|
||||||
|
var files []os.FileInfo
|
||||||
|
|
||||||
|
if s.path == "/" {
|
||||||
|
cnts, err := s.sw.ContainersAll(nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
files = append(files, NewDirItem(".", 4096, 0), NewDirItem("..", 4096, 0))
|
||||||
|
for _, cnt := range cnts {
|
||||||
|
it := NewDirItem(cnt.Name, cnt.Bytes, cnt.Count)
|
||||||
|
files = append(files, it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if idx := strings.Index(s.path, "/"); idx != -1 {
|
||||||
|
s.container = s.path[idx+1:]
|
||||||
|
} else {
|
||||||
|
s.container = s.path
|
||||||
|
}
|
||||||
|
objs, err := s.sw.ObjectsAll(s.container, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
files = append(files, NewDirItem(".", 4096, 0), NewDirItem("..", 4096, 0))
|
||||||
|
for _, obj := range objs {
|
||||||
|
it := NewFileItem(obj.Name, obj.Bytes, 1)
|
||||||
|
files = append(files, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ls := newListFormatter(files)
|
||||||
|
n, err = c.Write([]byte(ls.Detailed()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(err.Error())
|
fmt.Printf(err.Error())
|
||||||
}
|
}
|
||||||
s.data.Close()
|
c.Close()
|
||||||
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||||
s.ctrl.PrintfLine("226 Transfer complete.")
|
// s.ctrl.PrintfLine("226 Transfer complete.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerSyst(args []string) {
|
func (s *Conn) cmdServerSyst(args []string) {
|
||||||
@ -136,9 +199,7 @@ func (s *Conn) cmdServerSyst(args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerQuit(args []string) {
|
func (s *Conn) cmdServerQuit(args []string) {
|
||||||
if s.data != nil {
|
s.ctrl.PrintfLine("221 Goodbye")
|
||||||
s.data.Close()
|
|
||||||
}
|
|
||||||
if s.ln != nil {
|
if s.ln != nil {
|
||||||
s.ln.Close()
|
s.ln.Close()
|
||||||
}
|
}
|
||||||
@ -149,26 +210,24 @@ func (s *Conn) cmdServerQuit(args []string) {
|
|||||||
|
|
||||||
func (s *Conn) cmdServerPasv(args []string) {
|
func (s *Conn) cmdServerPasv(args []string) {
|
||||||
fmt.Printf("cmdServerPasv: %s\n", args)
|
fmt.Printf("cmdServerPasv: %s\n", args)
|
||||||
|
if s.ln == nil {
|
||||||
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
ln, err := net.Listen("tcp4", fmt.Sprintf(":%d", s.port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Printf("%s\n", err.Error())
|
||||||
|
s.ctrl.PrintfLine("425 Data connection failed")
|
||||||
|
}
|
||||||
|
s.ln = ln
|
||||||
}
|
}
|
||||||
s.ln = ln
|
host, port, _ := net.SplitHostPort(s.ln.Addr().String())
|
||||||
host, port, _ := net.SplitHostPort(ln.Addr().String())
|
|
||||||
p0, _ := strconv.Atoi(port)
|
p0, _ := strconv.Atoi(port)
|
||||||
p1 := p0 / 256
|
p1 := p0 / 256
|
||||||
p2 := p0 - p1*256
|
p2 := p0 - p1*256
|
||||||
|
s.port, _ = strconv.Atoi(port)
|
||||||
s.ctrl.PrintfLine("227 Entering Passive Mode (%s,%d,%d)", strings.Replace(host, ".", ",", -1), p1, p2)
|
s.ctrl.PrintfLine("227 Entering Passive Mode (%s,%d,%d)", strings.Replace(host, ".", ",", -1), p1, p2)
|
||||||
go func() {
|
}
|
||||||
for {
|
|
||||||
conn, err := s.ln.Accept()
|
func (s *Conn) newPassiveSocket() (net.Conn, error) {
|
||||||
if err != nil {
|
return s.ln.Accept()
|
||||||
return
|
|
||||||
}
|
|
||||||
s.data = conn
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerSize(args []string) {
|
func (s *Conn) cmdServerSize(args []string) {
|
||||||
@ -178,17 +237,71 @@ func (s *Conn) cmdServerSize(args []string) {
|
|||||||
|
|
||||||
func (s *Conn) cmdServerCwd(args []string) {
|
func (s *Conn) cmdServerCwd(args []string) {
|
||||||
fmt.Printf("cmdServerCwd: %s\n", args)
|
fmt.Printf("cmdServerCwd: %s\n", args)
|
||||||
s.ctrl.PrintfLine("250 Okay")
|
if len(args) == 0 {
|
||||||
|
s.path = "/"
|
||||||
|
} else {
|
||||||
|
s.path = filepath.Clean(args[0])
|
||||||
|
}
|
||||||
|
s.ctrl.PrintfLine(`250 "%s" is current directory.`, s.path)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerPort(args []string) {
|
||||||
|
fmt.Printf("cmdServerPort: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("501 Data connection failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerEprt(args []string) {
|
||||||
|
fmt.Printf("cmdServerEprt: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("501 Data connection failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerLprt(args []string) {
|
||||||
|
fmt.Printf("cmdServerLprt: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("501 Data connection failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerLpsv(args []string) {
|
||||||
|
fmt.Printf("cmdServerLpsv: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("501 Data connection failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerFeat(args []string) {
|
||||||
|
fmt.Printf("cmdServerFeat: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("501 Data connection failed")
|
||||||
|
return
|
||||||
|
s.ctrl.PrintfLine(`211-Extensions supported:
|
||||||
|
SIZE
|
||||||
|
RETR
|
||||||
|
CWD
|
||||||
|
PWD
|
||||||
|
QUIT
|
||||||
|
SYST
|
||||||
|
PASV
|
||||||
|
EPSV
|
||||||
|
LIST
|
||||||
|
TYPE
|
||||||
|
USER
|
||||||
|
PASS
|
||||||
|
UTF8
|
||||||
|
211 END`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Conn) cmdServerRetr(args []string) {
|
func (s *Conn) cmdServerRetr(args []string) {
|
||||||
fmt.Printf("cmdServerRetr: %s\n", args)
|
fmt.Printf("cmdServerRetr: %s\n", args)
|
||||||
s.ctrl.PrintfLine(`150 Opening data channel for file contents "%s"`, args[0])
|
s.ctrl.PrintfLine(`150 Opening data channel for file contents "%s"`, args[0])
|
||||||
n, err := s.data.Write([]byte("test\n"))
|
c, err := s.newPassiveSocket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(err.Error())
|
s.ctrl.PrintfLine("425 Data connection failed")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
s.data.Close()
|
n, err := c.Write([]byte("test\n"))
|
||||||
|
if err != nil {
|
||||||
|
s.ctrl.PrintfLine("425 Data connection failed")
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||||
s.ctrl.PrintfLine("226 Transfer complete.")
|
s.ctrl.PrintfLine("226 Transfer complete.")
|
||||||
|
|
||||||
|
18
server.go
18
server.go
@ -3,12 +3,22 @@ package main
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
|
||||||
|
"github.com/ncw/swift"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
ctrl *textproto.Conn
|
ctrl *textproto.Conn
|
||||||
data net.Conn
|
data net.Conn
|
||||||
ln net.Listener
|
ln net.Listener
|
||||||
|
port int
|
||||||
|
mode string
|
||||||
|
path string
|
||||||
|
sw *swift.Connection
|
||||||
|
user string
|
||||||
|
token string
|
||||||
|
container string
|
||||||
|
api string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Close() error {
|
func (c *Conn) Close() error {
|
||||||
@ -16,5 +26,5 @@ func (c *Conn) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(c net.Conn) (*Conn, error) {
|
func NewServer(c net.Conn) (*Conn, error) {
|
||||||
return &Conn{ctrl: textproto.NewConn(c)}, nil
|
return &Conn{api: "https://api.clodo.ru", user: "storage_21_1", token: "56652e9028ded5ea5d4772ba80e578ce", ctrl: textproto.NewConn(c)}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user