@@ -290,6 +290,7 @@ public static boolean isAscii(String string) {
290
290
* @throws MalformedURLException if an error occurred generating the URL
291
291
*/
292
292
public static URL resolve (URL base , String relUrl ) throws MalformedURLException {
293
+ relUrl = stripControlChars (relUrl );
293
294
// workaround: java resolves '//path/file + ?foo' to '//path/?foo', not '//path/file?foo' as desired
294
295
if (relUrl .startsWith ("?" ))
295
296
relUrl = base .getPath () + relUrl ;
@@ -308,7 +309,9 @@ public static URL resolve(URL base, String relUrl) throws MalformedURLException
308
309
* @param relUrl the relative URL to resolve. (If it's already absolute, it will be returned)
309
310
* @return an absolute URL if one was able to be generated, or the empty string if not
310
311
*/
311
- public static String resolve (final String baseUrl , final String relUrl ) {
312
+ public static String resolve (String baseUrl , String relUrl ) {
313
+ // workaround: java will allow control chars in a path URL and may treat as relative, but Chrome / Firefox will strip and may see as a scheme. Normalize to browser's view.
314
+ baseUrl = stripControlChars (baseUrl ); relUrl = stripControlChars (relUrl );
312
315
try {
313
316
URL base ;
314
317
try {
@@ -327,6 +330,11 @@ public static String resolve(final String baseUrl, final String relUrl) {
327
330
}
328
331
private static final Pattern validUriScheme = Pattern .compile ("^[a-zA-Z][a-zA-Z0-9+-.]*:" );
329
332
333
+ private static final Pattern controlChars = Pattern .compile ("[\\ x00-\\ x1f]*" ); // matches ascii 0 - 31, to strip from url
334
+ private static String stripControlChars (final String input ) {
335
+ return controlChars .matcher (input ).replaceAll ("" );
336
+ }
337
+
330
338
private static final ThreadLocal <Stack <StringBuilder >> threadLocalBuilders = new ThreadLocal <Stack <StringBuilder >>() {
331
339
@ Override
332
340
protected Stack <StringBuilder > initialValue () {
0 commit comments