From f32eb006d8f148d5394ecb5ba2530116729ecfff Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Wed, 19 Nov 2025 10:09:51 -0500 Subject: [PATCH 1/7] Avoid adding multiple CSRF tokens to a URL --- .../filters/CsrfPreventionFilter.java | 85 +++++++++++++++++ .../filters/TestCsrfPreventionFilter.java | 95 +++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index 8f131439eec0..fbde08bdc0d7 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -544,6 +544,8 @@ public CsrfResponseWrapper(HttpServletResponse response, String nonceRequestPara @Override public String encodeRedirectURL(String url) { + url = removeQueryParameters(url, nonceRequestParameterName); + if (shouldAddNonce(url)) { return addNonce(super.encodeRedirectURL(url)); } else { @@ -553,6 +555,8 @@ public String encodeRedirectURL(String url) { @Override public String encodeURL(String url) { + url = removeQueryParameters(url, nonceRequestParameterName); + if (shouldAddNonce(url)) { return addNonce(super.encodeURL(url)); } else { @@ -574,6 +578,87 @@ private boolean shouldAddNonce(String url) { return true; } + public static String removeQueryParameters(String url, String parameterName) { + if(null != parameterName) { + // Check for query string + int q = url.indexOf('?'); + if(q > -1) { +// System.out.println("Found query string at position " + q); + // Check for parameter name + int pos = url.indexOf(parameterName, q + 1); + int iterations = 0; + while(pos > -1) { + if(++iterations > 100000) { + // Just in case things get out of control + throw new IllegalStateException("Way too many loop iterations"); + } +// System.out.println("url is currently: " + url); + + char c = url.charAt(pos - 1); + + if(c == '?' || c == '&') { +// System.out.println("Found parameter at position " + pos); + int next = pos + parameterName.length(); + if(url.length() > next) { +// System.out.println("URL extends beyond the parameter name " + parameterName); + c = url.charAt(next); +// System.out.println("Next character: " + c); + if(c == '&') { +// System.out.println("Trailing character is & at position " + next + "; param without value"); + // We have found our parameter without a value + url = url.substring(0, pos) + url.substring(next + 1); + } else if(c == '=') { +// System.out.println("Trailing character is = at position " + next + "; param with value"); + // We have found our parameter with a value + // Get this position before truncating + next = url.indexOf('&', next); + if(next > -1) { +// System.out.println("Found more characters at position " + next); + // There are more parameters in the URL +// System.out.println("Substring: 0-" + pos + ", " +(next-1) + "- *"); + url = url.substring(0, pos) + url.substring(next + 1); // Be sure to remove the & + + // Set pos appropriately for the next loop iteration + // pos is currently pointing at what was the start of the parameter name. + // It should now be pointing to the start of whatever comes next, + // so let's look forward. + pos = url.indexOf(parameterName, pos); + } else { +// System.out.println("Found no trailing & character"); + // Also remove the trailing '&' + url = url.substring(0, pos - 1); + + // We are done + break; + } + } else { +// System.out.println("Foil: parameter name was a prefix of the actual parameter name; skipping"); +// System.out.println("Foil: " ); + // Skip to the next & or end-of-string + next = url.indexOf('&'); + if(pos > -1) { + // Skip the & and find the next parameter + pos = url.indexOf(parameterName, next + 1); + } else { + // We are done + break; + } + } + } else { +// System.out.println("Param without suffix; truncating to " + q); + // We have ?name without any suffix. Truncate the query string. + url = url.substring(0, q); + + // We are done + break; + } + } + } + } + } + return url; + } + /* * Return the specified URL with the nonce added to the query string. * diff --git a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java index 8cf872dda87e..85679a46397f 100644 --- a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java +++ b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java @@ -25,6 +25,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jakarta.servlet.http.HttpServletResponse; @@ -196,6 +198,99 @@ public void testNoNonceMimeMatcher() { Assert.assertEquals("/foo/images/home.jpg", response.encodeURL("/foo/images/home.jpg")); } + @Test + public void testMultipleTokens() { + String nonce = "TESTNONCE"; + String testURL = "/foo/bar?" + Constants.CSRF_NONCE_SESSION_ATTR_NAME + "=sample"; + CsrfPreventionFilter.CsrfResponseWrapper response = new CsrfPreventionFilter.CsrfResponseWrapper(new NonEncodingResponse(), + Constants.CSRF_NONCE_SESSION_ATTR_NAME, nonce, null); + + Assert.assertTrue("Original URL does not contain CSRF token", + testURL.contains(Constants.CSRF_NONCE_SESSION_ATTR_NAME)); + + String result = response.encodeURL(testURL); + + int pos = result.indexOf(Constants.CSRF_NONCE_SESSION_ATTR_NAME); + Assert.assertTrue("Result URL does not contain CSRF token", + pos >= 0); + pos = result.indexOf(Constants.CSRF_NONCE_SESSION_ATTR_NAME, pos + 1); + Assert.assertFalse("Result URL contains multiple CSRF tokens: " + result, + pos >= 0); + } + + @Test + public void testURLCleansing() { + String[] urls = new String[] { + "/foo/bar", + "/foo/bar?", + "/foo/bar?csrf", + "/foo/bar?csrf=", + "/foo/bar?csrf=abc", + "/foo/bar?csrf=abc&bar=foo", + "/foo/bar?bar=foo&csrf=abc", + "/foo/bar?bar=foo&csrf=abc&foo=bar", + "/foo/bar?csrfx=foil&bar=foo&csrf=abc&foo=bar", + "/foo/bar?csrfx=foil&bar=foo&csrf=abc&foo=bar&csrf=def", + "/foo/bar?csrf=&csrf&csrf&csrf&csrf=abc&csrf=", + }; + + String csrfParameterName = "csrf"; + + for(String url : urls) { + String result = CsrfPreventionFilter.CsrfResponseWrapper.removeQueryParameters(url, csrfParameterName); + + Assert.assertEquals("Failed to cleanse URL '" + url + "' properly", dumbButAccurateCleanse(url, csrfParameterName), result); + } + + } + + private static String dumbButAccurateCleanse(String url, String csrfParameterName) { + if(url.endsWith("?")) { + // This is a special case we don't care about too much + return url; + } + + // Get rid of [&csrf=value] with optional =value + Pattern p = Pattern.compile(Pattern.quote("&") + Pattern.quote(csrfParameterName) + "(=[^&]*)?(&|$)"); + + // Do this iteratively to get everything + Matcher m = p.matcher(url); + + while(m.find()) { + url = m.replaceFirst("$2"); + m = p.matcher(url); + } + + // Get rid of [?csrf=value] with optional =value + url = url.replaceAll(Pattern.quote("?") + csrfParameterName + "(=[^&]*)?(&|$)", "?"); + + if(url.endsWith("?")) { + url = url.substring(0, url.length() - 1); + } + + return url; + } + + @Test + public void testDuplicateTokens() { + String nonce = "TESTNONCE"; + String testURL = "/foo/bar?" + Constants.CSRF_NONCE_SESSION_ATTR_NAME + "=" + nonce; + CsrfPreventionFilter.CsrfResponseWrapper response = new CsrfPreventionFilter.CsrfResponseWrapper(new NonEncodingResponse(), + Constants.CSRF_NONCE_SESSION_ATTR_NAME, nonce, null); + + Assert.assertTrue("Original URL does not contain CSRF token", + testURL.contains(Constants.CSRF_NONCE_SESSION_ATTR_NAME)); + + String result = response.encodeURL(testURL); + + int pos = result.indexOf(Constants.CSRF_NONCE_SESSION_ATTR_NAME); + Assert.assertTrue("Result URL does not contain CSRF token", + pos >= 0); + pos = result.indexOf(Constants.CSRF_NONCE_SESSION_ATTR_NAME, pos + 1); + Assert.assertFalse("Result URL contains multiple CSRF tokens: " + result, + pos >= 0); + } + private static class MimeTypeServletContext extends TesterServletContext { private String mimeType; From 459bf26c82982ac41dc3ecb58012cc7287c2d583 Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Wed, 19 Nov 2025 10:36:33 -0500 Subject: [PATCH 2/7] Add javadoc --- .../catalina/filters/CsrfPreventionFilter.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index fbde08bdc0d7..0d74163f4359 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -578,6 +578,19 @@ private boolean shouldAddNonce(String url) { return true; } + /** + * Removes zero or more query parameters from a URL. + * + * All instances of the query parameter and any associated values will be + * removed. + * + * @param url The URL whose query parameters should be removed. + * + * @param parameterName The name of the parameter to remove. + * + * @return The URL without any instances of the query parameter + * parameterName present. + */ public static String removeQueryParameters(String url, String parameterName) { if(null != parameterName) { // Check for query string From 1dcf80f057d2f006b5f8b450be3bbaa8ad98d2c4 Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Wed, 19 Nov 2025 11:53:44 -0500 Subject: [PATCH 3/7] Whitespace police --- java/org/apache/catalina/filters/CsrfPreventionFilter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index 0d74163f4359..b846375204b4 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -580,12 +580,12 @@ private boolean shouldAddNonce(String url) { /** * Removes zero or more query parameters from a URL. - * + * * All instances of the query parameter and any associated values will be * removed. - * + * * @param url The URL whose query parameters should be removed. - * + * * @param parameterName The name of the parameter to remove. * * @return The URL without any instances of the query parameter From e2b032b51e55081243939dc2d3d1f496ec5731b9 Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Wed, 19 Nov 2025 12:38:39 -0500 Subject: [PATCH 4/7] Process parameters in a more straightforward way This fixes incorrect matching of parameters whose names *end with* the CSRF token name The code is arguably easier to read --- .../filters/CsrfPreventionFilter.java | 124 +++++++++--------- .../filters/TestCsrfPreventionFilter.java | 9 +- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index b846375204b4..c1c1eeb9458e 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -593,82 +593,80 @@ private boolean shouldAddNonce(String url) { */ public static String removeQueryParameters(String url, String parameterName) { if(null != parameterName) { +// System.out.println("Removing parameter " + parameterName + " from url " + url); // Check for query string int q = url.indexOf('?'); if(q > -1) { // System.out.println("Found query string at position " + q); - // Check for parameter name - int pos = url.indexOf(parameterName, q + 1); + + // Look for parameter end + int start = q + 1; + int pos = url.indexOf('&', start); + int iterations = 0; - while(pos > -1) { + + while(-1 < pos) { + // Process all parameters +// System.out.println(":: url=" + url + ", pos=" + pos + ", start=" + start); if(++iterations > 100000) { // Just in case things get out of control throw new IllegalStateException("Way too many loop iterations"); } -// System.out.println("url is currently: " + url); - - char c = url.charAt(pos - 1); - - if(c == '?' || c == '&') { -// System.out.println("Found parameter at position " + pos); - int next = pos + parameterName.length(); - if(url.length() > next) { -// System.out.println("URL extends beyond the parameter name " + parameterName); - c = url.charAt(next); -// System.out.println("Next character: " + c); - if(c == '&') { -// System.out.println("Trailing character is & at position " + next + "; param without value"); - // We have found our parameter without a value - url = url.substring(0, pos) + url.substring(next + 1); - } else if(c == '=') { -// System.out.println("Trailing character is = at position " + next + "; param with value"); - // We have found our parameter with a value - // Get this position before truncating - next = url.indexOf('&', next); - if(next > -1) { -// System.out.println("Found more characters at position " + next); - // There are more parameters in the URL -// System.out.println("Substring: 0-" + pos + ", " +(next-1) + "- *"); - url = url.substring(0, pos) + url.substring(next + 1); // Be sure to remove the & - - // Set pos appropriately for the next loop iteration - // pos is currently pointing at what was the start of the parameter name. - // It should now be pointing to the start of whatever comes next, - // so let's look forward. - pos = url.indexOf(parameterName, pos); - } else { -// System.out.println("Found no trailing & character"); - // Also remove the trailing '&' - url = url.substring(0, pos - 1); - - // We are done - break; - } - } else { -// System.out.println("Foil: parameter name was a prefix of the actual parameter name; skipping"); -// System.out.println("Foil: " ); - // Skip to the next & or end-of-string - next = url.indexOf('&'); - if(pos > -1) { - // Skip the & and find the next parameter - pos = url.indexOf(parameterName, next + 1); - } else { - // We are done - break; - } - } - } else { -// System.out.println("Param without suffix; truncating to " + q); - // We have ?name without any suffix. Truncate the query string. - url = url.substring(0, q); - - // We are done - break; - } + + int eq = url.indexOf('=', start); + int paramNameEnd; + if(-1 == eq || eq > pos) { + paramNameEnd = pos; + // Found no equal sign at all or past next & ; Parameter is all name. + } else { + // Found this param's equal sign + paramNameEnd = eq; + } + if(parameterName.equals(url.substring(start, paramNameEnd))) { +// System.out.println("Removing parameter " + parameterName + " between index " + start + " and " + paramNameEnd); + // Remove the parameter + url = url.substring(0, start) + url.substring(pos + 1); // +1 to consume the & + } else { +// System.out.println("Not removing parameter name " + url.substring(start, paramNameEnd)); + start = pos + 1; // Go to next parameter + } + pos = url.indexOf('&', start); + } + + // Check final parameter + String paramName; +// System.out.println("Final parameter: " + url.substring(start)); + pos = url.indexOf('=', start); + + if(-1 < pos) { + paramName = url.substring(start, pos); + } else { + paramName = url.substring(start); + // No value + } + if(paramName.equals(parameterName)) { + // Remove this parameter + +// System.out.println("Removing final parameter " + parameterName); + // Remove any trailing ? or & as well + char c = url.charAt(start - 1); + if('?' == c || '&' == c) { + start--; + } + + url = url.substring(0, start); + } else { + // Remove trailing ? if it's there. Is this worth it? + int length = url.length(); + if(length == q + 1) { + url = url.substring(0, length - 1); } } } } + +// System.out.println("Returning " + url); + return url; } diff --git a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java index 85679a46397f..8c8aa826436d 100644 --- a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java +++ b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java @@ -224,7 +224,9 @@ public void testURLCleansing() { "/foo/bar", "/foo/bar?", "/foo/bar?csrf", + "/foo/bar?csrf&", "/foo/bar?csrf=", + "/foo/bar?csrf=&", "/foo/bar?csrf=abc", "/foo/bar?csrf=abc&bar=foo", "/foo/bar?bar=foo&csrf=abc", @@ -232,6 +234,8 @@ public void testURLCleansing() { "/foo/bar?csrfx=foil&bar=foo&csrf=abc&foo=bar", "/foo/bar?csrfx=foil&bar=foo&csrf=abc&foo=bar&csrf=def", "/foo/bar?csrf=&csrf&csrf&csrf&csrf=abc&csrf=", + "/foo/bar?xcsrf=&xcsrf&xcsrf&xcsrf&xcsrf=abc&xcsrf=", + "/foo/bar?xcsrf=&xcsrf&xcsrf&csrf=foo&xcsrf&xcsrf=abc&csrf=bar&xcsrf=&", }; String csrfParameterName = "csrf"; @@ -245,11 +249,6 @@ public void testURLCleansing() { } private static String dumbButAccurateCleanse(String url, String csrfParameterName) { - if(url.endsWith("?")) { - // This is a special case we don't care about too much - return url; - } - // Get rid of [&csrf=value] with optional =value Pattern p = Pattern.compile(Pattern.quote("&") + Pattern.quote(csrfParameterName) + "(=[^&]*)?(&|$)"); From 41ed18afd7b00b56c926e252ff2c0ceceb183aa5 Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Wed, 19 Nov 2025 12:42:22 -0500 Subject: [PATCH 5/7] Code style whitespace ; no functional change --- .../filters/CsrfPreventionFilter.java | 20 +++++++++---------- .../filters/TestCsrfPreventionFilter.java | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index c1c1eeb9458e..53e9fba94864 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -592,11 +592,11 @@ private boolean shouldAddNonce(String url) { * parameterName present. */ public static String removeQueryParameters(String url, String parameterName) { - if(null != parameterName) { + if (null != parameterName) { // System.out.println("Removing parameter " + parameterName + " from url " + url); // Check for query string int q = url.indexOf('?'); - if(q > -1) { + if (q > -1) { // System.out.println("Found query string at position " + q); // Look for parameter end @@ -605,24 +605,24 @@ public static String removeQueryParameters(String url, String parameterName) { int iterations = 0; - while(-1 < pos) { + while (-1 < pos) { // Process all parameters // System.out.println(":: url=" + url + ", pos=" + pos + ", start=" + start); - if(++iterations > 100000) { + if (++iterations > 100000) { // Just in case things get out of control throw new IllegalStateException("Way too many loop iterations"); } int eq = url.indexOf('=', start); int paramNameEnd; - if(-1 == eq || eq > pos) { + if (-1 == eq || eq > pos) { paramNameEnd = pos; // Found no equal sign at all or past next & ; Parameter is all name. } else { // Found this param's equal sign paramNameEnd = eq; } - if(parameterName.equals(url.substring(start, paramNameEnd))) { + if (parameterName.equals(url.substring(start, paramNameEnd))) { // System.out.println("Removing parameter " + parameterName + " between index " + start + " and " + paramNameEnd); // Remove the parameter url = url.substring(0, start) + url.substring(pos + 1); // +1 to consume the & @@ -638,19 +638,19 @@ public static String removeQueryParameters(String url, String parameterName) { // System.out.println("Final parameter: " + url.substring(start)); pos = url.indexOf('=', start); - if(-1 < pos) { + if (-1 < pos) { paramName = url.substring(start, pos); } else { paramName = url.substring(start); // No value } - if(paramName.equals(parameterName)) { + if (paramName.equals(parameterName)) { // Remove this parameter // System.out.println("Removing final parameter " + parameterName); // Remove any trailing ? or & as well char c = url.charAt(start - 1); - if('?' == c || '&' == c) { + if ('?' == c || '&' == c) { start--; } @@ -658,7 +658,7 @@ public static String removeQueryParameters(String url, String parameterName) { } else { // Remove trailing ? if it's there. Is this worth it? int length = url.length(); - if(length == q + 1) { + if (length == q + 1) { url = url.substring(0, length - 1); } } diff --git a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java index 8c8aa826436d..662a1e1710a2 100644 --- a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java +++ b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java @@ -255,7 +255,7 @@ private static String dumbButAccurateCleanse(String url, String csrfParameterNam // Do this iteratively to get everything Matcher m = p.matcher(url); - while(m.find()) { + while (m.find()) { url = m.replaceFirst("$2"); m = p.matcher(url); } @@ -263,7 +263,7 @@ private static String dumbButAccurateCleanse(String url, String csrfParameterNam // Get rid of [?csrf=value] with optional =value url = url.replaceAll(Pattern.quote("?") + csrfParameterName + "(=[^&]*)?(&|$)", "?"); - if(url.endsWith("?")) { + if (url.endsWith("?")) { url = url.substring(0, url.length() - 1); } From ab87c71424b91d0c3c6a59998ddeed1ff1905c24 Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Fri, 12 Dec 2025 09:14:25 -0500 Subject: [PATCH 6/7] Handle special case where query-string contains a ? --- .../catalina/filters/TestCsrfPreventionFilter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java index 662a1e1710a2..d053552a2ec3 100644 --- a/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java +++ b/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java @@ -236,6 +236,8 @@ public void testURLCleansing() { "/foo/bar?csrf=&csrf&csrf&csrf&csrf=abc&csrf=", "/foo/bar?xcsrf=&xcsrf&xcsrf&xcsrf&xcsrf=abc&xcsrf=", "/foo/bar?xcsrf=&xcsrf&xcsrf&csrf=foo&xcsrf&xcsrf=abc&csrf=bar&xcsrf=&", + "/foo/bar?bar=fo?&csrf=abc", + "/foo/bar?bar=fo?&csrf=abc&baz=boh", }; String csrfParameterName = "csrf"; @@ -264,7 +266,13 @@ private static String dumbButAccurateCleanse(String url, String csrfParameterNam url = url.replaceAll(Pattern.quote("?") + csrfParameterName + "(=[^&]*)?(&|$)", "?"); if (url.endsWith("?")) { - url = url.substring(0, url.length() - 1); + // Special case: it's possible to have multiple ? in a URL: + // the query-string is technically allowed to contain ? characters. + // Only trim the trailing ? if it is actually the quest-string + // separator. + if(url.lastIndexOf('?', url.length() - 2) < 0) { + url = url.substring(0, url.length() - 1); + } } return url; From f93b96f25c0d37568bb4654a6d42bbe6aeaa276e Mon Sep 17 00:00:00 2001 From: Christopher Schultz Date: Fri, 12 Dec 2025 09:15:46 -0500 Subject: [PATCH 7/7] Remove debugging System.outs --- .../apache/catalina/filters/CsrfPreventionFilter.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index 53e9fba94864..41bd83a8f29d 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -593,11 +593,9 @@ private boolean shouldAddNonce(String url) { */ public static String removeQueryParameters(String url, String parameterName) { if (null != parameterName) { -// System.out.println("Removing parameter " + parameterName + " from url " + url); // Check for query string int q = url.indexOf('?'); if (q > -1) { -// System.out.println("Found query string at position " + q); // Look for parameter end int start = q + 1; @@ -607,7 +605,6 @@ public static String removeQueryParameters(String url, String parameterName) { while (-1 < pos) { // Process all parameters -// System.out.println(":: url=" + url + ", pos=" + pos + ", start=" + start); if (++iterations > 100000) { // Just in case things get out of control throw new IllegalStateException("Way too many loop iterations"); @@ -623,11 +620,9 @@ public static String removeQueryParameters(String url, String parameterName) { paramNameEnd = eq; } if (parameterName.equals(url.substring(start, paramNameEnd))) { -// System.out.println("Removing parameter " + parameterName + " between index " + start + " and " + paramNameEnd); // Remove the parameter url = url.substring(0, start) + url.substring(pos + 1); // +1 to consume the & } else { -// System.out.println("Not removing parameter name " + url.substring(start, paramNameEnd)); start = pos + 1; // Go to next parameter } pos = url.indexOf('&', start); @@ -635,7 +630,6 @@ public static String removeQueryParameters(String url, String parameterName) { // Check final parameter String paramName; -// System.out.println("Final parameter: " + url.substring(start)); pos = url.indexOf('=', start); if (-1 < pos) { @@ -647,7 +641,6 @@ public static String removeQueryParameters(String url, String parameterName) { if (paramName.equals(parameterName)) { // Remove this parameter -// System.out.println("Removing final parameter " + parameterName); // Remove any trailing ? or & as well char c = url.charAt(start - 1); if ('?' == c || '&' == c) { @@ -665,8 +658,6 @@ public static String removeQueryParameters(String url, String parameterName) { } } -// System.out.println("Returning " + url); - return url; }