You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/11/25 18:31:55 UTC

[commons-vfs] branch master updated (39df576 -> 9abc735)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git.


    from 39df576  Bump actions/checkout from 2.3.5 to 2.4.0 #220.
     new 78bc12d  Drop useless parentheses.
     new 04ce25e  Drop useless parentheses.
     new 7878519  Reduce duplication.
     new 9abc735  [VFS-810] Percent encoded backslashes in authority of URLs aren't allowed for WebDav.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../webdav4/test/WebDav4FilesTestCase.java         |  35 +++---
 .../commons/vfs2/provider/GenericFileName.java     |   7 +-
 .../org/apache/commons/vfs2/provider/RFC2396.java  | 133 +++++++++++++++++++++
 .../apache/commons/vfs2/provider/UriParser.java    |  23 ++++
 .../vfs2/provider/http4/Http4FileSystem.java       |  10 +-
 .../vfs2/provider/http5/Http5FileSystem.java       |  10 +-
 .../provider/http4/Http4FilesCacheTestCase.java    |  96 +++++++++++++--
 .../provider/test/GenericFileNameTestCase.java     |   7 +-
 src/changes/changes.xml                            |   3 +
 9 files changed, 273 insertions(+), 51 deletions(-)
 copy commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/StandardFileSystemManagerTest.java => commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/WebDav4FilesTestCase.java (55%)
 create mode 100644 commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/RFC2396.java

[commons-vfs] 02/04: Drop useless parentheses.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit 04ce25e3f0237c2018023816faf9d4a16fdda852
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Nov 25 13:08:07 2021 -0500

    Drop useless parentheses.
---
 .../java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
