Uploaded image for project: 'Undertow'
  1. Undertow
  2. UNDERTOW-1532

PathResourceManager doesn't seem work properly with Windows shortened file names

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Minor Minor
    • 2.2.11.Final
    • 2.0.20.Final
    • Core
    • None

      On Windows 10, when using an io.undertow.server.handlers.resource.PathResourceManager with a basePath from a shortened Windows path (like my temp file C:\Users\JEAN-S~1\AppData\Local\Temp\foo15582568227639031748), all getResource method call return null.

      This shortened Windows path is returned by default on my computer when I call Files.createTempDirectory("foo").

      This code always fails on the last assertion :

      @Test
      public void pathResourceManager_getResource_KO() throws IOException {
          // In my case, return "C:\Users\JEAN-S~1\AppData\Local\Temp\foo15582568227639031748"
          Path basePathShortened = Files.createTempDirectory("foo");
      
          File file = new File(basePathShortened.toFile(), "bar.txt");
          boolean fileCreated = file.createNewFile();
      
          assertThat(fileCreated, is(true));
      
          ResourceManager resourceManager = new PathResourceManager(basePathShortened);
          Resource resource = resourceManager.getResource("/bar.txt");
      
          assertThat(resource, is(notNullValue()));
      }
      

      If I create a PathResourceManager with the same basePath but not shortened, there is no problem.

      This code works fine :

      @Test
      public void pathResourceManager_getResource_OK() throws IOException {
          // In this case, return "C:\Users\Jean-Sébastien\AppData\Local\Temp\foo15582568227639031748"
          Path basePathShortened = Files.createTempDirectory(Paths.get("C:\\Users\\Jean-Sébastien\\AppData\\Local\\Temp"), "foo");
      
          File file = new File(basePathShortened.toFile(), "bar.txt");
          boolean fileCreated = file.createNewFile();
      
          assertThat(fileCreated, is(true));
      
          ResourceManager resourceManager = new PathResourceManager(basePathShortened);
          Resource resource = resourceManager.getResource("/bar.txt");
      
          assertThat(resource, is(notNullValue()));
      }
      

      The problem seem to be in the method isFileSameCase of the class io.undertow.server.handlers.resource.PathResourceManager :

          /**
           * Security check for case insensitive file systems.
           * We make sure the case of the filename matches the case of the request.
           * This is only a check for case sensitivity, not for non canonical . and ../ which are allowed.
           *
           * For example:
           * file.getName() == "page.jsp" && file.getCanonicalFile().getName() == "page.jsp" should return true
           * file.getName() == "page.jsp" && file.getCanonicalFile().getName() == "page.JSP" should return false
           * file.getName() == "./page.jsp" && file.getCanonicalFile().getName() == "page.jsp" should return true
           */
          private boolean isFileSameCase(final Path file, String normalizeFile) throws IOException {
              String canonicalName = file.toRealPath().toString();
              return canonicalName.equals(normalizeFile);
          }
      

      In my example :

      • file is equal to a Path of "C:\Users\JEAN-S~1\AppData\Local\Temp\foo15582568227639031748\bar.txt"
      • normalizeFile is equal to "C:\Users\JEAN-S~1\AppData\Local\Temp\foo15582568227639031748\bar.txt"
      • but the canonicalName / realPath is equal to "C:\Users\Jean-Sébastien\AppData\Local\Temp\foo2468601341669057457\bar.txt"

      So, the method call returns false when it should have returned true.

            rhn-cservice-bbaranow Bartosz Baranowski
            jsebtes Jean-Sébastien Tessier
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: