Skip to content
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
133a324
refactor: split OpenExternalFileAction into OpenSingleExternalFileAct…
Muskan244 Jul 8, 2025
91da0cf
Merge branch 'main' into fix-for-issue-13431
Muskan244 Jul 8, 2025
bcf3b76
Cleaned up constant name, dialog text, and removed extra comment
Muskan244 Jul 8, 2025
a8a1235
Merge branch 'main' into fix-for-issue-13431
koppor Jul 8, 2025
6ccf927
Add null checks to OpenSingleExternalFileAction constructor
Muskan244 Jul 8, 2025
4dd6694
Add @NonNull annotations and fix localization key warnings
Muskan244 Jul 8, 2025
90233e4
Merge branch 'main' into fix-for-issue-13431
Muskan244 Jul 8, 2025
dc0d67f
fix submodules
Muskan244 Jul 8, 2025
dd9ca53
Use database latest context, update button text, and add comments exp…
Muskan244 Jul 10, 2025
87b7ca9
Merge branch 'main' into fix-for-issue-13431
Muskan244 Jul 10, 2025
6c654b6
Bump org.junit.platform:junit-platform-launcher in /versions (#13505)
dependabot[bot] Jul 7, 2025
77fd7a1
Fix: clarify fallback logic, update dialog labels, and avoid null Opt…
Muskan244 Jul 11, 2025
e717e07
Fix: Make FileUtil.relativize symlink-aware for robust relative path …
Muskan244 Jul 18, 2025
22522dc
remove unnecessary comments and make test more clearer and maintainable
Muskan244 Jul 19, 2025
9f38281
Merge branch 'main' into fix-for-issue-12995
Muskan244 Jul 19, 2025
8c9257d
Refactor to avoid using exceptions for normal control flow in tryReal…
Muskan244 Jul 19, 2025
bb3b3b2
Merge branch 'fix-for-issue-12995' of https://github.com/Muskan244/ja…
Muskan244 Jul 19, 2025
b394a3c
Merge branch 'main' into fix-for-issue-12995
Muskan244 Jul 20, 2025
1d236aa
Refactored symlink tests for independence, used Files.writeString for…
Muskan244 Jul 20, 2025
5124b5f
Fix code style issues with OpenRewrite and update symlink tests
Muskan244 Jul 20, 2025
ad92c0d
Fix submodules
Muskan244 Jul 20, 2025
cb314a2
Fix submodules
Muskan244 Jul 20, 2025
c60919c
Merge branch 'main' into fix-for-issue-12995
Muskan244 Jul 24, 2025
b7f7587
Fix typo
koppor Aug 4, 2025
4270261
Refactor tests
koppor Aug 4, 2025
18fa797
Add comments to explain the logic to not use directory.relativize()
Muskan244 Aug 17, 2025
e90cafb
Merge branch 'fix-for-issue-12995' of https://github.com/Muskan244/ja…
Muskan244 Aug 17, 2025
9e1952d
Merge branch 'main' into fix-for-issue-12995
Muskan244 Aug 17, 2025
618e12a
Removed unneccesary comment
Muskan244 Aug 17, 2025
3f88a1d
Merge branch 'fix-for-issue-12995' of https://github.com/Muskan244/ja…
Muskan244 Aug 17, 2025
19d7cb3
Add ignored test for symlink escape case (#12995 comment)
Muskan244 Aug 18, 2025
be8b7f6
Tests: split relativizeSymlinks() parameterized test into separate te…
Muskan244 Aug 28, 2025
20f3a8c
Merge branch 'main' into follow-up-for-pr-13553
Muskan244 Aug 28, 2025
c0c635d
resolved checkstyle issues
Muskan244 Aug 28, 2025
44c47f1
Resolved failed test cases issue and removed unused imports
Muskan244 Aug 28, 2025
3b763cb
fix failing tests in jablib module
Muskan244 Aug 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 54 additions & 38 deletions jablib/src/test/java/org/jabref/logic/util/io/FileUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -448,70 +448,86 @@ public void cTemp() {
}
}

@ParameterizedTest
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
@MethodSource
void relativizeSymlinks(Path file, List<Path> directories, Path expected, String message) {
if (message.startsWith("IGNORED")) {
org.junit.jupiter.api.Assumptions.assumeTrue(false, message);
}
Path result = FileUtil.relativize(file, directories);
assertEquals(expected, result, message);
}

/// Tests for issue <https://github.com/JabRef/jabref/issues/12995>
static Stream<Arguments> relativizeSymlinks() throws IOException {
List<Arguments> result = new ArrayList<>();

Path realDir = bibTempDir.resolve("realDir");
@Test
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
void simpleRelativizeSymlinks() throws IOException {
Path realDir = bibTempDir.resolve("realDir_" + UUID.randomUUID());
Files.createDirectories(realDir);

// symlinkDir -> realDir
// realDir/simple.pdf
Path simpleFile = Files.createFile(realDir.resolve("simple.pdf"));
Path symlinkDir = bibTempDir.resolve("symlinkDir");
Path symlinkDir = bibTempDir.resolve("symlinkDir_" + UUID.randomUUID());
Files.createSymbolicLink(symlinkDir, realDir);
result.add(Arguments.of(simpleFile, List.of(symlinkDir), Path.of("simple.pdf"), "Simple symlink resolves to relative"));

// chainLink1 -> chainLink2 -> chainReal
// chainReal/chained.pdf
Path chainReal = bibTempDir.resolve("chainReal");
Path result = FileUtil.relativize(simpleFile, List.of(symlinkDir));
assertEquals(Path.of("simple.pdf"), result, "Simple symlink resolves to relative");
}

@Test
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
void chainedRelativizeSymlinks() throws IOException {
Path chainReal = bibTempDir.resolve("chainReal_" + UUID.randomUUID());
Files.createDirectories(chainReal);

Path chainedFile = Files.createFile(chainReal.resolve("chained.pdf"));
Path chainLink2 = bibTempDir.resolve("chainLink2");
Path chainLink2 = bibTempDir.resolve("chainLink2_" + UUID.randomUUID());
Files.createSymbolicLink(chainLink2, chainReal);
Path chainLink1 = bibTempDir.resolve("chainLink1");
Path chainLink1 = bibTempDir.resolve("chainLink1_" + UUID.randomUUID());
Files.createSymbolicLink(chainLink1, chainLink2);
result.add(Arguments.of(chainedFile, List.of(chainLink1), Path.of("chained.pdf"), "Chained symlink resolves to relative"));

// realDir/nestedLink -> realDir/nested
// realDir/nested/nested.pdf
Path nestedDir = realDir.resolve("nested");
Path result = FileUtil.relativize(chainedFile, List.of(chainLink1));
assertEquals(Path.of("chained.pdf"), result, "Chained symlink resolves to relative");
}

@Test
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
void nestedRelativizeSymlinks() throws IOException {
Path realDir = bibTempDir.resolve("realDir_" + UUID.randomUUID());
Files.createDirectories(realDir);

Path nestedDir = realDir.resolve("nested_" + UUID.randomUUID());
Files.createDirectories(nestedDir);
Path nestedFile = Files.createFile(nestedDir.resolve("nested.pdf"));
Path nestedSymlink = realDir.resolve("nestedLink");
Path nestedSymlink = realDir.resolve("nestedLink_" + UUID.randomUUID());
Files.createSymbolicLink(nestedSymlink, nestedDir);
result.add(Arguments.of(nestedFile, List.of(nestedSymlink), Path.of("nested.pdf"), "Nested symlink resolves to relative"));

// symlinkDir -> realDir
// outside.pdf
Path result = FileUtil.relativize(nestedFile, List.of(nestedSymlink));
assertEquals(Path.of("nested.pdf"), result, "Nested symlink resolves to relative");
}

@Test
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
void unrelatedFileRemainsAbsolute() throws IOException {
Path realDir = bibTempDir.resolve("realDir_" + UUID.randomUUID());
Files.createDirectories(realDir);
Path symlinkDir = bibTempDir.resolve("symlinkDir_" + UUID.randomUUID());
Files.createSymbolicLink(symlinkDir, realDir);

Path outsideFile = Files.createFile(bibTempDir.resolve("outside.pdf"));
result.add(Arguments.of(outsideFile, List.of(symlinkDir), outsideFile, "Unrelated file remains absolute"));

// symlink chain escaping base dir (ignored test case, see <https://github.com/JabRef/jabref/issues/12995#issuecomment-3065149862>)
Path result = FileUtil.relativize(outsideFile, List.of(symlinkDir));
assertEquals(outsideFile, result, "Unrelated file remains absolute");
}

@Test
@DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Symlink behavior unreliable on windows")
void symlinkEscapeCaseIgnored() throws IOException {
Path veryPrivate = bibTempDir.resolve("veryprivate");
Files.createDirectories(veryPrivate);
Path secretFile = Files.createFile(veryPrivate.resolve("a.pdf"));

Path expensive = bibTempDir.resolve("expensive");
Files.createSymbolicLink(expensive, veryPrivate);
Path things = bibTempDir.resolve("things");
Files.createSymbolicLink(things, expensive);

Path libDir = bibTempDir.resolve("lib");
Files.createDirectories(libDir);
Path bibFile = Files.createFile(libDir.resolve("bib.bib"));
result.add(Arguments.of(secretFile, List.of(things), secretFile, "IGNORED: Symlink chain escaping base dir (#12995 comment)"));
Files.createFile(libDir.resolve("bib.bib"));

return result.stream();
org.junit.jupiter.api.Assumptions.assumeTrue(false, "IGNORED: Symlink chain escaping base dir, see <https://github.com/JabRef/jabref/issues/12995#issuecomment-3065149862>");
Path result = FileUtil.relativize(secretFile, List.of(things));
assertEquals(secretFile, result);
}

/**
Expand Down