initial import
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
parent
5d9081f0e4
commit
0b1f88c1aa
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ _testmain.go
|
|||||||
*.exe
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
*.prof
|
*.prof
|
||||||
|
go-ftp
|
||||||
|
195
main.go
Normal file
195
main.go
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
l, err := net.Listen("tcp", ":8021")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
conn, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go handle(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handle(c net.Conn) {
|
||||||
|
defer c.Close()
|
||||||
|
s, err := NewServer(c)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
}
|
||||||
|
s.ctrl.PrintfLine("220 %s [%s]", "go-ftp", c.LocalAddr())
|
||||||
|
for {
|
||||||
|
line, err := s.ctrl.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
cmd := parts[0]
|
||||||
|
params := parts[1:]
|
||||||
|
switch cmd {
|
||||||
|
case "USER":
|
||||||
|
s.cmdServerUser(params)
|
||||||
|
case "PASS":
|
||||||
|
s.cmdServerPass(params)
|
||||||
|
case "PWD":
|
||||||
|
s.cmdServerPwd(params)
|
||||||
|
case "EPSV":
|
||||||
|
s.cmdServerEpsv(params)
|
||||||
|
case "PASV":
|
||||||
|
s.cmdServerPasv(params)
|
||||||
|
case "TYPE":
|
||||||
|
s.cmdServerType(params)
|
||||||
|
case "LIST":
|
||||||
|
s.cmdServerList(params)
|
||||||
|
case "SYST":
|
||||||
|
s.cmdServerSyst(params)
|
||||||
|
case "QUIT":
|
||||||
|
s.cmdServerQuit(params)
|
||||||
|
s.Close()
|
||||||
|
return
|
||||||
|
case "SIZE":
|
||||||
|
s.cmdServerSize(params)
|
||||||
|
case "CWD":
|
||||||
|
s.cmdServerCwd(params)
|
||||||
|
case "RETR":
|
||||||
|
s.cmdServerRetr(params)
|
||||||
|
default:
|
||||||
|
fmt.Printf("%s\n", line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerUser(args []string) {
|
||||||
|
fmt.Printf("cmdServerUser: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("331 Password required for %s", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerPass(args []string) {
|
||||||
|
fmt.Printf("cmdServerPass: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("230 Logged on")
|
||||||
|
//530 Login incorrect.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerPwd(args []string) {
|
||||||
|
fmt.Printf("cmdServerPwd: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine(`257 "/" is current directory.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerEpsv(args []string) {
|
||||||
|
fmt.Printf("cmdServerEpsv: %s\n", args)
|
||||||
|
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
s.ln = ln
|
||||||
|
_, 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
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerType(args []string) {
|
||||||
|
fmt.Printf("cmdServerType: %s\n", args)
|
||||||
|
switch args[0] {
|
||||||
|
default:
|
||||||
|
s.ctrl.PrintfLine("200 Type set to %s", args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerList(args []string) {
|
||||||
|
fmt.Printf("cmdServerList: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine(`150 Opening data channel for directory listing of "%s"`, args[0])
|
||||||
|
n, err := s.data.Write([]byte("-rw-r--r-- 1 ftp ftp 4 Apr 16 2008 TEST\n"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
}
|
||||||
|
s.data.Close()
|
||||||
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||||
|
s.ctrl.PrintfLine("226 Transfer complete.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerSyst(args []string) {
|
||||||
|
fmt.Printf("cmdServerSyst: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("215 UNIX Type: L8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerQuit(args []string) {
|
||||||
|
if s.data != nil {
|
||||||
|
s.data.Close()
|
||||||
|
}
|
||||||
|
if s.ln != nil {
|
||||||
|
s.ln.Close()
|
||||||
|
}
|
||||||
|
if s.ctrl != nil {
|
||||||
|
s.ctrl.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerPasv(args []string) {
|
||||||
|
fmt.Printf("cmdServerPasv: %s\n", args)
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
s.ln = ln
|
||||||
|
host, port, _ := net.SplitHostPort(ln.Addr().String())
|
||||||
|
p0, _ := strconv.Atoi(port)
|
||||||
|
p1 := p0 / 256
|
||||||
|
p2 := p0 - p1*256
|
||||||
|
s.ctrl.PrintfLine("227 Entering Passive Mode (%s,%d,%d)", strings.Replace(host, ".", ",", -1), p1, p2)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := s.ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.data = conn
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerSize(args []string) {
|
||||||
|
fmt.Printf("cmdServerSize: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("213 %d", len([]byte("test\n")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerCwd(args []string) {
|
||||||
|
fmt.Printf("cmdServerCwd: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine("250 Okay")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Conn) cmdServerRetr(args []string) {
|
||||||
|
fmt.Printf("cmdServerRetr: %s\n", args)
|
||||||
|
s.ctrl.PrintfLine(`150 Opening data channel for file contents "%s"`, args[0])
|
||||||
|
n, err := s.data.Write([]byte("test\n"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(err.Error())
|
||||||
|
}
|
||||||
|
s.data.Close()
|
||||||
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||||
|
s.ctrl.PrintfLine("226 Transfer complete.")
|
||||||
|
|
||||||
|
}
|
20
server.go
Normal file
20
server.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/textproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Conn struct {
|
||||||
|
ctrl *textproto.Conn
|
||||||
|
data net.Conn
|
||||||
|
ln net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Close() error {
|
||||||
|
return c.ctrl.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(c net.Conn) (*Conn, error) {
|
||||||
|
return &Conn{ctrl: textproto.NewConn(c)}, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user