Index: openide/src/org/openide/filesystems/FileUtil.java =================================================================== RCS file: /cvs/openide/src/org/openide/filesystems/FileUtil.java,v --- openide/src/org/openide/filesystems/FileUtil.java 17 Jun 2004 18:06:14 -0000 1.103 +++ openide/src/org/openide/filesystems/FileUtil.java 22 Jul 2004 18:41:11 -0000 @@ -13,18 +13,34 @@ package org.openide.filesystems; -import org.openide.util.WeakListeners; -import java.io.*; -import java.net.URLStreamHandler; -import java.net.URL; +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.SyncFailedException; import java.net.MalformedURLException; import java.net.URI; -import java.util.*; -import java.util.jar.*; +import java.net.URL; +import java.net.URLStreamHandler; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.WeakHashMap; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import javax.swing.Icon; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileSystemView; import org.openide.ErrorManager; - -import org.openide.util.Utilities; import org.openide.util.NbBundle; +import org.openide.util.Utilities; /** Common utilities for handling files. * This is a dummy class; all methods are static. @@ -930,7 +946,13 @@ } } else { // On Unix, do not want to traverse symlinks. - file = new File(file.toURI().normalize()).getAbsoluteFile(); + if (file.getAbsolutePath().equals("/..")) { // NOI18N + // Special treatment. + file = new File("/"); // NOI18N + } else { + // URI.normalize removes ../ and ./ sequences nicely. + file = new File(file.toURI().normalize()).getAbsoluteFile(); + } } return file; } @@ -1082,6 +1104,143 @@ return index != -1 && index > urlPath.lastIndexOf('/'); } } + + /** + * Make sure that a JFileChooser does not traverse symlinks on Unix. + * @see Issue #46014 + * @see JRE bug #4906607 + * @since XXX + */ + public static void preventFileChooserSymlinkTraversal(JFileChooser jfc) { + if (!Utilities.isWindows()) { + jfc.setCurrentDirectory(wrapFileNoCanonicalize(jfc.getCurrentDirectory())); + jfc.setFileSystemView(new NonCanonicalizingFileSystemView()); + } + } + private static File wrapFileNoCanonicalize(File f) { + if (f instanceof NonCanonicalizingFile) { + return f; + } else if (f != null) { + return new NonCanonicalizingFile(f); + } else { + return null; + } + } + + private static File[] wrapFilesNoCanonicalize(File[] fs) { + if (fs != null) { + for (int i = 0; i < fs.length; i++) { + fs[i] = wrapFileNoCanonicalize(fs[i]); + } + } + return fs; + } + + private static final class NonCanonicalizingFile extends File { + public NonCanonicalizingFile(File orig) { + this(orig.getPath()); + } + private NonCanonicalizingFile(String path) { + super(path); + } + private NonCanonicalizingFile(URI uri) { + super(uri); + } + public File getCanonicalFile() throws IOException { + return wrapFileNoCanonicalize(normalizeFile(this)); + } + public String getCanonicalPath() throws IOException { + return normalizeFile(this).getAbsolutePath(); + } + public File getParentFile() { + return wrapFileNoCanonicalize(super.getParentFile()); + } + public File getAbsoluteFile() { + return wrapFileNoCanonicalize(super.getAbsoluteFile()); + } + public File[] listFiles() { + return wrapFilesNoCanonicalize(super.listFiles()); + } + public File[] listFiles(FileFilter filter) { + return wrapFilesNoCanonicalize(super.listFiles(filter)); + } + public File[] listFiles(FilenameFilter filter) { + return wrapFilesNoCanonicalize(super.listFiles(filter)); + } + } + + private static final class NonCanonicalizingFileSystemView extends FileSystemView { + private final FileSystemView delegate = FileSystemView.getFileSystemView(); + public NonCanonicalizingFileSystemView() {} + public boolean isFloppyDrive(File dir) { + return delegate.isFloppyDrive(dir); + } + public boolean isComputerNode(File dir) { + return delegate.isComputerNode(dir); + } + public File createNewFolder(File containingDir) throws IOException { + return wrapFileNoCanonicalize(delegate.createNewFolder(containingDir)); + } + public boolean isDrive(File dir) { + return delegate.isDrive(dir); + } + public boolean isFileSystemRoot(File dir) { + return delegate.isFileSystemRoot(dir); + } + public File getHomeDirectory() { + return wrapFileNoCanonicalize(delegate.getHomeDirectory()); + } + public File createFileObject(File dir, String filename) { + return wrapFileNoCanonicalize(delegate.createFileObject(dir, filename)); + } + public Boolean isTraversable(File f) { + return delegate.isTraversable(f); + } + public boolean isFileSystem(File f) { + return delegate.isFileSystem(f); + } + /* + protected File createFileSystemRoot(File f) { + return translate(delegate.createFileSystemRoot(f)); + } + */ + public File getChild(File parent, String fileName) { + return wrapFileNoCanonicalize(delegate.getChild(parent, fileName)); + } + public File getParentDirectory(File dir) { + return wrapFileNoCanonicalize(delegate.getParentDirectory(dir)); + } + public Icon getSystemIcon(File f) { + return delegate.getSystemIcon(f); + } + public boolean isParent(File folder, File file) { + return delegate.isParent(folder, file); + } + public String getSystemTypeDescription(File f) { + return delegate.getSystemTypeDescription(f); + } + public File getDefaultDirectory() { + return wrapFileNoCanonicalize(delegate.getDefaultDirectory()); + } + public String getSystemDisplayName(File f) { + return delegate.getSystemDisplayName(f); + } + public File[] getRoots() { + return wrapFilesNoCanonicalize(delegate.getRoots()); + } + public boolean isHiddenFile(File f) { + return delegate.isHiddenFile(f); + } + public File[] getFiles(File dir, boolean useFileHiding) { + return wrapFilesNoCanonicalize(delegate.getFiles(dir, useFileHiding)); + } + public boolean isRoot(File f) { + return delegate.isRoot(f); + } + public File createFileObject(String path) { + return wrapFileNoCanonicalize(delegate.createFileObject(path)); + } + } } Index: projects/projectui/src/org/netbeans/modules/project/ui/ProjectChooserAccessory.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/ProjectChooserAccessory.java,v --- projects/projectui/src/org/netbeans/modules/project/ui/ProjectChooserAccessory.java 19 Jul 2004 20:16:12 -0000 1.17 +++ projects/projectui/src/org/netbeans/modules/project/ui/ProjectChooserAccessory.java 22 Jul 2004 18:41:11 -0000 @@ -383,6 +383,7 @@ if ( defaultAccessory ) { chooser.setAccessory( new ProjectChooserAccessory( chooser, opls.isOpenSubprojects(), opls.isOpenAsMain() ) ); } + FileUtil.preventFileChooserSymlinkTraversal(chooser); chooser.setFileView( new ProjectFileView( chooser.getFileSystemView() ) ); String dir = opls.getLastOpenProjectDir();