index 3700025..758024d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
@@ -66,7 +66,7 @@ public class Http5FileSystem extends AbstractFileSystem {
 
         final String rootURI = getRootURI();
         final int offset = rootURI.indexOf(':');
-        final char lastCharOfScheme = (offset > 0) ? rootURI.charAt(offset - 1) : 0;
+        final char lastCharOfScheme = offset > 0 ? rootURI.charAt(offset - 1) : 0;
 
         // if scheme is 'http*s' or 'HTTP*S', then the internal base URI should be 'https'. 'http' otherwise.
         if (lastCharOfScheme == 's' || lastCharOfScheme == 'S') {

[commons-vfs] 04/04: [VFS-810] Percent encoded backslashes in authority of URLs aren't allowed for WebDav.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit 9abc7355ea4de3712fe2e79945ec48c1cd3462d7
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Nov 25 13:31:52 2021 -0500

    [VFS-810] Percent encoded backslashes in authority of URLs aren't
    allowed for WebDav.
---
 .../webdav4/test/WebDav4FilesTestCase.java         |  30 ++---
 .../commons/vfs2/provider/GenericFileName.java     |   7 +-
 .../org/apache/commons/vfs2/provider/RFC2396.java  | 133 +++++++++++++++++++++
 .../apache/commons/vfs2/provider/UriParser.java    |  23 ++++
 .../provider/http4/Http4FilesCacheTestCase.java    |  96 +++++++++++++--
 .../provider/test/GenericFileNameTestCase.java     |   7 +-
 src/changes/changes.xml                            |   3 +
 7 files changed, 263 insertions(+), 36 deletions(-)

diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/WebDav4FilesTestCase.java
similarity index 51%
copy from commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java
copy to commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/WebDav4FilesTestCase.java
index 4df8c62..c18fa0c 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java
+++ b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/WebDav4FilesTestCase.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.vfs2.provider.http4;
+package org.apache.commons.vfs2.provider.webdav4.test;
 
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileSystemException;
@@ -26,28 +26,20 @@ import org.junit.Test;
 import junit.framework.TestCase;
 
 /**
- * Tests https://issues.apache.org/jira/browse/VFS-426.
+ * Tests https://issues.apache.org/jira/browse/VFS-810.
  */
-public class Http4FilesCacheTestCase extends TestCase {
+public class WebDav4FilesTestCase extends TestCase {
 
-    /**
-     * Tests https://issues.apache.org/jira/browse/VFS-426
-     */
     @Test
-    public void testQueryStringUrls() throws FileSystemException {
-        final String noQueryStringUrl = "http4://commons.apache.org/vfs";
-        final String queryStringUrl = "http4://commons.apache.org/vfs?query=string";
-        final String queryStringUrl2 = "http4://commons.apache.org/vfs?query=string&more=stuff";
-
+    public void testUrlWithAuthority() throws FileSystemException {
+        @SuppressWarnings("resource")
         final FileSystemManager fileSystemManager = VFS.getManager();
 
-        final FileObject noQueryFile = fileSystemManager.resolveFile(noQueryStringUrl);
-        Assert.assertEquals(noQueryStringUrl, noQueryFile.getURL().toExternalForm());
-
-        final FileObject queryFile = fileSystemManager.resolveFile(queryStringUrl);
-        Assert.assertEquals(queryStringUrl, queryFile.getURL().toExternalForm()); // failed for VFS-426
-
-        final FileObject queryFile2 = fileSystemManager.resolveFile(queryStringUrl2);
-        Assert.assertEquals(queryStringUrl2, queryFile2.getURL().toExternalForm()); // failed for VFS-426
+        // TODO All lowercase input except the percent encoded '\' (%5C);
+        // We end up converting back to lowercase, but OK per RFC.
+        final String urlWithAuthority = "webdav4://alice%5C1234:secret@localhost:80";
+        try (final FileObject file = fileSystemManager.resolveFile(urlWithAuthority)) {
+            Assert.assertEquals("webdav4://alice%5c1234:secret@localhost/", file.getURL().toExternalForm());
+        }
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
index 354a1ac..a32da6c 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
@@ -25,8 +25,7 @@ import org.apache.commons.vfs2.FileType;
  * password), hostname, port, and path.
  */
 public class GenericFileName extends AbstractFileName {
-    private static final char[] USERNAME_RESERVED = { ':', '@', '/' };
-    private static final char[] PASSWORD_RESERVED = { '@', '/', '?' };
+
     private final String userName;
     private final String hostName;
     private final int defaultPort;
@@ -126,11 +125,11 @@ public class GenericFileName extends AbstractFileName {
      */
     protected void appendCredentials(final StringBuilder buffer, final boolean addPassword) {
         if (!StringUtils.isEmpty(userName)) {
-            UriParser.appendEncoded(buffer, userName, USERNAME_RESERVED);
+            UriParser.appendEncodedRfc2396(buffer, userName, RFC2396.USERINFO_UNESCAPED);
             if (password != null && !password.isEmpty()) {
                 buffer.append(':');
                 if (addPassword) {
-                    UriParser.appendEncoded(buffer, password, PASSWORD_RESERVED);
+                    UriParser.appendEncodedRfc2396(buffer, password, RFC2396.USERINFO_UNESCAPED);
                 } else {
                     buffer.append("***");
                 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/RFC2396.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/RFC2396.java
new file mode 100644
index 0000000..3fb6fca
--- /dev/null
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/RFC2396.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs2.provider;
+
+import org.apache.commons.lang3.ArraySorter;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Helps deal with <a href="https://datatracker.ietf.org/doc/html/rfc2396">RFC 2396</a>.
+ * <p>
+ * The RFC 2396 Collected BNF for URI from <a href="https://datatracker.ietf.org/doc/html/rfc2396#appendix-A">Appendix
+ * A</a>:
+ * </p>
+ * 
+ * <pre>
+      URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+      absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+
+      hier_part     = ( net_path | abs_path ) [ "?" query ]
+      opaque_part   = uric_no_slash *uric
+
+      uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+                      "&" | "=" | "+" | "$" | ","
+
+      net_path      = "//" authority [ abs_path ]
+      abs_path      = "/"  path_segments
+      rel_path      = rel_segment [ abs_path ]
+
+      rel_segment   = 1*( unreserved | escaped |
+                          ";" | "@" | "&" | "=" | "+" | "$" | "," )
+
+      scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+
+      authority     = server | reg_name
+
+      reg_name      = 1*( unreserved | escaped | "$" | "," |
+                          ";" | ":" | "@" | "&" | "=" | "+" )
+
+      server        = [ [ userinfo "@" ] hostport ]
+      userinfo      = *( unreserved | escaped |
+                         ";" | ":" | "&" | "=" | "+" | "$" | "," )
+
+      hostport      = host [ ":" port ]
+      host          = hostname | IPv4address
+      hostname      = *( domainlabel "." ) toplabel [ "." ]
+      domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+      toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
+      IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
+      port          = *digit
+
+      path          = [ abs_path | opaque_part ]
+      path_segments = segment *( "/" segment )
+      segment       = *pchar *( ";" param )
+      param         = *pchar
+      pchar         = unreserved | escaped |
+                      ":" | "@" | "&" | "=" | "+" | "$" | ","
+
+      query         = *uric
+
+      fragment      = *uric
+
+      uric          = reserved | unreserved | escaped
+      reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+                      "$" | ","
+      unreserved    = alphanum | mark
+      mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+                      "(" | ")"
+
+      escaped       = "%" hex hex
+      hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+                              "a" | "b" | "c" | "d" | "e" | "f"
+
+      alphanum      = alpha | digit
+      alpha         = lowalpha | upalpha
+
+      lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+                 "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+                 "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
+      upalpha  = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
+                 "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
+                 "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+      digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+                 "8" | "9"
+ * </pre>
+ */
+class RFC2396 {
+
+    // RFC 2396 mark
+    static final char[] MARK = {'-', '_', '.', '!', '~', '*', '\'', '(', ')'};
+
+    // RFC 2396 digit
+    static final char[] DIGIT = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+    // RFC 2396 lowalpha
+    static final char[] LOWALPHA = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+        'z'};
+
+    // RFC 2396 upalpha
+    static final char[] UPALPHA = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+        'Z'};
+
+    // RFC 2396 alpha
+    static final char[] ALPHA = ArrayUtils.addAll(LOWALPHA, UPALPHA);
+
+    // RFC 2396 alphanum
+    static final char[] ALPHANUM = ArrayUtils.addAll(ALPHA, DIGIT);
+
+    // RFC 2396 reserved
+    static final char[] RESERVED = {';', '/', '?', ':', '@', '&', '=', '+', '$', ','};
+
+    // RFC 2396 unreserved
+    static final char[] UNRESERVED = ArrayUtils.addAll(ALPHANUM, MARK);
+
+    // RFC 2396 userinfo chars which are unescaped, here sorted.
+    static final char[] USERINFO_UNESCAPED = ArraySorter.sort(ArrayUtils.addAll(UNRESERVED, ';', ':', '&', '=', '+', '$', ','));
+
+}
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
index aa24f88..d321e59 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.vfs2.provider;
 
+import java.util.Arrays;
+
 import org.apache.commons.lang3.SystemUtils;
 import org.apache.commons.vfs2.FileName;
 import org.apache.commons.vfs2.FileSystemException;
@@ -58,6 +60,12 @@ public final class UriParser {
         encode(buffer, offset, unencodedValue.length(), reserved);
     }
 
+    static void appendEncodedRfc2396(final StringBuilder buffer, final String unencodedValue, final char[] allowed) {
+        final int offset = buffer.length();
+        buffer.append(unencodedValue);
+        encodeRfc2396(buffer, offset, unencodedValue.length(), allowed);
+    }
+
     public static void canonicalizePath(final StringBuilder buffer, final int offset, final int length,
             final FileNameParser fileNameParser) throws FileSystemException {
         int index = offset;
@@ -245,6 +253,21 @@ public final class UriParser {
         }
     }
 
+    static void encodeRfc2396(final StringBuilder buffer, final int offset, final int length, final char[] allowed) {
+        int index = offset;
+        int count = length;
+        for (; count > 0; index++, count--) {
+            final char ch = buffer.charAt(index);
+            if (Arrays.binarySearch(allowed, ch) < 0) {
+                // Encode
+                final char[] digits = {Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE), Character.forDigit(ch & LOW_MASK, HEX_BASE)};
+                buffer.setCharAt(index, '%');
+                buffer.insert(index + 1, digits);
+                index += 2;
+            }
+        }
+    }
+
     /**
      * Extracts the first element of a path.
      *
diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java
index 4df8c62..ef9896a 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java
+++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/Http4FilesCacheTestCase.java
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.vfs2.provider.http4;
 
+import java.util.Locale;
+
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileSystemException;
 import org.apache.commons.vfs2.FileSystemManager;
@@ -26,28 +28,100 @@ import org.junit.Test;
 import junit.framework.TestCase;
 
 /**
- * Tests https://issues.apache.org/jira/browse/VFS-426.
+ * Tests https://issues.apache.org/jira/browse/VFS-426 and https://issues.apache.org/jira/browse/VFS-810.
  */
 public class Http4FilesCacheTestCase extends TestCase {
 
-    /**
-     * Tests https://issues.apache.org/jira/browse/VFS-426
-     */
     @Test
-    public void testQueryStringUrls() throws FileSystemException {
+    public void testQueryStringUrl0() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
+        final String noQueryStringUrl = "http4://commons.apache.org/";
+        try (final FileObject noQueryFile = fileSystemManager.resolveFile(noQueryStringUrl)) {
+            Assert.assertEquals(noQueryStringUrl, noQueryFile.getURL().toExternalForm());
+        }
+    }
+
+    @Test
+    public void testQueryStringUrl1() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
         final String noQueryStringUrl = "http4://commons.apache.org/vfs";
+        try (final FileObject noQueryFile = fileSystemManager.resolveFile(noQueryStringUrl)) {
+            Assert.assertEquals(noQueryStringUrl, noQueryFile.getURL().toExternalForm());
+        }
+    }
+
+    @Test
+    public void testQueryStringUrl2() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
         final String queryStringUrl = "http4://commons.apache.org/vfs?query=string";
+        try (final FileObject queryFile = fileSystemManager.resolveFile(queryStringUrl)) {
+            Assert.assertEquals(queryStringUrl, queryFile.getURL().toExternalForm()); // failed for VFS-426
+        }
+    }
+
+    @Test
+    public void testQueryStringUrl3() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
         final String queryStringUrl2 = "http4://commons.apache.org/vfs?query=string&more=stuff";
+        try (final FileObject queryFile2 = fileSystemManager.resolveFile(queryStringUrl2)) {
+            Assert.assertEquals(queryStringUrl2, queryFile2.getURL().toExternalForm()); // failed for VFS-426
+        }
+    }
+
+    @Test
+    public void testQueryStringUrl4() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
+        // TODO All lowercase input except the percent encoded '\' (%5C);
+        // We end up converting back to lowercase, but OK per RFC.
+        final String queryStringUrl3 = "http4://alice%5C1234:secret@localhost:8080/";
+        try (final FileObject queryFile3 = fileSystemManager.resolveFile(queryStringUrl3)) {
+            Assert.assertEquals(queryStringUrl3.toLowerCase(Locale.ROOT), queryFile3.getURL().toExternalForm());
+        }
+    }
+
+    @Test
+    public void testQueryStringUrl5() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
+        // Like testQueryStringUrl4() but with all LC input.
+        final String queryStringUrl4 = "http4://alice%5c1234:secret@localhost:8080/";
+        try (final FileObject queryFile4 = fileSystemManager.resolveFile(queryStringUrl4)) {
+            Assert.assertEquals(queryStringUrl4, queryFile4.getURL().toExternalForm());
+        }
+    }
 
+    @Test
+    public void testQueryStringUrl6() throws FileSystemException {
+        @SuppressWarnings("resource")
         final FileSystemManager fileSystemManager = VFS.getManager();
 
-        final FileObject noQueryFile = fileSystemManager.resolveFile(noQueryStringUrl);
-        Assert.assertEquals(noQueryStringUrl, noQueryFile.getURL().toExternalForm());
+        // Like testQueryStringUrl4() but with all LC input and NO percent encoding.
+        final String queryStringUrl4 = "http4://alice:secret@localhost:8080/";
+        try (final FileObject queryFile4 = fileSystemManager.resolveFile(queryStringUrl4)) {
+            Assert.assertEquals(queryStringUrl4, queryFile4.getURL().toExternalForm());
+        }
+    }
 
-        final FileObject queryFile = fileSystemManager.resolveFile(queryStringUrl);
-        Assert.assertEquals(queryStringUrl, queryFile.getURL().toExternalForm()); // failed for VFS-426
+    @Test
+    public void testQueryStringUrl7() throws FileSystemException {
+        @SuppressWarnings("resource")
+        final FileSystemManager fileSystemManager = VFS.getManager();
 
-        final FileObject queryFile2 = fileSystemManager.resolveFile(queryStringUrl2);
-        Assert.assertEquals(queryStringUrl2, queryFile2.getURL().toExternalForm()); // failed for VFS-426
+        // Like testQueryStringUrl4() but with all LC input and NO percent encoding.
+        final String queryStringUrl4 = "http4://localhost:8080/";
+        try (final FileObject queryFile4 = fileSystemManager.resolveFile(queryStringUrl4)) {
+            Assert.assertEquals(queryStringUrl4, queryFile4.getURL().toExternalForm());
+        }
     }
 }
diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/test/GenericFileNameTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/test/GenericFileNameTestCase.java
index ebfda7e..bce3939 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/test/GenericFileNameTestCase.java
+++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/test/GenericFileNameTestCase.java
@@ -134,7 +134,10 @@ public class GenericFileNameTestCase extends AbstractVfsTestCase {
         assertEquals("hostname", name.getHostName());
         assertEquals(21, name.getPort());
         assertEquals("/", name.getPath());
-        assertEquals("ftp://user%3a:%40@hostname/", name.getRootURI());
-        assertEquals("ftp://user%3a:%40@hostname/", name.getURI());
+        // RFC 2396: The ':' character in a userinfo does not have to be escaped/percent-encoded, it is NOT RECOMMENDED for use.
+        // RFC 3986: The ':' character in a userinfo is deprecated.
+        // See also https://issues.apache.org/jira/browse/VFS-810
+        assertEquals("ftp://user::%40@hostname/", name.getRootURI());
+        assertEquals("ftp://user::%40@hostname/", name.getURI());
     }
 }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d05be5d..653df06 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -56,6 +56,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="fix" dev="ggregory" due-to="wodencafe">
         (doc) Update the Javadoc link to not lead to 404. #218.
       </action>
+      <action type="fix" issue="VFS-810" dev="ggregory" due-to="Jan Aelbrecht, Gary Gregory">
+        Percent encoded backslashes in authority of URLs aren't allowed for WebDav.
+      </action>
       <!-- ADD -->
       <action type="add" dev="ggregory" due-to="Seth Falco">
         Add vscode files to gitignore #205.

[commons-vfs] 03/04: Reduce duplication.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit 78785196e1cdea917c3fff3af4c31ab5ffc35386
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Nov 25 13:31:18 2021 -0500

    Reduce duplication.
---
 .../org/apache/commons/vfs2/provider/http4/Http4FileSystem.java   | 8 ++------
 .../org/apache/commons/vfs2/provider/http5/Http5FileSystem.java   | 8 ++------
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
index 9747232..85aa472 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
@@ -69,12 +69,8 @@ public class Http4FileSystem extends AbstractFileSystem {
         final char lastCharOfScheme = offset > 0 ? rootURI.charAt(offset - 1) : 0;
 
         // if scheme is 'http*s' or 'HTTP*S', then the internal base URI should be 'https'. 'http' otherwise.
-        if (lastCharOfScheme == 's' || lastCharOfScheme == 'S') {
-            this.internalBaseURI = URI.create("https" + rootURI.substring(offset));
-        } else {
-            this.internalBaseURI = URI.create("http" + rootURI.substring(offset));
-        }
-
+        final String scheme  = lastCharOfScheme == 's' || lastCharOfScheme == 'S' ? "https" : "http";
+        this.internalBaseURI = URI.create(scheme + rootURI.substring(offset));
         this.httpClient = httpClient;
         this.httpClientContext = httpClientContext;
     }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
index 758024d..63b7c36 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http5/Http5FileSystem.java
@@ -69,12 +69,8 @@ public class Http5FileSystem extends AbstractFileSystem {
         final char lastCharOfScheme = offset > 0 ? rootURI.charAt(offset - 1) : 0;
 
         // if scheme is 'http*s' or 'HTTP*S', then the internal base URI should be 'https'. 'http' otherwise.
-        if (lastCharOfScheme == 's' || lastCharOfScheme == 'S') {
-            this.internalBaseURI = URI.create("https" + rootURI.substring(offset));
-        } else {
-            this.internalBaseURI = URI.create("http" + rootURI.substring(offset));
-        }
-
+        final String scheme  = lastCharOfScheme == 's' || lastCharOfScheme == 'S' ? "https" : "http";
+        this.internalBaseURI = URI.create(scheme + rootURI.substring(offset));
         this.httpClient = httpClient;
         this.httpClientContext = httpClientContext;
     }

[commons-vfs] 01/04: Drop useless parentheses.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit 78bc12dc40279bf4ad7ec887c0289b9a94ef1b7c
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Nov 25 13:03:34 2021 -0500

    Drop useless parentheses.
---
 .../java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
index b683157..9747232 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4/Http4FileSystem.java
@@ -66,7 +66,7 @@ public class Http4FileSystem extends AbstractFileSystem {
 
         final String rootURI = getRootURI();
         final int offset = rootURI.indexOf(':');
-        final char lastCharOfScheme = (offset > 0) ? rootURI.charAt(offset - 1) : 0;
+        final char lastCharOfScheme = offset > 0 ? rootURI.charAt(offset - 1) : 0;
 
         // if scheme is 'http*s' or 'HTTP*S', then the internal base URI should be 'https'. 'http' otherwise.
         if (lastCharOfScheme == 's' || lastCharOfScheme == 'S') {