|
3 | 3 | import com.gargoylesoftware.htmlunit.Page; |
4 | 4 | import com.gargoylesoftware.htmlunit.html.HtmlPage; |
5 | 5 | import hudson.ExtensionList; |
| 6 | +import hudson.FilePath; |
6 | 7 | import hudson.model.DirectoryBrowserSupport; |
7 | 8 | import hudson.model.FreeStyleProject; |
8 | 9 | import hudson.model.Item; |
| 10 | +import hudson.model.UnprotectedRootAction; |
9 | 11 | import jenkins.model.Jenkins; |
10 | 12 | import jenkins.model.JenkinsLocationConfiguration; |
11 | 13 | import org.junit.Assert; |
|
17 | 19 | import org.jvnet.hudson.test.Issue; |
18 | 20 | import org.jvnet.hudson.test.JenkinsRule; |
19 | 21 | import org.jvnet.hudson.test.MockAuthorizationStrategy; |
| 22 | +import org.jvnet.hudson.test.TestExtension; |
| 23 | +import org.kohsuke.stapler.HttpResponse; |
20 | 24 |
|
| 25 | +import javax.annotation.CheckForNull; |
21 | 26 | import java.net.URL; |
| 27 | +import java.time.Instant; |
22 | 28 | import java.util.UUID; |
23 | 29 |
|
24 | 30 | @Issue("JENKINS-41891") |
@@ -279,4 +285,88 @@ public void adminMonitorShowsUpWithOverriddenCSP() throws Exception { |
279 | 285 | } |
280 | 286 | Assert.assertFalse(monitor.isActivated()); |
281 | 287 | } |
| 288 | + |
| 289 | + @Test |
| 290 | + public void testRedirectUrls() throws Exception { |
| 291 | + ResourceDomainRootAction rootAction = ResourceDomainRootAction.get(); |
| 292 | + String url = rootAction.getRedirectUrl(new ResourceDomainRootAction.Token("foo", "bar", Instant.now()), "foo bar baz"); |
| 293 | + Assert.assertFalse("urlencoded", url.contains(" ")); |
| 294 | + } |
| 295 | + |
| 296 | + @Test |
| 297 | + @Issue("JENKINS-59849") |
| 298 | + public void testUrlEncoding() throws Exception { |
| 299 | + FreeStyleProject project = j.createFreeStyleProject(); |
| 300 | + project.getBuildersList().add(new CreateFileBuilder("This has spaces and is 100% evil.html", "<html><body>the content</body></html>")); |
| 301 | + project.save(); |
| 302 | + |
| 303 | + j.buildAndAssertSuccess(project); |
| 304 | + |
| 305 | + JenkinsRule.WebClient webClient = j.createWebClient(); |
| 306 | + webClient.setThrowExceptionOnFailingStatusCode(false); |
| 307 | + webClient.setRedirectEnabled(true); |
| 308 | + |
| 309 | + HtmlPage page = webClient.getPage(project, "ws/This%20has%20spaces%20and%20is%20100%25%20evil.html"); |
| 310 | + Assert.assertEquals("page is found", 200, page.getWebResponse().getStatusCode()); |
| 311 | + Assert.assertTrue("page content is as expected", page.getWebResponse().getContentAsString().contains("the content")); |
| 312 | + |
| 313 | + URL url = page.getUrl(); |
| 314 | + Assert.assertTrue("page is served by resource domain", url.toString().contains("/static-files/")); |
| 315 | + } |
| 316 | + |
| 317 | + @Test |
| 318 | + @Issue("JENKINS-59849") |
| 319 | + public void testMoreUrlEncoding() throws Exception { |
| 320 | + JenkinsRule.WebClient webClient = j.createWebClient(); |
| 321 | + webClient.setThrowExceptionOnFailingStatusCode(false); |
| 322 | + webClient.setRedirectEnabled(true); |
| 323 | + |
| 324 | + Page page = webClient.goTo("100%25%20evil/%20100%25%20evil%20dir%20name%20%20%20/%20100%25%20evil%20content%20.html"); |
| 325 | + Assert.assertEquals("page is found", 200, page.getWebResponse().getStatusCode()); |
| 326 | + Assert.assertTrue("page content is as expected", page.getWebResponse().getContentAsString().contains("this is the content")); |
| 327 | + |
| 328 | + URL url = page.getUrl(); |
| 329 | + Assert.assertTrue("page is served by resource domain", url.toString().contains("/static-files/")); |
| 330 | + |
| 331 | + URL dirUrl = new URL(url.toString().replace("%20100%25%20evil%20content%20.html", "")); |
| 332 | + Page dirPage = webClient.getPage(dirUrl); |
| 333 | + Assert.assertEquals("page is found", 200, dirPage.getWebResponse().getStatusCode()); |
| 334 | + Assert.assertTrue("page content is HTML", dirPage.getWebResponse().getContentAsString().contains("href")); |
| 335 | + Assert.assertTrue("page content references file", dirPage.getWebResponse().getContentAsString().contains("evil content")); |
| 336 | + |
| 337 | + URL topDirUrl = new URL(url.toString().replace("%20100%25%20evil%20dir%20name%20%20%20/%20100%25%20evil%20content%20.html", "")); |
| 338 | + Page topDirPage = webClient.getPage(topDirUrl); |
| 339 | + Assert.assertEquals("page is found", 200, topDirPage.getWebResponse().getStatusCode()); |
| 340 | + Assert.assertTrue("page content is HTML", topDirPage.getWebResponse().getContentAsString().contains("href")); |
| 341 | + Assert.assertTrue("page content references directory", topDirPage.getWebResponse().getContentAsString().contains("evil dir name")); |
| 342 | + } |
| 343 | + |
| 344 | + @TestExtension |
| 345 | + public static class RootActionImpl implements UnprotectedRootAction { |
| 346 | + |
| 347 | + @CheckForNull |
| 348 | + @Override |
| 349 | + public String getIconFileName() { |
| 350 | + return null; |
| 351 | + } |
| 352 | + |
| 353 | + @CheckForNull |
| 354 | + @Override |
| 355 | + public String getDisplayName() { |
| 356 | + return null; |
| 357 | + } |
| 358 | + |
| 359 | + @CheckForNull |
| 360 | + @Override |
| 361 | + public String getUrlName() { |
| 362 | + return "100% evil"; |
| 363 | + } |
| 364 | + |
| 365 | + public HttpResponse doDynamic() throws Exception { |
| 366 | + Jenkins jenkins = Jenkins.get(); |
| 367 | + FilePath tempDir = jenkins.getRootPath().createTempDir("root", "tmp"); |
| 368 | + tempDir.child(" 100% evil dir name ").child(" 100% evil content .html").write("this is the content", "UTF-8"); |
| 369 | + return new DirectoryBrowserSupport(jenkins, tempDir, "title", "", true); |
| 370 | + } |
| 371 | + } |
282 | 372 | } |
0 commit comments