ftpd: fix wildcards handling for backend with virtual dirs

Fixes #915

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-07-12 12:04:01 +02:00
parent 20e8cb898a
commit 8fc4971df1
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB

View file

@ -27,7 +27,8 @@ var (
// It implements common.ActiveConnection and ftpserver.ClientDriver interfaces // It implements common.ActiveConnection and ftpserver.ClientDriver interfaces
type Connection struct { type Connection struct {
*common.BaseConnection *common.BaseConnection
clientContext ftpserver.ClientContext clientContext ftpserver.ClientContext
doWildcardListDir bool
} }
func (c *Connection) getFTPMode() string { func (c *Connection) getFTPMode() string {
@ -140,6 +141,7 @@ func (c *Connection) Rename(oldname, newname string) error {
// if any happens // if any happens
func (c *Connection) Stat(name string) (os.FileInfo, error) { func (c *Connection) Stat(name string) (os.FileInfo, error) {
c.UpdateLastActivity() c.UpdateLastActivity()
c.doWildcardListDir = false
if !c.User.HasPerm(dataprovider.PermListItems, path.Dir(name)) { if !c.User.HasPerm(dataprovider.PermListItems, path.Dir(name)) {
return nil, c.GetPermissionDeniedError() return nil, c.GetPermissionDeniedError()
@ -147,7 +149,8 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) {
fi, err := c.DoStat(name, 0, true) fi, err := c.DoStat(name, 0, true)
if err != nil { if err != nil {
if c.isListDirWithWildcards(path.Base(name), os.ErrNotExist) { if c.isListDirWithWildcards(path.Base(name)) {
c.doWildcardListDir = true
return vfs.NewFileInfo(name, true, 0, time.Now(), false), nil return vfs.NewFileInfo(name, true, 0, time.Now(), false), nil
} }
return nil, err return nil, err
@ -277,17 +280,16 @@ func (c *Connection) Symlink(oldname, newname string) error {
func (c *Connection) ReadDir(name string) ([]os.FileInfo, error) { func (c *Connection) ReadDir(name string) ([]os.FileInfo, error) {
c.UpdateLastActivity() c.UpdateLastActivity()
files, err := c.ListDir(name) if c.doWildcardListDir {
if err != nil { c.doWildcardListDir = false
baseName := path.Base(name) baseName := path.Base(name)
if c.isListDirWithWildcards(baseName, err) { // we only support wildcards for the last path level, for example:
// we only support wildcards for the last path level, for example: // - *.xml is supported
// - *.xml is supported // - dir*/*.xml is not supported
// - dir*/*.xml is not supported return c.getListDirWithWildcards(path.Dir(name), baseName)
return c.getListDirWithWildcards(path.Dir(name), baseName)
}
} }
return files, err
return c.ListDir(name)
} }
// GetHandle implements ClientDriverExtentionFileTransfer // GetHandle implements ClientDriverExtentionFileTransfer
@ -510,12 +512,10 @@ func (c *Connection) getListDirWithWildcards(dirName, pattern string) ([]os.File
return files[:validIdx], nil return files[:validIdx], nil
} }
func (c *Connection) isListDirWithWildcards(name string, err error) bool { func (c *Connection) isListDirWithWildcards(name string) bool {
if errors.Is(err, c.GetNotExistError()) { if strings.ContainsAny(name, "*?[]") {
lastCommand := c.clientContext.GetLastCommand() lastCommand := c.clientContext.GetLastCommand()
if lastCommand == "LIST" || lastCommand == "NLST" { return lastCommand == "LIST" || lastCommand == "NLST"
return strings.ContainsAny(name, "*?[]")
}
} }
return false return false
} }