Commit 18fc3396 authored by lucashedding's avatar lucashedding Committed by sumitmadan
Browse files

Issue #2247261 by heddn, sumitmadan: URLs are not validated

parent b93d7e8f
......@@ -291,7 +291,7 @@ function link_field_validate($entity_type, $entity, $field, $instance, $langcode
*/
function link_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
foreach ($items as $delta => $value) {
_link_process($items[$delta], $delta, $field, $entity);
_link_process($items[$delta], $delta, $field, $entity, $instance);
}
}
......@@ -300,7 +300,7 @@ function link_field_insert($entity_type, $entity, $field, $instance, $langcode,
*/
function link_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
foreach ($items as $delta => $value) {
_link_process($items[$delta], $delta, $field, $entity);
_link_process($items[$delta], $delta, $field, $entity, $instance);
}
}
......@@ -371,8 +371,24 @@ function _link_load($field, $item, $instance) {
/**
* Prepares the item attributes and url for storage.
*
* @param $item
* Link field values.
*
* @param $delta
* The sequence number for current values.
*
* @param $field
* The field structure array.
*
* @param $entity
* Entity object.
*
* @param $instance
* The instance structure for $field on $entity's bundle.
*
*/
function _link_process(&$item, $delta, $field, $entity) {
function _link_process(&$item, $delta, $field, $entity, $instance) {
// Trim whitespace from URL.
if (!empty($item['url'])) {
$item['url'] = trim($item['url']);
......@@ -391,7 +407,8 @@ function _link_process(&$item, $delta, $field, $entity) {
// Don't save an invalid default value (e.g. 'http://').
if ((isset($field['widget']['default_value'][$delta]['url']) && $item['url'] == $field['widget']['default_value'][$delta]['url']) && is_object($entity)) {
if (!link_validate_url($item['url'])) {
$langcode = !empty($entity) ? field_language($instance['entity_type'], $entity, $instance['field_name']) : LANGUAGE_NONE;
if (!link_validate_url($item['url'], $langcode)) {
unset($item['url']);
}
}
......@@ -403,7 +420,8 @@ function _link_process(&$item, $delta, $field, $entity) {
function _link_validate(&$item, $delta, $field, $entity, $instance, $langcode, &$optional_field_found, &$errors) {
if ($item['url'] && !(isset($instance['default_value'][$delta]['url']) && $item['url'] === $instance['default_value'][$delta]['url'] && !$instance['required'])) {
// Validate the link.
if (link_validate_url(trim($item['url'])) == FALSE) {
$langcode = !empty($entity) ? field_language($instance['entity_type'], $entity, $instance['field_name']) : LANGUAGE_NONE;
if (!link_validate_url(trim($item['url']), $langcode)) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'link_required',
'message' => t('The value %value provided for %field is not a valid URL.', array(
......@@ -488,7 +506,7 @@ function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {
}
}
$type = link_validate_url($item['url']);
$type = link_url_type($item['url']);
// If the type of the URL cannot be determined and URL validation is disabled,
// then assume LINK_EXTERNAL for later processing.
if ($type == FALSE && $instance['settings']['validate_url'] === 0) {
......@@ -1161,7 +1179,7 @@ function link_views_api() {
*/
function link_cleanup_url($url, $protocol = 'http') {
$url = trim($url);
$type = link_validate_url($url);
$type = link_url_type($url);
if ($type === LINK_EXTERNAL) {
// Check if there is no protocol specified.
......@@ -1182,17 +1200,58 @@ function link_cleanup_url($url, $protocol = 'http') {
/**
* Validates a URL.
*
* @param $text
* Url to be validated.
*
* @param $langcode
* An optional language code to look up the path in.
*
* @return boolean
* True if a valid link, FALSE otherwise.
*/
function link_validate_url($text, $langcode = NULL) {
$text = link_cleanup_url($text);
$type = link_url_type($text);
if ($type && ($type == LINK_INTERNAL || $type == LINK_EXTERNAL)) {
$flag = valid_url($text, TRUE);
if (!$flag) {
$normal_path = drupal_get_normal_path($text, $langcode);
$parsed_link = parse_url($normal_path, PHP_URL_PATH);
if ($normal_path != $parsed_link) {
$normal_path = $parsed_link;
}
$flag = drupal_valid_path($normal_path);
}
if (!$flag) {
$flag = file_exists($normal_path);
}
if (!$flag) {
$uri = file_build_uri($normal_path);
$flag = file_exists($uri);
}
}
else {
$flag = (bool) $type;
}
return $flag;
}
/**
* Type check a URL.
*
* Accepts all URLs following RFC 1738 standard for URL formation and all e-mail
* addresses following the RFC 2368 standard for mailto address formation.
*
* @param string $text
* Url to be validated.
* Url to be checked.
*
* @return mixed
* Returns boolean FALSE if the URL is not valid. On success, returns one of
* the LINK_(linktype) constants.
*/
function link_validate_url($text) {
function link_url_type($text) {
// @TODO Complete letters.
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array(
"æ", // æ
......
......@@ -22,25 +22,24 @@ class LinkValidateTestCase extends LinkBaseTestClass {
$field_name = $this->createLinkField();
$permission = 'create page content';
$this->checkPermissions(array($permission), TRUE);
$this->drupalGet('node/add/page');
$label = $this->randomName();
$edit = array(
$settings = array(
'title' => $label,
$field_name . '[und][0][title]' => $label,
$field_name . '[und][0][url]' => $url,
$field_name => array(
LANGUAGE_NONE=> array(
array(
'title' => $label,
'url' => $url,
)
),
),
);
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertRaw(' has been created.', 'Node created');
$nid = 1; //$matches[1];
$node = $this->drupalCreateNode($settings);
$node = node_load($nid);
$this->assertNotNull($node, ' has been created.', 'Node created');
$this->assertEqual($url, $node->{$field_name}['und'][0]['url']);
$this->assertEqual($url, $node->{$field_name}[LANGUAGE_NONE][0]['url']);
}
}
......@@ -269,7 +268,13 @@ class LinkValidateTest extends LinkValidateTestCase {
// Validate that an internal url would be accepted.
function test_link_internal_url() {
$this->link_test_validate_url('node/32');
// Create the content first.
$node = $this->drupalCreateNode();
$link = 'node/' . $node->nid;
$this->link_test_validate_url($link);
$type = link_url_type($link);
$this->assertEqual(LINK_INTERNAL, $type, 'Test ' . $link . ' is an internal link.');
}
// Validate a simple mailto.
......@@ -390,10 +395,10 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
}
}
// Make sure that a link labelled <front> works.
// Make sure that a link labeled <front> works.
function testValidateFrontLink() {
$valid = link_validate_url('<front>');
$this->assertEqual(LINK_FRONT, $valid, 'Make sure that front link is verfied and identified');
$this->assertEqual(LINK_FRONT, $valid, 'Make sure that front link is verified and identified');
}
function testValidateEmailLink() {
......@@ -413,7 +418,7 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
function testValidateNewsArticleLink() {
$valid = link_validate_url('news:hj0db8$vrm$1@news.eternal-september.org');
$this->assertEqual(LINK_NEWS, $valid, 'Make sure link to specific article valiates as news.');
$this->assertEqual(LINK_NEWS, $valid, 'Make sure link to specific article validates as news.');
}
function testValidateBadNewsgroupLink() {
......@@ -422,16 +427,18 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
}
function testValidateInternalLinks() {
$tempfile = drupal_tempnam('public://files', 'test');
$links = array(
'node/5',
'rss.xml',
'files/test.jpg',
'/var/www/test',
file_uri_target($tempfile),
drupal_realpath($tempfile),
);
foreach ($links as $link) {
$type = link_url_type($link);
$this->assertEqual(LINK_INTERNAL, $type, 'Test ' . $link . ' is an internal link.');
$valid = link_validate_url($link);
$this->assertEqual(LINK_INTERNAL, $valid, 'Test ' . $link . ' internal link.');
$this->assertTrue($valid, 'Test ' . $link . ' is valid internal link.');
}
}
......@@ -450,7 +457,6 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
'http://255.255.255.255:4823/',
'www.test-site.com',
'http://example.com/index.php?q=node/123',
'http://example.com/index.php?page=this\that',
'http://example.com/?first_name=Joe Bob&last_name=Smith',
// Anchors
'http://www.example.com/index.php#test',
......@@ -468,8 +474,10 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
}
}
foreach ($links as $link) {
$type = link_url_type($link);
$this->assertEqual(LINK_EXTERNAL, $type, 'Testing that ' . $link . ' is an external link.');
$valid = link_validate_url($link);
$this->assertEqual(LINK_EXTERNAL, $valid, 'Testing that ' . $link . ' is a valid external link.');
$this->assertTrue($valid, 'Test ' . $link . ' is valid external link.');
// The following two lines are commented out and only used for comparisons.
//$valid2 = valid_url($link, TRUE);
//$this->assertEqual(TRUE, $valid2, "Using valid_url() on $link.");
......@@ -489,6 +497,8 @@ class LinkValidateUrlLight extends DrupalWebTestCase {
'http://www.testß.com/', // ß not allowed in domain names!
'http://www.example.frog/', // Bad TLD
//'http://www.-fudge.com/', // domains can't have sections starting with a dash.
'http://example.com/index.php?page=this\that',
'example@example.com',
);
foreach ($links as $link) {
$valid = link_validate_url($link);
......
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