From c4ce260b493be64579f4a3dca7917e1f69761846 Mon Sep 17 00:00:00 2001 From: Heiko Bornholdt Date: Sat, 30 May 2020 15:59:23 +0200 Subject: [PATCH] vendor: update jlaffaye/ftp --- go.mod | 2 +- go.sum | 2 + vendor/github.com/jlaffaye/ftp/README.md | 1 + vendor/github.com/jlaffaye/ftp/ftp.go | 77 ++++++++++++++++++++-- vendor/github.com/jlaffaye/ftp/status.go | 2 + vendor/github.com/jlaffaye/ftp/walker.go | 84 ++++++++++++++++++++++++ vendor/modules.txt | 2 +- 7 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 vendor/github.com/jlaffaye/ftp/walker.go diff --git a/go.mod b/go.mod index a4afb68ca..f43a0d673 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/google/go-querystring v1.0.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/hanwen/go-fuse/v2 v2.0.3-0.20191108143333-152e6ac32d54 - github.com/jlaffaye/ftp v0.0.0-20191218041957-e1b8fdd0dcc3 + github.com/jlaffaye/ftp v0.0.0-20200422224957-b9f3ade29122 github.com/jzelinskie/whirlpool v0.0.0-20170603002051-c19460b8caa6 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect diff --git a/go.sum b/go.sum index 6903361c2..306b80e3b 100644 --- a/go.sum +++ b/go.sum @@ -208,6 +208,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY= github.com/jlaffaye/ftp v0.0.0-20191218041957-e1b8fdd0dcc3 h1:QyB6CQGLB65Al72mAIbqrkGRk56JdGMHgBziM3F0FCw= github.com/jlaffaye/ftp v0.0.0-20191218041957-e1b8fdd0dcc3/go.mod h1:PwUeyujmhaGohgOf0kJKxPfk3HcRv8QD/wAUN44go4k= +github.com/jlaffaye/ftp v0.0.0-20200422224957-b9f3ade29122 h1:dzYWuozdWNaY7mTQh5ZdmoJt2BUMavwhiux0AfGwg90= +github.com/jlaffaye/ftp v0.0.0-20200422224957-b9f3ade29122/go.mod h1:PwUeyujmhaGohgOf0kJKxPfk3HcRv8QD/wAUN44go4k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/vendor/github.com/jlaffaye/ftp/README.md b/vendor/github.com/jlaffaye/ftp/README.md index c9df01e33..8488deb9c 100644 --- a/vendor/github.com/jlaffaye/ftp/README.md +++ b/vendor/github.com/jlaffaye/ftp/README.md @@ -50,6 +50,7 @@ r, err := c.Retr("test-file.txt") if err != nil { panic(err) } +defer r.Close() buf, err := ioutil.ReadAll(r) println(string(buf)) diff --git a/vendor/github.com/jlaffaye/ftp/ftp.go b/vendor/github.com/jlaffaye/ftp/ftp.go index 376ff5e4f..341e58d2f 100644 --- a/vendor/github.com/jlaffaye/ftp/ftp.go +++ b/vendor/github.com/jlaffaye/ftp/ftp.go @@ -50,6 +50,7 @@ type dialOptions struct { context context.Context dialer net.Dialer tlsConfig *tls.Config + explicitTLS bool conn net.Conn disableEPSV bool location *time.Location @@ -90,7 +91,7 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) { if do.dialFunc != nil { tconn, err = do.dialFunc("tcp", addr) - } else if do.tlsConfig != nil { + } else if do.tlsConfig != nil && !do.explicitTLS { tconn, err = tls.DialWithDialer(&do.dialer, "tcp", addr, do.tlsConfig) } else { ctx := do.context @@ -111,15 +112,10 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) { // If we use the domain name, we might not resolve to the same IP. remoteAddr := tconn.RemoteAddr().(*net.TCPAddr) - var sourceConn io.ReadWriteCloser = tconn - if do.debugOutput != nil { - sourceConn = newDebugWrapper(tconn, do.debugOutput) - } - c := &ServerConn{ options: do, features: make(map[string]string), - conn: textproto.NewConn(sourceConn), + conn: textproto.NewConn(do.wrapConn(tconn)), host: remoteAddr.IP.String(), } @@ -129,6 +125,15 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) { return nil, err } + if do.explicitTLS { + if err := c.authTLS(); err != nil { + _ = c.Quit() + return nil, err + } + tconn = tls.Client(tconn, do.tlsConfig) + c.conn = textproto.NewConn(do.wrapConn(tconn)) + } + err = c.feat() if err != nil { c.Quit() @@ -198,6 +203,15 @@ func DialWithTLS(tlsConfig *tls.Config) DialOption { }} } +// DialWithExplicitTLS returns a DialOption that configures the ServerConn to be upgraded to TLS +// See DialWithTLS for general TLS documentation +func DialWithExplicitTLS(tlsConfig *tls.Config) DialOption { + return DialOption{func(do *dialOptions) { + do.explicitTLS = true + do.tlsConfig = tlsConfig + }} +} + // DialWithDebugOutput returns a DialOption that configures the ServerConn to write to the Writer // everything it reads from the server func DialWithDebugOutput(w io.Writer) DialOption { @@ -218,6 +232,14 @@ func DialWithDialFunc(f func(network, address string) (net.Conn, error)) DialOpt }} } +func (o *dialOptions) wrapConn(netConn net.Conn) io.ReadWriteCloser { + if o.debugOutput == nil { + return netConn + } + + return newDebugWrapper(netConn, o.debugOutput) +} + // Connect is an alias to Dial, for backward compatibility func Connect(addr string) (*ServerConn, error) { return Dial(addr) @@ -269,6 +291,12 @@ func (c *ServerConn) Login(user, password string) error { return err } +// authTLS upgrades the connection to use TLS +func (c *ServerConn) authTLS() error { + _, _, err := c.cmd(StatusAuthOK, "AUTH TLS") + return err +} + // feat issues a FEAT FTP command to list the additional commands supported by // the remote FTP server. // FEAT is described in RFC 2389 @@ -629,6 +657,27 @@ func (c *ServerConn) StorFrom(path string, r io.Reader, offset uint64) error { return err } +// Append issues a APPE FTP command to store a file to the remote FTP server. +// If a file already exists with the given path, then the content of the +// io.Reader is appended. Otherwise, a new file is created with that content. +// +// Hint: io.Pipe() can be used if an io.Writer is required. +func (c *ServerConn) Append(path string, r io.Reader) error { + conn, err := c.cmdDataConnFrom(0, "APPE %s", path) + if err != nil { + return err + } + + _, err = io.Copy(conn, r) + conn.Close() + if err != nil { + return err + } + + _, _, err = c.conn.ReadResponse(StatusClosingDataConnection) + return err +} + // Rename renames a file on the remote FTP server. func (c *ServerConn) Rename(from, to string) error { _, _, err := c.cmd(StatusRequestFilePending, "RNFR %s", from) @@ -701,6 +750,20 @@ func (c *ServerConn) RemoveDir(path string) error { return err } +//Walk prepares the internal walk function so that the caller can begin traversing the directory +func (c *ServerConn) Walk(root string) *Walker { + w := new(Walker) + w.serverConn = c + + if !strings.HasSuffix(root, "/") { + root += "/" + } + + w.root = root + + return w +} + // NoOp issues a NOOP FTP command. // NOOP has no effects and is usually used to prevent the remote FTP server to // close the otherwise idle connection. diff --git a/vendor/github.com/jlaffaye/ftp/status.go b/vendor/github.com/jlaffaye/ftp/status.go index 7d281b8b8..c8ea026c9 100644 --- a/vendor/github.com/jlaffaye/ftp/status.go +++ b/vendor/github.com/jlaffaye/ftp/status.go @@ -25,6 +25,7 @@ const ( StatusLoggedIn = 230 StatusLoggedOut = 231 StatusLogoutAck = 232 + StatusAuthOK = 234 StatusRequestedFileActionOK = 250 StatusPathCreated = 257 @@ -73,6 +74,7 @@ var statusText = map[int]string{ StatusLoggedIn: "User logged in, proceed.", StatusLoggedOut: "User logged out; service terminated.", StatusLogoutAck: "Logout command noted, will complete when transfer done.", + StatusAuthOK: "AUTH command OK", StatusRequestedFileActionOK: "Requested file action okay, completed.", StatusPathCreated: "Path created.", diff --git a/vendor/github.com/jlaffaye/ftp/walker.go b/vendor/github.com/jlaffaye/ftp/walker.go new file mode 100644 index 000000000..dacd0d8d0 --- /dev/null +++ b/vendor/github.com/jlaffaye/ftp/walker.go @@ -0,0 +1,84 @@ +package ftp + +import ( + pa "path" + "strings" +) + +//Walker traverses the directory tree of a remote FTP server +type Walker struct { + serverConn *ServerConn + root string + cur item + stack []item + descend bool +} + +type item struct { + path string + entry Entry + err error +} + +// Next advances the Walker to the next file or directory, +// which will then be available through the Path, Stat, and Err methods. +// It returns false when the walk stops at the end of the tree. +func (w *Walker) Next() bool { + if w.descend && w.cur.err == nil && w.cur.entry.Type == EntryTypeFolder { + list, err := w.serverConn.List(w.cur.path) + if err != nil { + w.cur.err = err + w.stack = append(w.stack, w.cur) + } else { + for i := len(list) - 1; i >= 0; i-- { + if !strings.HasSuffix(w.cur.path, "/") { + w.cur.path += "/" + } + + var path string + if list[i].Type == EntryTypeFolder { + path = pa.Join(w.cur.path, list[i].Name) + } else { + path = w.cur.path + } + + w.stack = append(w.stack, item{path, *list[i], nil}) + } + } + } + + if len(w.stack) == 0 { + return false + } + i := len(w.stack) - 1 + w.cur = w.stack[i] + w.stack = w.stack[:i] + w.descend = true + return true +} + +//SkipDir tells the Next function to skip the currently processed directory +func (w *Walker) SkipDir() { + w.descend = false +} + +//Err returns the error, if any, for the most recent attempt by Next to +//visit a file or a directory. If a directory has an error, the walker +//will not descend in that directory +func (w *Walker) Err() error { + return w.cur.err +} + +// Stat returns info for the most recent file or directory +// visited by a call to Step. +func (w *Walker) Stat() Entry { + return w.cur.entry +} + +// Path returns the path to the most recent file or directory +// visited by a call to Next. It contains the argument to Walk +// as a prefix; that is, if Walk is called with "dir", which is +// a directory containing the file "a", Path will return "dir/a". +func (w *Walker) Path() string { + return w.cur.path +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 5c26e8782..8ff60655d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -141,7 +141,7 @@ github.com/hanwen/go-fuse/v2/internal/utimens github.com/hanwen/go-fuse/v2/splice # github.com/inconshreveable/mousetrap v1.0.0 github.com/inconshreveable/mousetrap -# github.com/jlaffaye/ftp v0.0.0-20191218041957-e1b8fdd0dcc3 +# github.com/jlaffaye/ftp v0.0.0-20200422224957-b9f3ade29122 ## explicit github.com/jlaffaye/ftp # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af