]> source.dussan.org Git - gitblit.git/commitdiff
Do not resolve symbolic links to repositories.
authorFlorian Zschocke <florian.zschocke@devolo.de>
Mon, 10 Jun 2019 14:37:15 +0000 (16:37 +0200)
committerFlorian Zschocke <florian.zschocke@devolo.de>
Mon, 10 Jun 2019 14:37:15 +0000 (16:37 +0200)
When symbolic links under the base repository folder point to repositories
outside the base repository folder, the forming of relative repository
names failed and resulted in NullPointerExceptions.

Create the relative path by not following symbolic links, i.e. the link
name is taken as is and not resolved to the external path.

This also changes the whole `exactPath` method to work on Paths, instead
of Files.

Fixes #891 and fixes #837.

src/main/java/com/gitblit/utils/FileUtils.java
src/test/java/com/gitblit/tests/JGitUtilsTest.java

index ad2509d0dd84b63ac02c60dc84f468036f842266..0a12229c36307f85c87f06f411fcf41bc4834d00 100644 (file)
@@ -26,6 +26,7 @@ import java.io.IOException;
 import java.io.InputStreamReader;\r
 import java.io.OutputStreamWriter;\r
 import java.nio.charset.Charset;\r
+import java.nio.file.LinkOption;\r
 import java.nio.file.Path;\r
 import java.nio.file.Paths;\r
 \r
