initial import

Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
Василий Толстов 2015-04-14 03:14:38 +03:00
parent 5d9081f0e4
commit 0b1f88c1aa
3 changed files with 216 additions and 0 deletions

1
.gitignore vendored
View File

@ -22,3 +22,4 @@ _testmain.go
*.exe
*.test
*.prof
go-ftp

195
main.go Normal file
View 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
View 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
}