Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.833
diff -u -p -r1.833 common.inc
--- includes/common.inc	2 Dec 2008 19:33:33 -0000	1.833
+++ includes/common.inc	3 Dec 2008 00:33:44 -0000
@@ -1120,12 +1120,11 @@ 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("/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?([A-Za-z0-9\.-]+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/\(\)]+))?$/i", $url);
   }
   else {
-    return (bool)preg_match("/^" . $allowed_characters . "+$/i", $url);
+    return (bool)preg_match("/^[\w#!:.?+=&%@!\-\/\(\)]+$/i", $url);
   }
 }
 
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	3 Dec 2008 00:33:44 -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&param=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&param=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.'));
+      }
+    }
+  }
+}
