package net.minecraft.world.level.validation; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.Objects; public class DirectoryValidator { private final PathMatcher symlinkTargetAllowList; public DirectoryValidator(final PathMatcher symlinkTargetAllowList) { this.symlinkTargetAllowList = symlinkTargetAllowList; } public void validateSymlink(final Path path, final List issues) throws IOException { Path target = Files.readSymbolicLink(path); if (!this.symlinkTargetAllowList.matches(target)) { issues.add(new ForbiddenSymlinkInfo(path, target)); } } public List validateSymlink(final Path path) throws IOException { List result = new ArrayList(); this.validateSymlink(path, result); return result; } public List validateDirectory(Path directory, final boolean allowTopSymlink) throws IOException { List issues = new ArrayList(); BasicFileAttributes targetAttributes; try { targetAttributes = Files.readAttributes(directory, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); } catch (NoSuchFileException var6) { return issues; } if (targetAttributes.isRegularFile()) { throw new IOException("Path " + directory + " is not a directory"); } else { if (targetAttributes.isSymbolicLink()) { if (!allowTopSymlink) { this.validateSymlink(directory, issues); return issues; } directory = Files.readSymbolicLink(directory); } this.validateKnownDirectory(directory, issues); return issues; } } public void validateKnownDirectory(final Path directory, final List issues) throws IOException { Files.walkFileTree(directory, new SimpleFileVisitor() { { Objects.requireNonNull(DirectoryValidator.this); } private void validateSymlink(final Path path, final BasicFileAttributes attrs) throws IOException { if (attrs.isSymbolicLink()) { DirectoryValidator.this.validateSymlink(path, issues); } } public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { this.validateSymlink(dir, attrs); return super.preVisitDirectory(dir, attrs); } public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { this.validateSymlink(file, attrs); return super.visitFile(file, attrs); } }); } }