diff --git a/pkg/filesystem/ftp/client.go b/pkg/filesystem/ftp/client.go index 3c65b3f..8d4e488 100644 --- a/pkg/filesystem/ftp/client.go +++ b/pkg/filesystem/ftp/client.go @@ -3,7 +3,9 @@ package ftp import ( "context" "crypto/tls" + "github.com/pkg/errors" "io" + "net/textproto" "net/url" "time" @@ -35,7 +37,9 @@ type Pool struct { Auth *url.Userinfo MaxConnections int32 ConnectTimeout time.Duration - TLSConfig *tls.Config + + ExplicitTLS bool + TLSConfig *tls.Config count int64 } @@ -52,9 +56,16 @@ func (p *Pool) Conn(ctx context.Context, args ...any) (Conn, error) { } if p.TLSConfig != nil { - options = append(options, - ftp.DialWithTLS(p.TLSConfig), - ) + if p.ExplicitTLS { + options = append(options, + ftp.DialWithExplicitTLS(p.TLSConfig), + ) + } else { + options = append(options, + ftp.DialWithTLS(p.TLSConfig), + ) + } + } c, err := ftp.Dial(p.Addr, options...) @@ -73,7 +84,9 @@ func (p *Pool) Conn(ctx context.Context, args ...any) (Conn, error) { } } - return &conn{conn: c}, nil + return &conn{ + conn: c, + }, nil } type conn struct { @@ -89,7 +102,29 @@ func (c *conn) MakeDir(path string) error { } func (c *conn) GetEntry(path string) (*ftp.Entry, error) { - return c.conn.GetEntry(path) + e, err := c.conn.GetEntry(path) + if err != nil { + // to handle ftp MLST not support + terr := &textproto.Error{} + if errors.As(err, &terr) { + if terr.Code == ftp.StatusNotImplemented { + list, err := c.List(path) + if err != nil { + return nil, err + } + if len(list) > 0 { + return list[0], nil + } + return nil, &textproto.Error{ + Code: ftp.StatusBadFileName, + Msg: "NotFound", + } + } + } + + return nil, err + } + return e, nil } func (c *conn) Delete(name string) error { diff --git a/pkg/filesystem/ftp/config.go b/pkg/filesystem/ftp/config.go index 184ce72..0f23a6c 100644 --- a/pkg/filesystem/ftp/config.go +++ b/pkg/filesystem/ftp/config.go @@ -82,6 +82,14 @@ func (c *Config) Conn(ctx context.Context, args ...any) (Conn, error) { } p.TLSConfig.InsecureSkipVerify = d } + + if t := c.Endpoint.Extra.Get("explicitTLS"); t != "" { + d, err := strconv.ParseBool(t) + if err != nil { + return nil, err + } + p.ExplicitTLS = d + } } c.p = p