@@ -302,8 +303,8 @@ public class FileUtils {
         * @return a relative path from basePath to path\r
         */\r
        public static String getRelativePath(File basePath, File path) {\r
-               Path exactBase = Paths.get(getExactFile(basePath).toURI());\r
-               Path exactPath = Paths.get(getExactFile(path).toURI());\r
+               Path exactBase = getExactPath(basePath);\r
+               Path exactPath = getExactPath(path);\r
                if (exactPath.startsWith(exactBase)) {\r
                        return exactBase.relativize(exactPath).toString().replace('\\', '/');\r
                }\r
@@ -312,20 +313,28 @@ public class FileUtils {
        }\r
 \r
        /**\r
-        * Returns the exact path for a file. This path will be the canonical path\r
-        * unless an exception is thrown in which case it will be the absolute path.\r
+        * Returns the exact path for a file. This path will be the real path\r
+        * with symbolic links unresolved. If that produces an IOException,\r
+        * the path will be the canonical path unless an exception is thrown\r
+        * in which case it will be the absolute path.\r
         *\r
         * @param path\r
         * @return the exact file\r
         */\r
-       public static File getExactFile(File path) {\r
+       private static Path getExactPath(File path) {\r
                try {\r
-                       return path.getCanonicalFile();\r
+                       return path.toPath().toRealPath(LinkOption.NOFOLLOW_LINKS);\r
                } catch (IOException e) {\r
-                       return path.getAbsoluteFile();\r
+                       // ignored, try next option\r
+               }\r
+               try {\r
+                       return Paths.get(path.getCanonicalPath());\r
+               } catch (IOException e) {\r
+                       return Paths.get(path.getAbsolutePath());\r
                }\r
        }\r
 \r
+\r
        public static File resolveParameter(String parameter, File aFolder, String path) {\r
                if (aFolder == null) {\r
                        // strip any parameter reference\r
index b133a8c8db0cedea0c3400622f0d540ab9c665fa..5f0835554b6129b6bc6ed46c08f39cea0285a038 100644 (file)
@@ -17,6 +17,10 @@ package com.gitblit.tests;
 \r
 import java.io.File;\r
 import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
 import java.text.SimpleDateFormat;\r
 import java.util.Arrays;\r
 import java.util.Date;\r
@@ -51,6 +55,8 @@ import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.JnaUtils;\r
 import com.gitblit.utils.StringUtils;\r
 \r
+import static org.junit.Assume.assumeTrue;\r
+\r
 public class JGitUtilsTest extends GitblitUnitTest {\r
 \r
        @Test\r
@@ -74,6 +80,117 @@ public class JGitUtilsTest extends GitblitUnitTest {
                assertTrue("No repositories found in " + GitBlitSuite.REPOSITORIES, list.size() > 0);\r
        }\r
 \r
+       @Test\r
+       public void testFindRepositoriesSymLinked() {\r
+\r
+               String reposdirName = "gitrepos";\r
+               String repositoryName = "test-linked.git";\r
+               File extrepodir = new File(GitBlitSuite.REPOSITORIES.getParent(), reposdirName);\r
+               Path symlink = null;\r
+               Path alink = null;\r
+               try {\r
+                       Path link = Paths.get( GitBlitSuite.REPOSITORIES.toString(),  "test-rln.git");\r
+                       Path target = Paths.get("../" + reposdirName,repositoryName);\r
+                       symlink = Files.createSymbolicLink(link, target);\r
+\r
+                       link = Paths.get( GitBlitSuite.REPOSITORIES.toString(),  "test-ln.git");\r
+                       target = Paths.get(extrepodir.getCanonicalPath(), repositoryName);\r
+                       alink = Files.createSymbolicLink(link, target);\r
+               }\r
+               catch (UnsupportedOperationException e) {\r
+                       assumeTrue("No symbolic links supported.", false);\r
+               }\r
+               catch (IOException ioe) {\r
+                       try {\r
+                               if (symlink != null) Files.delete(symlink);\r
+                               if (alink != null) Files.delete(alink);\r
+                       }\r
+                       catch (IOException ignored) {}\r
+                       fail(ioe.getMessage());\r
+               }\r
+\r
+\r
+               Path extDir = null;\r
+               Repository repository = null;\r
+\r
+               String testDirName = "test-linked";\r
+               String testTestDirName = "test-linked/test";\r
+               Path testDir = Paths.get(GitBlitSuite.REPOSITORIES.toString(),testDirName);\r
+               Path testTestDir = Paths.get(GitBlitSuite.REPOSITORIES.toString(),testTestDirName);\r
+               Path linkTestRepo = null;\r
+               Path linkTestTestRepo = null;\r
+               Path linkExtDir = null;\r
+               try {\r
+                       List<String> list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true, -1, null);\r
+                       int preSize = list.size();\r
+\r
+                       // Create test repo. This will make the link targets exist, so that the number of repos increases by two.\r
+                       extDir = Files.createDirectory(extrepodir.toPath());\r
+                       repository = JGitUtils.createRepository(extrepodir, repositoryName);\r
+\r
+                       list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true, -1, null);\r
+                       assertEquals("No linked repositories found in " + GitBlitSuite.REPOSITORIES, 2, (list.size() - preSize));\r
+\r
+                       list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true, -1, Arrays.asList(".*ln\\.git"));\r
+                       assertEquals("Filtering out linked repos failed.", preSize, list.size());\r
+\r
+                       // Create subdirectories and place links into them\r
+                       Files.createDirectories(testTestDir);\r
+\r
+                       Path target = Paths.get(extrepodir.getCanonicalPath(), repositoryName);\r
+                       Path link = Paths.get(testDir.toString(), "test-ln-one.git");\r
+                       linkTestRepo = Files.createSymbolicLink(link, target);\r
+                       link = Paths.get(testTestDir.toString(), "test-ln-two.git");\r
+                       linkTestTestRepo = Files.createSymbolicLink(link, target);\r
+\r
+                       list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true, -1, null);\r
+                       assertEquals("No linked repositories found in subdirectories of " + GitBlitSuite.REPOSITORIES, 4, (list.size() - preSize));\r
+                       assertTrue("Did not find linked repo test-ln-one.git", list.contains(testDirName + "/test-ln-one.git"));\r
+                       assertTrue("Did not find linked repo test-ln-two.git", list.contains(testTestDirName + "/test-ln-two.git"));\r
+                       list = JGitUtils.getRepositoryList(new File(testDir.toString()), true, true, -1, null);\r
+                       assertEquals("No linked repositories found in subdirectories of " + testDir, 2, list.size());\r
+                       assertTrue("Did not find linked repo test-ln-one.git", list.contains("test-ln-one.git"));\r
+                       assertTrue("Did not find linked repo test-ln-two.git", list.contains("test/test-ln-two.git"));\r
+\r
+\r
+                       // Create link to external directory with repos\r
+                       target = Paths.get(extrepodir.getCanonicalPath());\r
+                       link = Paths.get(testDir.toString(), "test-linked");\r
+                       linkExtDir = Files.createSymbolicLink(link, target);\r
+\r
+                       list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true, -1, null);\r
+                       assertEquals("No repositories found in linked subdirectories of " + GitBlitSuite.REPOSITORIES, 5, (list.size() - preSize));\r
+                       assertTrue("Did not find repo in linked subfolder.", list.contains(testDirName + "/test-linked/" + repositoryName));\r
+\r
+                       list = JGitUtils.getRepositoryList(new File(testDir.toString()), true, true, -1, null);\r
+                       assertEquals("No repositories found in linked subdirectories of " + testDir, 3, list.size());\r
+                       assertTrue("Did not find repo in linked subfolder.", list.contains("test-linked/" + repositoryName));\r
+\r
+               } catch (IOException e) {\r
+                       fail(e.toString());\r
+               } finally {\r
+                       try {\r
+                               if (repository != null) {\r
+                                       repository.close();\r
+                                       RepositoryCache.close(repository);\r
+                                       FileUtils.delete(repository.getDirectory(), FileUtils.RECURSIVE);\r
+                               }\r
+                               if (extDir != null) Files.delete(extDir);\r
+                               if (symlink != null) Files.delete(symlink);\r
+                               if (alink != null) Files.delete(alink);\r
+\r
+                               if (linkExtDir != null) Files.deleteIfExists(linkExtDir);\r
+                               if (linkTestTestRepo != null) Files.deleteIfExists(linkTestTestRepo);\r
+                               if (linkTestRepo != null) Files.deleteIfExists(linkTestRepo);\r
+\r
+                               Files.deleteIfExists(testTestDir);\r
+                               Files.deleteIfExists(testDir);\r
+                       }\r
+                       catch (IOException ignored) {}\r
+               }\r
+\r
+       }\r
+\r
        @Test\r
        public void testFindExclusions() {\r
                List<String> list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, null);\r