Fix HER-1792 backslashes in urls can in some cases really mean backslashes

(specifically, when they're in the query string)
* UURIFactory.java
    fixup() - replace \ with / up to the first ? in the url, instead of
    anywhere in the url
    and update comments
* UURIFactoryTest.java
    backslash test
This commit is contained in:
nlevitt
2011-04-19 02:11:20 +00:00
parent 2be8af10a9
commit b064d43db5
2 changed files with 32 additions and 14 deletions
@@ -33,18 +33,18 @@ import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.archive.util.TextUtils;
/**
* Factory that returns UURIs.
*
* Does escaping and fixup on URIs massaging in accordance with RFC2396
* and to match browser practice. For example, it removes any
* '..' if first thing in the path as per IE, converts backslashes to forward
* slashes, and discards any 'fragment'/anchor portion of the URI. This
* Does escaping and fixup on URIs massaging in accordance with RFC2396 and to
* match browser practice. For example, it removes any '..' if first thing in
* the path as per IE, converts backslashes preceding the query string to
* forward slashes, and discards any 'fragment'/anchor portion of the URI. This
* class will also fail URIs if they are longer than IE's allowed maximum
* length.
*
* <p>TODO: Test logging.
* <p>
* TODO: Test logging.
*
* @author stack
*/
@@ -173,7 +173,6 @@ public class UURIFactory extends URI {
public static final String RCURBRACKET_PATTERN = "\\}";
public static final String ESCAPED_RCURBRACKET = "%7D";
public static final String BACKSLASH = "\\";
public static final String BACKSLASH_PATTERN = "\\\\";
public static final String ESCAPED_BACKSLASH = "%5C";
public static final String STRAY_SPACING = "[\n\r\t]+";
public static final String IMPROPERESC_REPLACE = "%25$1";
@@ -357,13 +356,19 @@ public class UURIFactory extends URI {
// Get rid of any trailing spaces or new-lines.
uri = uri.trim();
// IE actually converts backslashes to slashes rather than to %5C.
// Since URIs that have backslashes usually work only with IE, we will
// convert backslashes to slashes as well.
// TODO: Maybe we can first convert backslashes by specs and than by IE
// so that we fetch both versions.
if (uri.indexOf(BACKSLASH) >= 0) {
uri = TextUtils.replaceAll(BACKSLASH_PATTERN, uri, SLASH);
// IE converts backslashes preceding the query string to slashes, rather
// than to %5C. Since URIs that have backslashes usually work only with
// IE, we will convert backslashes to slashes as well.
int nextBackslash = uri.indexOf(BACKSLASH);
if (nextBackslash >= 0) {
int queryStart = uri.indexOf('?');
StringBuilder tmp = new StringBuilder(uri);
while (nextBackslash >= 0
&& (queryStart < 0 || nextBackslash < queryStart)) {
tmp.setCharAt(nextBackslash, '/');
nextBackslash = uri.indexOf(BACKSLASH, nextBackslash + 1);
}
uri = tmp.toString();
}
// Remove stray TAB/CR/LF
@@ -1166,4 +1166,17 @@ public class UURIFactoryTest extends TestCase {
base.resolve(relative);
UURIFactory.getInstance(base,relative);
}
/**
* To match IE behavior, backslashes in path-info (really, anywhere before
* query string) assumed to be slashes, to match IE behavior. In
* query-string, they are escaped to %5C.
*
* @throws URIException
*/
public void testBackslashes() throws URIException {
UURI uuri = UURIFactory.getInstance("http:\\/www.example.com\\a/b\\c/d?q\\r\\|s/t\\v");
String expected = "http://www.example.com/a/b/c/d?q%5Cr%5C|s/t%5Cv";
assertEquals(expected, uuri.toString());
}
}