/** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { // Validate video URL. if (!UrlHelper::isValid($form_state->getValue('video'), TRUE)) { $form_state->setErrorByName('video', $this->t("The video url '%url' is invalid.", array('%url' => $form_state->getValue('video')))); } }
/** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (isset($value)) { $url_is_valid = TRUE; /** @var $link_item \Drupal\link\LinkItemInterface */ $link_item = $value; $link_type = $link_item->getFieldDefinition()->getSetting('link_type'); $url_string = $link_item->url; // Validate the url property. if ($url_string !== '') { try { // @todo This shouldn't be needed, but massageFormValues() may not // run. $parsed_url = UrlHelper::parse($url_string); $url = Url::createFromPath($parsed_url['path']); if ($url->isExternal() && !UrlHelper::isValid($url_string, TRUE)) { $url_is_valid = FALSE; } elseif ($url->isExternal() && !($link_type & LinkItemInterface::LINK_EXTERNAL)) { $url_is_valid = FALSE; } } catch (NotFoundHttpException $e) { $url_is_valid = FALSE; } catch (MatchingRouteNotFoundException $e) { $url_is_valid = FALSE; } catch (ParamNotConvertedException $e) { $url_is_valid = FALSE; } } if (!$url_is_valid) { $this->context->addViolation($this->message, array('%url' => $url_string)); } } }
/** * {@inheritdoc} */ public function blockValidate($form, FormStateInterface $form_state) { // Instantiate UrlHelper object to validate the URL's. $url_helper = new UrlHelper(); // Build an array of the links that need validating. If more fields are // added later, add another entry to the links array. $links = []; $links['pantheon_url'] = $form_state->getValue('pantheon_url'); // Create an error variable to prevent setting the error message repeatedly. $error_set = FALSE; // Validate and set errors where appropriate. foreach ($links as $key => $link) { if ($link == '') { break; } $validity = $url_helper->isValid($link, TRUE); if ($validity != TRUE) { $form_state->setErrorByName($key, "The value must be a full URL similar to http://www.example.com."); // Using drupal_set_message because of a bug with setError that is // causing the form to not submit correctly, but isn't displaying // messages. if ($error_set == FALSE) { drupal_set_message('All values must be full URLs of format: http://www.example.com.', 'error'); // Prevent the error from outputting multiple times. $error_set = TRUE; } } } }
/** * {@inheritdoc} */ public function execute($object = NULL) { $url = $this->configuration['url']; // Leave external URLs unchanged, and assemble others as absolute URLs // relative to the site's base URL. if (!UrlHelper::isExternal($url)) { $parts = UrlHelper::parse($url); // @todo '<front>' is valid input for BC reasons, may be removed by // https://www.drupal.org/node/2421941 if ($parts['path'] === '<front>') { $parts['path'] = ''; } $uri = 'base:' . $parts['path']; $options = ['query' => $parts['query'], 'fragment' => $parts['fragment'], 'absolute' => TRUE]; // Treat this as if it's user input of a path relative to the site's // base URL. $url = $this->unroutedUrlAssembler->assemble($uri, $options); } $response = new RedirectResponse($url); $listener = function ($event) use($response) { $event->setResponse($response); }; // Add the listener to the event dispatcher. $this->dispatcher->addListener(KernelEvents::RESPONSE, $listener); }
/** * {@inheritdoc} */ protected function prepareValue($delta, array &$values) { $values['uri'] = trim($values['uri']); if (!UrlHelper::isValid($values['uri'], TRUE)) { $values['uri'] = ''; } }
/** * {@inheritdoc} */ public function isValid($path) { // External URLs and the front page are always valid. if ($path == '<front>' || UrlHelper::isExternal($path)) { return TRUE; } // Check the routing system. $collection = $this->routeProvider->getRoutesByPattern('/' . $path); if ($collection->count() == 0) { return FALSE; } $request = RequestHelper::duplicate($this->requestStack->getCurrentRequest(), '/' . $path); $request->attributes->set('_system_path', $path); // We indicate that a menu administrator is running the menu access check. $request->attributes->set('_menu_admin', TRUE); // Attempt to match this path to provide a fully built request to the // access checker. try { $request->attributes->add($this->requestMatcher->matchRequest($request)); } catch (ParamNotConvertedException $e) { return FALSE; } // Consult the access manager. $routes = $collection->all(); $route = reset($routes); return $this->accessManager->check($route, $request, $this->account); }
/** * {@inheritdoc} */ public static function validateValue(array &$element, FormStateInterface $form_state, array $form) { if (!empty($element['#value'])) { if (!UrlHelper::isValid($element['#value'], TRUE)) { $form_state->setError($element, t('The entered Tumblr URI is not valid.')); } } }
/** * @param $url * * @see FillPdfLinkManipulatorInterface::parseUrlString() * * @return \Drupal\Core\Url */ protected function createUrlFromString($url) { $url_parts = UrlHelper::parse($url); $path = $url_parts['path']; $query = $url_parts['query']; $link = Url::fromUri($path, ['query' => $query]); return $link; }
/** * Form element validation handler for #type 'url'. * * Note that #maxlength and #required is validated by _form_validate() already. */ public static function validateUrl(&$element, FormStateInterface $form_state, &$complete_form) { $value = trim($element['#value']); $form_state->setValueForElement($element, $value); if ($value !== '' && !UrlHelper::isValid($value, TRUE)) { $form_state->setError($element, t('The URL %url is not valid.', array('%url' => $value))); } }
public function validateForm(array &$form, FormStateInterface $form_state) { if (strlen($form_state->getValue('title')) < 3) { $form_state->setErrorByName('title', $this->t('Your name is too short.')); } if (!UrlHelper::isValid($form_state->getValue('video'), TRUE)) { $form_state->setErrorByName('video', $this->t("The video url '%url' is invalid.", array('%url' => $form_state->getValue('video')))); } }
/** * Constructs a new generator object. * * @param \Drupal\Core\Routing\RouteProviderInterface $provider * The route provider to be searched for routes. * @param \Drupal\Core\PathProcessor\OutboundPathProcessorInterface $path_processor * The path processor to convert the system path to one suitable for urls. * @param \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface $route_processor * The route processor. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * A request stack object. * @param string[] $filter_protocols * (optional) An array of protocols allowed for URL generation. */ public function __construct(RouteProviderInterface $provider, OutboundPathProcessorInterface $path_processor, OutboundRouteProcessorInterface $route_processor, RequestStack $request_stack, array $filter_protocols = ['http', 'https']) { $this->provider = $provider; $this->context = new RequestContext(); $this->pathProcessor = $path_processor; $this->routeProcessor = $route_processor; UrlHelper::setAllowedProtocols($filter_protocols); $this->requestStack = $request_stack; }
/** * {@inheritdoc} */ public function setEmbedProvider($provider) { $provider_parsed = UrlHelper::parse($provider); $provider_parsed['query'] = array_filter($provider_parsed['query'], function ($value) { return $value !== '{callback}'; }); $provider_parsed['absolute'] = TRUE; $this->embed_provider = $this->urlAssembler->assemble($provider_parsed['path'], $provider_parsed); }
/** * Tests onHandleException with a GET request. */ public function testHandleWithGetRequest() { $request = Request::create('/test', 'GET', array('name' => 'druplicon', 'pass' => '12345')); $this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { return new Response($request->getMethod() . ' ' . UrlHelper::buildQuery($request->query->all())); })); $event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new \Exception('foo')); $this->exceptionListener->onKernelException($event); $response = $event->getResponse(); $this->assertEquals('GET name=druplicon&pass=12345 ', $response->getContent() . " " . UrlHelper::buildQuery($request->request->all())); }
/** * Checks that harmful protocols are stripped. */ function testBadProtocolStripping() { // Ensure that check_url() strips out harmful protocols, and encodes for // HTML. // Ensure \Drupal\Component\Utility\UrlHelper::stripDangerousProtocols() can // be used to return a plain-text string stripped of harmful protocols. $url = 'javascript:http://www.example.com/?x=1&y=2'; $expected_plain = 'http://www.example.com/?x=1&y=2'; $expected_html = 'http://www.example.com/?x=1&y=2'; $this->assertIdentical(check_url($url), $expected_html, 'check_url() filters a URL and encodes it for HTML.'); $this->assertIdentical(UrlHelper::stripDangerousProtocols($url), $expected_plain, '\\Drupal\\Component\\Utility\\Url::stripDangerousProtocols() filters a URL and returns plain text.'); }
/** * Response for the xmlsitemap_engines_test.ping route. * * @throws NotFoundHttpException * Throw a NotFoundHttpException if query url is not valid. * * @return \Symfony\Component\HttpFoundation\Response * A response with 200 code if the url query is valid. */ public function render() { $query = \Drupal::request()->query->get('sitemap'); if (empty($query) || !UrlHelper::isValid($query)) { watchdog('xmlsitemap', 'No valid sitemap parameter provided.', array(), WATCHDOG_WARNING); // @todo Remove this? Causes an extra watchdog error to be handled. throw new NotFoundHttpException(); } else { watchdog('xmlsitemap', 'Recieved ping for @sitemap.', array('@sitemap' => $query)); } return new Response('', 200); }
/** * Builds the cancel link for a confirmation form. * * @param \Drupal\Core\Form\ConfirmFormInterface $form * The confirmation form. * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * * @return array * The link render array for the cancel form. */ public static function buildCancelLink(ConfirmFormInterface $form, Request $request) { // Prepare cancel link. $query = $request->query; // 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('/' . $options['path'], $options); } else { $url = $form->getCancelUrl(); } return ['#type' => 'link', '#title' => $form->getCancelText(), '#attributes' => ['class' => ['button']], '#url' => $url]; }
/** * Returns the next redirect path in a multipage sequence. * * @param array $destinations * An array of destinations to redirect to. * * @return array * The next destination to redirect to. */ public static function getNextDestination(array $destinations) { $next_destination = array_shift($destinations); if (is_array($next_destination)) { $next_destination['options']['query']['destinations'] = $destinations; } else { $options = UrlHelper::parse($next_destination); if ($destinations) { $options['query']['destinations'] = $destinations; } $next_destination = array($options['path'], $options); } return $next_destination; }
/** * {@inheritdoc} */ public function get() { if (!isset($this->destination)) { $query = $this->requestStack->getCurrentRequest()->query; if (UrlHelper::isExternal($query->get('destination'))) { $this->destination = '/'; } elseif ($query->has('destination')) { $this->destination = $query->get('destination'); } else { $this->destination = $this->urlGenerator->generateFromRoute('<current>', [], ['query' => UrlHelper::buildQuery(UrlHelper::filterQueryParameters($query->all()))]); } } return $this->destination; }
/** * Builds the cancel link for a confirmation form. * * @param \Drupal\Core\Form\ConfirmFormInterface $form * The confirmation form. * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * * @return array * The link render array for the cancel form. */ public static function buildCancelLink(ConfirmFormInterface $form, Request $request) { // Prepare cancel link. $query = $request->query; // If a destination is specified, that serves as the cancel link. if ($query->has('destination')) { $options = UrlHelper::parse($query->get('destination')); $link = array('#href' => $options['path'], '#options' => $options); } elseif ($route = $form->getCancelRoute()) { $link = $route->toRenderArray(); } $link['#type'] = 'link'; $link['#title'] = $form->getCancelText(); return $link; }
/** * Builds the cancel link for a confirmation form. * * @param \Drupal\Core\Form\ConfirmFormInterface $form * The confirmation form. * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * * @return array * The link render array for the cancel form. */ public static function buildCancelLink(ConfirmFormInterface $form, Request $request) { // Prepare cancel link. $query = $request->query; // If a destination is specified, that serves as the cancel link. if ($query->has('destination')) { $options = UrlHelper::parse($query->get('destination')); // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is // resolved. $url = Url::fromUri('base://' . $options['path'], $options); } else { $url = $form->getCancelUrl(); } return ['#type' => 'link', '#title' => $form->getCancelText(), '#url' => $url]; }
/** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (isset($value)) { try { /** @var \Drupal\Core\Url $url */ $url = $value->getUrl(); } catch (\InvalidArgumentException $e) { return; } // Disallow external URLs using untrusted protocols. if ($url->isExternal() && !in_array(parse_url($url->getUri(), PHP_URL_SCHEME), UrlHelper::getAllowedProtocols())) { $this->context->addViolation($constraint->message, array('@uri' => $value->uri)); } } }
/** * Implements \Drupal\Core\Form\FormInterface::validateForm(). */ public function validateForm(array &$form, FormStateInterface $form_state) { $routing_path = $form_state->getValue('routing_path'); if ($routing_path) { $form_state->setValueForElement($form['routing']['routing_path'], $routing_path); } else { $form_state->setValueForElement($form['routing']['routing_path'], '/headless'); } if ($routing_path[0] == '/') { $form_state->setErrorByName('routing_path', $this->t("The path '%path' cannot start with a slash.", array('%path' => $routing_path))); } if (!UrlHelper::isValid($routing_path)) { $form_state->setErrorByName('routing_path', $this->t("The path '%path' is invalid or you do not have access to it.", array('%path' => $routing_path))); } }
/** * @covers ::validate * @dataProvider providerValidate */ public function testValidate($value, $valid) { $context = $this->getMock('Symfony\\Component\\Validator\\ExecutionContextInterface'); if ($valid) { $context->expects($this->never())->method('addViolation'); } else { $context->expects($this->once())->method('addViolation'); } // Setup some more allowed protocols. UrlHelper::setAllowedProtocols(['http', 'https', 'magnet']); $constraint = new LinkExternalProtocolsConstraint(); $validator = new LinkExternalProtocolsConstraintValidator(); $validator->initialize($context); $validator->validate($value, $constraint); }
/** * {@inheritdoc} */ public function createPlaceholder(array $element) { $placeholder_render_array = array_intersect_key($element, ['#lazy_builder' => TRUE, '#cache' => TRUE]); // Generate placeholder markup. Note that the only requirement is that this // is unique markup that isn't easily guessable. The #lazy_builder callback // and its arguments are put in the placeholder markup solely to simplify<<< // debugging. $callback = $placeholder_render_array['#lazy_builder'][0]; $arguments = UrlHelper::buildQuery($placeholder_render_array['#lazy_builder'][1]); $token = hash('crc32b', serialize($placeholder_render_array)); $placeholder_markup = '<drupal-render-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-render-placeholder>'; // Build the placeholder element to return. $placeholder_element = []; $placeholder_element['#markup'] = Markup::create($placeholder_markup); $placeholder_element['#attached']['placeholders'][$placeholder_markup] = $placeholder_render_array; return $placeholder_element; }
/** * Returns the next redirect path in a multipage sequence. * * @param array $destinations * An array of destinations to redirect to. * * @return \Drupal\Core\Url * The next destination to redirect to. */ public static function getNextDestination(array $destinations) { $next_destination = array_shift($destinations); if (is_array($next_destination)) { $next_destination['options']['query']['destinations'] = $destinations; $next_destination += array('route_parameters' => array()); $next_destination = Url::fromRoute($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); } else { $options = UrlHelper::parse($next_destination); if ($destinations) { $options['query']['destinations'] = $destinations; } // Redirect to any given path within the same domain. // @todo Revisit this in https://www.drupal.org/node/2418219. $next_destination = Url::fromUserInput('/' . $options['path']); } return $next_destination; }
/** * Returns the next redirect path in a multipage sequence. * * @param array $destinations * An array of destinations to redirect to. * * @return \Drupal\Core\Url * The next destination to redirect to. */ public static function getNextDestination(array $destinations) { $next_destination = array_shift($destinations); if (is_array($next_destination)) { $next_destination['options']['query']['destinations'] = $destinations; $next_destination += array('route_parameters' => array()); $next_destination = Url::fromRoute($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); } else { $options = UrlHelper::parse($next_destination); if ($destinations) { $options['query']['destinations'] = $destinations; } // Redirect to any given path within the same domain. // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is // resolved. $next_destination = Url::fromUri('base://' . $options['path']); } return $next_destination; }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { // Define element array. $element = []; foreach ($items as $delta => $item) { // Convert the link-field item to a \Drupal\Core\Url object. $url = $this->buildUrl($item); // Parse the URL so we can check if the path contains a Github Gist. We do // this to check if we should actually render the element or provide a // notice in the log. $url = UrlHelper::parse($url->getUri()); if (FALSE !== Unicode::strpos($url['path'], 'gist.github.com')) { $element[$delta] = ['#theme' => 'gist_embed', '#url' => $url]; } else { $entity = $items->getEntity(); $message = $this->t('The entity type: "@type" with the ID: "@id" is trying to use a link that isn\'t a Github Gist link for the Gist Embed Formatter.', array('@type' => ucfirst($entity->getEntityType()->id()), '@id' => $entity->id())); \Drupal::logger('gist_embed')->notice($message); } } return $element; }
/** * Builds the cancel link for a confirmation form. * * @param \Drupal\Core\Form\ConfirmFormInterface $form * The confirmation form. * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * * @return array * The link render array for the cancel form. */ 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. 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. if (!$url) { $url = $form->getCancelUrl(); } return ['#type' => 'link', '#title' => $form->getCancelText(), '#attributes' => ['class' => ['button']], '#url' => $url]; }
/** * Allows manipulation of the response object when performing a redirect. * * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event * The Event to process. */ public function checkRedirectUrl(FilterResponseEvent $event) { $response = $event->getResponse(); if ($response instanceof RedirectResponse) { $options = array(); $destination = $event->getRequest()->query->get('destination'); // A destination from \Drupal::request()->query always overrides the // current RedirectResponse. We do not allow absolute URLs to be passed // via \Drupal::request()->query, as this can be an attack vector, with // the following exception: // - Absolute URLs that point to this site (i.e. same base URL and // base path) are allowed. if ($destination && (!UrlHelper::isExternal($destination) || UrlHelper::externalIsLocal($destination, $GLOBALS['base_url']))) { $destination = UrlHelper::parse($destination); $path = $destination['path']; $options['query'] = $destination['query']; $options['fragment'] = $destination['fragment']; // The 'Location' HTTP header must always be absolute. $options['absolute'] = TRUE; $response->setTargetUrl($this->urlGenerator->generateFromPath($path, $options)); } } }
/** * Tests using entity fields of the link field type. */ public function testLinkItem() { // Create entity. $entity = entity_create('entity_test'); $url = 'http://www.drupal.org?test_param=test_value'; $parsed_url = UrlHelper::parse($url); $title = $this->randomMachineName(); $class = $this->randomMachineName(); $entity->field_test->uri = $parsed_url['path']; $entity->field_test->title = $title; $entity->field_test->first()->get('options')->set('query', $parsed_url['query']); $entity->field_test->first()->get('options')->set('attributes', array('class' => $class)); $entity->name->value = $this->randomMachineName(); $entity->save(); // Verify that the field value is changed. $id = $entity->id(); $entity = entity_load('entity_test', $id); $this->assertTrue($entity->field_test instanceof FieldItemListInterface, 'Field implements interface.'); $this->assertTrue($entity->field_test[0] instanceof FieldItemInterface, 'Field item implements interface.'); $this->assertEqual($entity->field_test->uri, $parsed_url['path']); $this->assertEqual($entity->field_test[0]->uri, $parsed_url['path']); $this->assertEqual($entity->field_test->title, $title); $this->assertEqual($entity->field_test[0]->title, $title); $this->assertEqual($entity->field_test->options['attributes']['class'], $class); $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']); // Update only the entity name property to check if the link field data will // remain intact. $entity->name->value = $this->randomMachineName(); $entity->save(); $id = $entity->id(); $entity = entity_load('entity_test', $id); $this->assertEqual($entity->field_test->uri, $parsed_url['path']); $this->assertEqual($entity->field_test->options['attributes']['class'], $class); $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']); // Verify changing the field value. $new_url = 'http://drupal.org'; $new_title = $this->randomMachineName(); $new_class = $this->randomMachineName(); $entity->field_test->uri = $new_url; $entity->field_test->title = $new_title; $entity->field_test->first()->get('options')->set('query', NULL); $entity->field_test->first()->get('options')->set('attributes', array('class' => $new_class)); $this->assertEqual($entity->field_test->uri, $new_url); $this->assertEqual($entity->field_test->title, $new_title); $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class); $this->assertNull($entity->field_test->options['query']); // Read changed entity and assert changed values. $entity->save(); $entity = entity_load('entity_test', $id); $this->assertEqual($entity->field_test->uri, $new_url); $this->assertEqual($entity->field_test->title, $new_title); $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class); // Test the generateSampleValue() method. $entity = entity_create('entity_test'); $entity->field_test->generateSampleItems(); $this->entityValidateAndSave($entity); }