1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -22,3 +22,4 @@ _testmain.go | ||||
| *.exe | ||||
| *.test | ||||
| *.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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user