desktop: fix saving files with '[', '*', or '?' in name on Linux#6905
Open
Narasimha-sc wants to merge 2 commits into
Open
desktop: fix saving files with '[', '*', or '?' in name on Linux#6905Narasimha-sc wants to merge 2 commits into
Narasimha-sc wants to merge 2 commits into
Conversation
JFileChooser's BasicFileChooserUI treats filenames containing '[', '*', or '?' as glob patterns on Unix when the file does not exist on disk. The Save button's ApproveSelectionAction then applies a GlobFilter and returns without saving — the dialog stays open and nothing is written. Regression introduced in simplex-chat#2789 (commit 02d0094, 2023-07-28), which started pre-populating the filename via selectedFile = File(filename). Before that the save dialog ran in DIRECTORIES_ONLY mode and the JDK glob check never saw the filename. Fix: on Linux save dialogs, find the Save button by identity (BasicFileChooserUI.getApproveSelectionAction() is public and returns the exact ActionListener wired on the button) and replace it with a wrapper that delegates to the original action for non-glob names and calls approveSelection() directly for glob names. Windows (per the JDK only '*' and '?' are glob chars there) and macOS (uses AWT FileDialog) are unaffected. Open dialogs keep glob filtering for power-user search.
Earlier in this branch we added a heuristic to delegate to the
original ApproveSelectionAction for non-'[' names so that typing
'*.pdf' in the save dialog would still glob-filter the listing.
That preserved a Swing-only quirk that no native OS save dialog
implements:
- macOS uses NSSavePanel (already used in this app via AWT
FileDialog) — no glob-on-save.
- Native Windows / Linux GTK / KDE save dialogs — no glob-on-save.
- JFileChooser on Windows — has it, but '*' and '?' aren't even
legal NTFS filename chars, so users won't be typing them.
It also blocks legitimate filenames containing '*' or '?' on Linux
(legal on POSIX filesystems) from being saved, since they too get
intercepted as glob.
Replace the Save button's action with a handler that always treats
the typed text as a literal filename. The result: any filename can
be saved on Linux, behaviour aligns with macOS and with every
native OS save dialog. The open dialog is untouched, so '*.pdf'
glob-filtering there still works.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On Linux, you cannot save a received file whose name contains
[,*, or?— the Save dialog stays open and nothing is written to disk. Reproduced with[test].txt; common in practice with browser-style downloads likereport[1].pdf.Root cause
javax.swing.plaf.basic.BasicFileChooserUI.ApproveSelectionAction.actionPerformed()does this when the user clicks Save:getFileName()FileSystemView.createFileObject(name)isGlobPattern(name)istrue, it interprets the name as a glob: it callschangeDirectory(parent), sets aGlobFilteron the chooser, and returns — without ever callingapproveSelection().BasicFileChooserUI.isGlobPattern()(verified by reflection on JDK 17.0.18):/(Linux/macOS)*,?,[\(Windows)*,?So
file[1].pdf→isGlobPatterntrue → glob branch taken → save never happens. On Windows[is not a glob char per the JDK; on macOS this code base usesjava.awt.FileDialog, notJFileChooser, so neither is affected by the[case. (*and?are also intercepted as glob in the JFileChooser save dialog on Windows, but they are illegal NTFS filename chars anyway.)When this regressed
Introduced by 02d0094 / #2789 (2023-07-28, "desktop: fix creating tmpDir and providing name for file to save"). That commit started pre-populating the filename via:
Before then, the save dialog ran in
DIRECTORIES_ONLYmode — the user picked a folder and the file was written with its original name;JFileChoosernever saw the filename, so the glob branch never ran.Fix approach
BasicFileChooserUI.getApproveSelectionAction()is a public method that returns the exactActionListenerinstance wired onto the Save button. Using that we:it === listener) — no class-name string match;approveSelection()directly — bypassing the glob branch entirely.The handler is installed only when
!isLoad && desktopPlatform.isLinux():java.awt.FileDialog, different code path).!isLoad).Why bypass glob-on-save entirely (instead of only for
[)JFileChooser's glob-on-save behaviour is a Swing-only eccentricity that no native OS save dialog implements:
It also blocks legitimate POSIX filenames containing
*or?from being saved (those are legal on POSIX filesystems even though Windows forbids them).So the user-facing change on Linux is: the Save button always treats the typed text as a literal filename — matching what users get on macOS in this same app and what they get from every native OS save dialog.
Alternatives considered and rejected
java.awt.FileDialogon Linux for saveDefaultDialog.desktop.ktwarns of "graphic glitches on many Linux distributions" — that is why JFileChooser was chosen for Linux in the first place.BasicFileChooserUI.getApproveButton(JFileChooser)protected;setAccessible(true)fails under JPMS without--add-opens java.desktop/javax.swing.plaf.basic=ALL-UNNAMED. Verified on JDK 17.JFileChooser.approveSelection()in a subclassapproveSelection()is called, so an override never sees the click.actionMap["approveSelection"]entry[(and delegate for*/?)*/?, but no native OS save dialog has this feature, and it still blocks saving legitimate POSIX filenames containing*or?.FileSystemViewthat returns aFilewhoseexists()liesTest plan
[test].txt, click Save → saves correctly.*and?on Linux → save correctly.hello.txt→ unchanged behaviour.