cstamigo-droid opened a new pull request, #801:
URL: https://github.com/apache/commons-vfs/pull/801

   https://issues.apache.org/jira/browse/VFS-865
   
   `SftpFileObject` passes decoded paths to `ChannelSftp`. JSch expands `*` and 
`?` in the last path component (backslash is its escape character), so a file 
whose name contains them is treated as a glob pattern. Deleting a listed 
`a*.txt` also deletes `abc.txt`. Resolving the missing `del?.txt` matches 
`delA.txt`, which `delete()` then removes. Read, write and rename fail with `is 
not unique`. Listing a folder named `d*` returns its siblings.
   
   Separately, `doListChildrenResolved()` encodes child names with 
`UriParser.encode(name)`, which only escapes `%`. A child named `v2?final.txt` 
is then parsed as `v2` plus a query string.
   
   Changes in `SftpFileObject`:
   - New `escapeGlob(String)` escapes `\`, `*` and `?` with a backslash. It is 
applied to the paths given to `rm`, `rmdir`, `stat`, `get` (both call sites), 
`put`, `ls`, `cd`, `rename` (both paths) and `setStat`. These are the 
`ChannelSftp` methods that expand wildcards and unquote the result. `mkdir` 
does neither, so its path is left as is.
   - Child names are encoded with `UriParser.encode(name, {'?'})`. This matches 
`URLFileNameParser.encodeCharacter()`, so `getName().getBaseName()` returns 
`v2%3Ffinal.txt`, the same way a name with `%` is returned as `%25`.
   
   Tests: new `SftpFileNameWildcardTest` uses the embedded server. Eight of its 
tests fail on master and pass with this change: delete a file, delete an empty 
folder named `d*` (on master it looks non-empty and is not deleted), resolve, 
list with `?`, read, write, rename, and list a folder named `d*`. The ninth 
test covers `escapeGlob`. The class is disabled on Windows, where file names 
cannot contain `*` or `?`.
   
   Behaviour I checked in the JSch sources (0.1.55 and `com.github.mwiede:jsch` 
2.28.7, same code paths): `rm`, `rmdir` and `setStat` act on every match. 
`stat`, `get`, `put`, `cd` and the source of `rename` require exactly one 
match. `ls` and the target of `rename` glob and unquote. Paths without these 
characters reach the server unchanged.
   
   Behaviour change: code that relied on VFS passing wildcards through to JSch, 
for example `resolveFile("…/*.log").delete()` to delete every log file, now 
operates on the file literally named `*.log`. The documented way to match 
wildcards in VFS is `WildcardFileFilter` with `findFiles()`, which matches on 
the client side. Server-side expansion through JSch is undocumented, so I 
treated it as a bug. I can add a `changes.xml` entry if you want one.
   
   `mvn` (default goal) passes locally on Linux with Java 21. I also re-ran the 
downstream reproduction from the ticket with a jar built from this branch 
(Kestra plugin-fs, `atmoz/sftp`): only the named files are deleted, and the 
files literally named `del?.csv` and `b*.csv` can now be deleted.
   
   AI disclosure, per the [ASF Generative Tooling 
Guidance](https://www.apache.org/legal/generative-tooling.html): I used Claude 
(Anthropic) through Claude Code to investigate the JSch sources, write the 
change and the tests, and draft this description. I reviewed and ran 
everything, and the commit carries a `Co-Authored-By` trailer.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to