Commit 1462460f authored by alexpott's avatar alexpott

Issue #2512452 by dawehner, pwolanin, fnqgpc: Confirm form cancel button can...

Issue #2512452 by dawehner, pwolanin, fnqgpc: Confirm form cancel button can lead to external domain
parent 59469bfa
......@@ -30,14 +30,20 @@ class ConfirmFormHelper {
public static function buildCancelLink(ConfirmFormInterface $form, Request $request) {
// Prepare cancel link.
$query = $request->query;
$url = NULL;
// If a destination is specified, that serves as the cancel link.
if ($query->has('destination')) {
$options = UrlHelper::parse($query->get('destination'));
// @todo Revisit this in https://www.drupal.org/node/2418219.
$url = Url::fromUserInput('/' . ltrim($options['path'], '/'), $options);
try {
$url = Url::fromUserInput('/' . ltrim($options['path'], '/'), $options);
}
catch (\InvalidArgumentException $e) {
// Suppress the exception and fall back to the form's cancel url.
}
}
// Check for a route-based cancel link.
else {
if (!$url) {
$url = $form->getCancelUrl();
}
......
......@@ -232,7 +232,7 @@ public static function fromUserInput($user_input, $options = []) {
// because these are URI reserved characters that a scheme name may not
// start with.
if ((strpos($user_input, '/') !== 0) && (strpos($user_input, '#') !== 0) && (strpos($user_input, '?') !== 0)) {
throw new \InvalidArgumentException(SafeMarkup::format("The user-entered string @user_input must begin with a '/', '?', or '#'.", ['@user_input' => $user_input]));
throw new \InvalidArgumentException(sprintf("The user-entered string %s must begin with a '/', '?', or '#'.", $user_input));
}
// fromUri() requires an absolute URI, so prepend the appropriate scheme
......@@ -296,10 +296,10 @@ public static function fromUserInput($user_input, $options = []) {
public static function fromUri($uri, $options = []) {
$uri_parts = parse_url($uri);
if ($uri_parts === FALSE) {
throw new \InvalidArgumentException(SafeMarkup::format('The URI "@uri" is malformed.', ['@uri' => $uri]));
throw new \InvalidArgumentException(sprintf('The URI "%s" is malformed.', $uri));
}
if (empty($uri_parts['scheme'])) {
throw new \InvalidArgumentException(SafeMarkup::format('The URI "@uri" is invalid. You must use a valid URI scheme.', ['@uri' => $uri]));
throw new \InvalidArgumentException(sprintf('The URI "%s" is invalid. You must use a valid URI scheme.', $uri));
}
$uri_parts += ['path' => ''];
// Discard empty fragment in $options for consistency with parse_url().
......@@ -362,7 +362,7 @@ public static function fromUri($uri, $options = []) {
protected static function fromEntityUri(array $uri_parts, array $options, $uri) {
list($entity_type_id, $entity_id) = explode('/', $uri_parts['path'], 2);
if ($uri_parts['scheme'] != 'entity' || $entity_id === '') {
throw new \InvalidArgumentException(SafeMarkup::format('The entity URI "@uri" is invalid. You must specify the entity id in the URL. e.g., entity:node/1 for loading the canonical path to node entity with id 1.', ['@uri' => $uri]));
throw new \InvalidArgumentException(sprintf('The entity URI "%s" is invalid. You must specify the entity id in the URL. e.g., entity:node/1 for loading the canonical path to node entity with id 1.', $uri));
}
return new static("entity.$entity_type_id.canonical", [$entity_type_id => $entity_id], $options);
......@@ -422,10 +422,14 @@ protected static function fromInternalUri(array $uri_parts, array $options) {
}
else {
if ($uri_parts['path'][0] !== '/') {
throw new \InvalidArgumentException(SafeMarkup::format('The internal path component "@path" is invalid. Its path component must have a leading slash, e.g. internal:/foo.', ['@path' => $uri_parts['path']]));
throw new \InvalidArgumentException(sprintf('The internal path component "%s" is invalid. Its path component must have a leading slash, e.g. internal:/foo.', $uri_parts['path']));
}
// Remove the leading slash.
$uri_parts['path'] = substr($uri_parts['path'], 1);
if (UrlHelper::isExternal($uri_parts['path'])) {
throw new \InvalidArgumentException(sprintf('The internal path component "%s" is external. You are not allowed to specify an external URL together with internal:/.', $uri_parts['path']));
}
}
$url = \Drupal::pathValidator()
......@@ -458,7 +462,7 @@ protected static function fromRouteUri(array $uri_parts, array $options, $uri) {
$route_parts = explode(';', $uri_parts['path'], 2);
$route_name = $route_parts[0];
if ($route_name === '') {
throw new \InvalidArgumentException(SafeMarkup::format('The route URI "@uri" is invalid. You must have a route name in the URI. e.g., route:system.admin', ['@uri' => $uri]));
throw new \InvalidArgumentException(sprintf('The route URI "%s" is invalid. You must have a route name in the URI. e.g., route:system.admin', $uri));
}
$route_parameters = [];
if (!empty($route_parts[1])) {
......
......@@ -62,6 +62,11 @@ public function testConfirmFormWithExternalDestination() {
$this->assertCancelLinkUrl(Url::fromUri('internal:/node'));
$this->drupalGet('form-test/confirm-form', array('query' => array('destination' => 'http://example.com')));
$this->assertCancelLinkUrl(Url::fromRoute('form_test.route8'));
$this->drupalGet('form-test/confirm-form', array('query' => array('destination' => '<front>')));
$this->assertCancelLinkUrl(Url::fromRoute('<front>'));
// Other invalid destinations, should fall back to the form default.
$this->drupalGet('form-test/confirm-form', array('query' => array('destination' => '/http://example.com')));
$this->assertCancelLinkUrl(Url::fromRoute('form_test.route8'));
}
/**
......
......@@ -729,20 +729,22 @@ public function testFromInvalidInternalUri($path) {
public function providerFromInvalidInternalUri() {
return [
// Normal paths without a leading slash.
['kittens'],
['kittens/bengal'],
'normal_path0' => ['kittens'],
'normal_path1' => ['kittens/bengal'],
// Path without a leading slash containing a fragment.
['kittens#feeding'],
// Path without a leading slash containing a query string.
['kittens?page=1000'],
'fragment' => ['kittens#feeding'],
// Path without a leading slash containing a query string.
'without_leading_slash_query' => ['kittens?page=1000'],
// Paths with various token formats but no leading slash.
['[duckies]'],
['%bunnies'],
['{{ puppies }}'],
'path_with_tokens0' => ['[duckies]'],
'path_with_tokens1' => ['%bunnies'],
'path_with_tokens2' => ['{{ puppies }}'],
// Disallowed characters in the authority (host name) that are valid
// elsewhere in the path.
['(:;2&+h^'],
['AKI@&hO@'],
'disallowed_hostname_chars0' => ['(:;2&+h^'],
'disallowed_hostname_chars1' => ['AKI@&hO@'],
// Leading slash with a domain.
'leading_slash_with_domain' => ['/http://example.com'],
];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment