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 | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user