Index: modules/profile/profile.test =================================================================== RCS file: /cvs/drupal/drupal/modules/profile/profile.test,v retrieving revision 1.9 diff -u -p -r1.9 profile.test --- modules/profile/profile.test 5 Dec 2008 12:50:28 -0000 1.9 +++ modules/profile/profile.test 6 Dec 2008 21:57:05 -0000 @@ -134,7 +134,8 @@ class ProfileTestFields extends ProfileT 'textarea' => $this->randomName(), 'list' => $this->randomName(), 'checkbox' => 1, - 'url' => 'http://www.' . $this->randomName(10). '.org', + // _ is an invalid character for domain names. + 'url' => 'http://www.' . str_replace('_', '', $this->randomName(10)). '.org', ); // For each field type, create a field, give it a value and delete the field. Index: modules/simpletest/tests/common.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v retrieving revision 1.17 diff -u -p -r1.17 common.test --- modules/simpletest/tests/common.test 26 Nov 2008 13:48:49 -0000 1.17 +++ modules/simpletest/tests/common.test 6 Dec 2008 21:57:05 -0000 @@ -521,3 +521,75 @@ class DrupalErrorHandlerUnitTest extends $this->assertText($message, t("Found '%message' in error page.", array('%message' => $message))); } } + +/** + * Test for valid_url(). + */ +class ValidUrlTestCase extends DrupalWebTestCase { + /** + * Implementation of getInfo(). + */ + function getInfo() { + return array( + 'name' => t('Valid Url'), + 'description' => t("Performs tests on Drupal's valid url function."), + 'group' => t('System') + ); + } + + function testValidUrl() { + $url_schemes = array('http', 'https', 'ftp'); + $valid_absolute_urls = array( + 'example.com', + 'www.example.com', + 'ex-ample.com', + '3xampl3.com', + 'example.com/paren(the)sis', + 'example.com/index.html#pagetop', + 'example.com:8080', + 'sudomain.example.com', + 'example.com/index.php?q=node', + 'example.com/index.php?q=node¶m=false', + 'user@www.example.com', + 'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop', + '127.0.0.1', + ); + + foreach ($url_schemes as $scheme) { + foreach ($valid_absolute_urls as $url) { + $test_url = $scheme . '://' . $url; + $valid_url = valid_url($test_url, TRUE); + $this->assertTrue($valid_url, $test_url .t(' is a valid url.')); + } + } + + $invalid_ablosule_urls = array( + '', + 'ex!ample.com', + ); + + foreach ($url_schemes as $scheme) { + foreach ($invalid_ablosule_urls as $url) { + $test_url = $scheme . '://' . $url; + $valid_url = valid_url($test_url, TRUE); + $this->assertFalse($valid_url, $test_url .t(' is NOT a valid url.')); + } + } + + $valid_relative_urls = array( + 'paren(the)sis', + 'index.html#pagetop', + 'index.php?q=node', + 'index.php?q=node¶m=false', + 'login.php?do=login&style=%23#pagetop', + ); + + foreach (array('', '/') as $front) { + foreach ($valid_relative_urls as $url) { + $test_url = $front . $url; + $valid_url = valid_url($test_url); + $this->assertTrue($valid_url, $test_url .t(' is a valid url.')); + } + } + } +} Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.834 diff -u -p -r1.834 common.inc --- includes/common.inc 3 Dec 2008 12:31:37 -0000 1.834 +++ includes/common.inc 6 Dec 2008 21:57:07 -0000 @@ -1120,12 +1120,25 @@ function valid_email_address($mail) { * TRUE if the URL is in a valid format. */ function valid_url($url, $absolute = FALSE) { - $allowed_characters = '[a-z0-9\/:_\-_\.\?\$,;~=#&%\+]'; if ($absolute) { - return (bool)preg_match("/^(http|https|ftp):\/\/" . $allowed_characters . "+$/i", $url); + return (bool)preg_match(' + /^ # Start at the beginning of the text + (?:ftp|http|https):\/\/ # Look for ftp, http, or https + (?: # Username:password combinations (optional) + [\w\.\-\+]+ # A username + :{0,1} # an optional colon to separate the username and password + [\w\.\-\+]*@ # An optional password + )? + (?:[a-z0-9\-\.]+) # The domain + (?::[0-9]+)? # Server port number (optional) + (?: # The path (optional) + \/| # a forward slash + (?:\/|\?)(?:[\w#!:\.\?\+=&%@!\-\/\(\)]+) # or a forward slash or question mark followed by a full path + )?$ + /xi', $url); } else { - return (bool)preg_match("/^" . $allowed_characters . "+$/i", $url); + return (bool)preg_match("/^[\w#!:.?+=&%@!\-\/\(\)]+$/i", $url); } }