Skip to content

Commit 8f0aaff

Browse files
authored
SLING-13144: PostServlet with space in :redirect (#34)
Co-authored-by: dirk.tschentscher <orx0815@users.noreply.github.com>
1 parent 271cd07 commit 8f0aaff

2 files changed

Lines changed: 71 additions & 40 deletions

File tree

src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,19 @@ boolean redirectIfNeeded(
343343
final JakartaPostResponse htmlResponse,
344344
final SlingJakartaHttpServletResponse response)
345345
throws IOException {
346-
final String redirectURL = getRedirectUrl(request, htmlResponse);
346+
final String redirectURL = getRedirectUrl(request, htmlResponse, response);
347+
if (redirectURL != null) {
348+
log.debug("redirecting to URL [{}]", redirectURL);
349+
response.sendRedirect(redirectURL);
350+
return true;
351+
}
352+
return false;
353+
}
354+
355+
private String encodeRedirectUrl(
356+
final String redirectURL,
357+
final SlingJakartaHttpServletResponse response,
358+
final SlingJakartaHttpServletRequest request) {
347359
if (redirectURL != null) {
348360
final Matcher m = REDIRECT_WITH_SCHEME_PATTERN.matcher(redirectURL);
349361
final boolean hasScheme = m.matches();
@@ -356,11 +368,9 @@ boolean redirectIfNeeded(
356368
log.debug("Request path is [{}]", request.getPathInfo());
357369
encodedURL = response.encodeRedirectURL(redirectURL);
358370
}
359-
log.debug("redirecting to URL [{}] - encoded as [{}]", redirectURL, encodedURL);
360-
response.sendRedirect(encodedURL);
361-
return true;
371+
return encodedURL;
362372
}
363-
return false;
373+
return null;
364374
}
365375

366376
private static final Pattern REDIRECT_WITH_SCHEME_PATTERN = Pattern.compile("^(https?://[^/]+)(.*)$");
@@ -441,12 +451,16 @@ private JakartaPostOperation getSlingPostOperation(final SlingJakartaHttpServlet
441451
* @param ctx the post processor
442452
* @return the redirect location or <code>null</code>
443453
*/
444-
protected String getRedirectUrl(final SlingJakartaHttpServletRequest request, final JakartaPostResponse ctx) {
454+
private String getRedirectUrl(
455+
final SlingJakartaHttpServletRequest request,
456+
final JakartaPostResponse ctx,
457+
SlingJakartaHttpServletResponse response) {
445458
// redirect param has priority (but see below, magic star)
446459
String result = request.getParameter(SlingPostConstants.RP_REDIRECT_TO);
447460
if (result != null) {
448461
try {
449-
URI redirectUri = new URI(result);
462+
String encodedURL = encodeRedirectUrl(result, response, request);
463+
URI redirectUri = new URI(encodedURL);
450464
if (redirectUri.getAuthority() != null) {
451465
// if it has a host information
452466
log.warn(
@@ -462,42 +476,48 @@ protected String getRedirectUrl(final SlingJakartaHttpServletRequest request, fi
462476

463477
log.debug("redirect requested as [{}] for path [{}]", result, ctx.getPath());
464478

465-
// redirect to created/modified Resource
466-
final int star = result.indexOf('*');
467-
if (star >= 0 && ctx.getPath() != null) {
468-
final StringBuilder buf = new StringBuilder();
479+
result = handleStarResource(result, ctx, request);
469480

470-
// anything before the star
471-
if (star > 0) {
472-
buf.append(result.substring(0, star));
473-
}
481+
log.debug("Will redirect to {}", result);
482+
}
483+
return encodeRedirectUrl(result, response, request);
484+
}
474485

475-
// append the name of the manipulated node
476-
buf.append(ResourceUtil.getName(ctx.getPath()));
486+
private String handleStarResource(
487+
String result, final JakartaPostResponse ctx, final SlingJakartaHttpServletRequest request) {
488+
// redirect to created/modified Resource
489+
final int star = result.indexOf('*');
490+
if (star >= 0 && ctx.getPath() != null) {
491+
final StringBuilder buf = new StringBuilder();
477492

478-
// anything after the star
479-
if (star < result.length() - 1) {
480-
buf.append(result.substring(star + 1));
481-
}
493+
// anything before the star
494+
if (star > 0) {
495+
buf.append(result.substring(0, star));
496+
}
482497

483-
// Prepend request path if it ends with create suffix and result isn't absolute
484-
final String requestPath = request.getPathInfo();
485-
if (requestPath.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)
486-
&& buf.charAt(0) != '/'
487-
&& !REDIRECT_WITH_SCHEME_PATTERN.matcher(buf).matches()) {
488-
buf.insert(0, requestPath);
489-
}
498+
// append the name of the manipulated node
499+
buf.append(ResourceUtil.getName(ctx.getPath()));
490500

491-
// use the created path as the redirect result
492-
result = buf.toString();
501+
// anything after the star
502+
if (star < result.length() - 1) {
503+
buf.append(result.substring(star + 1));
504+
}
493505

494-
} else if (result.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)) {
495-
// if the redirect has a trailing slash, append modified node
496-
// name
497-
result = result.concat(ResourceUtil.getName(ctx.getPath()));
506+
// Prepend request path if it ends with create suffix and result isn't absolute
507+
final String requestPath = request.getPathInfo();
508+
if (requestPath.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)
509+
&& buf.charAt(0) != '/'
510+
&& !REDIRECT_WITH_SCHEME_PATTERN.matcher(buf).matches()) {
511+
buf.insert(0, requestPath);
498512
}
499513

500-
log.debug("Will redirect to {}", result);
514+
// use the created path as the redirect result
515+
result = buf.toString();
516+
517+
} else if (result.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)) {
518+
// if the redirect has a trailing slash, append modified node
519+
// name
520+
result = result.concat(ResourceUtil.getName(ctx.getPath()));
501521
}
502522
return result;
503523
}

src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
package org.apache.sling.servlets.post.impl;
2020

2121
import java.io.IOException;
22-
import java.io.UnsupportedEncodingException;
23-
import java.net.URLEncoder;
2422
import java.util.StringTokenizer;
2523

2624
import junit.framework.TestCase;
25+
import org.apache.commons.httpclient.URIException;
26+
import org.apache.commons.httpclient.util.URIUtil;
27+
import org.apache.commons.lang3.StringUtils;
2728
import org.apache.sling.api.SlingJakartaHttpServletRequest;
2829
import org.apache.sling.api.request.builder.Builders;
2930
import org.apache.sling.api.request.header.JakartaMediaRangeList;
@@ -190,6 +191,9 @@ public void testRedirection() throws Exception {
190191
testRedirection("/", "/fred/abc", "https://forced.com/test", null);
191192
// invalid URI
192193
testRedirection("/", "/fred/abc", "file://c:\\Users\\workspace\\test.java", null);
194+
195+
// test redirect with spaces in path
196+
testRedirection("/", "/", "/my space.html?q=hello+space", "/my%20space.html?q=hello+space");
193197
}
194198

195199
private void testRedirection(String requestPath, String resourcePath, String redirect, String expected)
@@ -236,21 +240,28 @@ public RedirectServletResponse() {
236240

237241
@Override
238242
public String encodeRedirectURL(String s) {
239-
StringTokenizer st = new StringTokenizer(s, "/", true);
243+
244+
String pathPart = StringUtils.substringBefore(s, "?");
245+
StringTokenizer st = new StringTokenizer(pathPart, "/", true);
240246
StringBuilder sb = new StringBuilder();
241247
try {
242248
while (st.hasMoreTokens()) {
243249
String token = st.nextToken();
244250
if ("/".equals(token)) {
245251
sb.append(token);
246252
} else {
247-
sb.append(URLEncoder.encode(token, "UTF-8"));
253+
// URLEncoder would replace ' ' with '+'. Needs to be '%20' as the real wrapper does too
254+
sb.append(URIUtil.encodeWithinPath(token, "UTF-8"));
248255
}
249256
}
250-
} catch (UnsupportedEncodingException e) {
257+
} catch (URIException e) {
251258
fail("Should have UTF-8?? " + e);
252259
return null;
253260
}
261+
String queryPart = StringUtils.substringAfter(s, "?");
262+
if (StringUtils.isNotEmpty(queryPart)) {
263+
sb.append("?").append(queryPart);
264+
}
254265
return sb.toString();
255266
}
256267

0 commit comments

Comments
 (0)