Bläddra i källkod

[ZF-10267] Zend_Validate_Hostname:

- added regname support (RFC3986)

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@22830 44c647ce-9c0f-0410-b52a-842ac1e357ba
thomas 15 år sedan
förälder
incheckning
623719ea9a

+ 16 - 4
documentation/manual/en/module_specs/Zend_Validate-Hostname.xml

@@ -95,8 +95,20 @@ if ($validator->isValid($hostname)) {
             <constant>ALLOW_DNS</constant> to allow only
             <acronym>DNS</acronym> hostnames, <constant>ALLOW_IP</constant> to allow IP addresses,
             <constant>ALLOW_LOCAL</constant> to allow local network names, and
-            <constant>ALLOW_ALL</constant> to allow all three types. To just check for IP addresses
-            you can use the example below:
+            <constant>ALLOW_ALL</constant> to allow all three above types.
+        </para>
+
+        <para>
+            Additionally there is <constant>ALLOW_URI</constant> which allows to check hostnames
+            according to <link linkend="http://tools.ietf.org/html/rfc3986">RFC3986</link>. These
+            are registered names which are used by <acronym>WINS</acronym>, NetInfo and also local
+            hostnames like those defined within your <filename>.hosts</filename> file. For security
+            reasons <constant>ALLOW_URI</constant> is not contained within
+            <constant>ALLOW_ALL</constant>.
+        </para>
+
+        <para>
+            To just check for IP addresses you can use the example below:
         </para>
 
         <programlisting language="php"><![CDATA[
@@ -112,8 +124,8 @@ if ($validator->isValid($hostname)) {
 ]]></programlisting>
 
         <para>
-            As well as using <constant>ALLOW_ALL</constant> to accept all hostnames types you can
-            combine these types to allow for combinations. For example, to accept
+            As well as using <constant>ALLOW_ALL</constant> to accept all common hostnames types
+            you can combine these types to allow for combinations. For example, to accept
             <acronym>DNS</acronym> and Local hostnames instantiate your
             <classname>Zend_Validate_Hostname</classname> object as so:
         </para>

+ 26 - 10
library/Zend/Validate/Hostname.php

@@ -46,31 +46,33 @@ require_once 'Zend/Validate/Ip.php';
  */
 class Zend_Validate_Hostname extends Zend_Validate_Abstract
 {
+    const CANNOT_DECODE_PUNYCODE  = 'hostnameCannotDecodePunycode';
     const INVALID                 = 'hostnameInvalid';
-    const IP_ADDRESS_NOT_ALLOWED  = 'hostnameIpAddressNotAllowed';
-    const UNKNOWN_TLD             = 'hostnameUnknownTld';
     const INVALID_DASH            = 'hostnameDashCharacter';
-    const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema';
-    const UNDECIPHERABLE_TLD      = 'hostnameUndecipherableTld';
     const INVALID_HOSTNAME        = 'hostnameInvalidHostname';
+    const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema';
     const INVALID_LOCAL_NAME      = 'hostnameInvalidLocalName';
+    const INVALID_URI             = 'hostnameInvalidUri';
+    const IP_ADDRESS_NOT_ALLOWED  = 'hostnameIpAddressNotAllowed';
     const LOCAL_NAME_NOT_ALLOWED  = 'hostnameLocalNameNotAllowed';
-    const CANNOT_DECODE_PUNYCODE  = 'hostnameCannotDecodePunycode';
+    const UNDECIPHERABLE_TLD      = 'hostnameUndecipherableTld';
+    const UNKNOWN_TLD             = 'hostnameUnknownTld';
 
     /**
      * @var array
      */
     protected $_messageTemplates = array(
+        self::CANNOT_DECODE_PUNYCODE  => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded",
         self::INVALID                 => "Invalid type given. String expected",
-        self::IP_ADDRESS_NOT_ALLOWED  => "'%value%' appears to be an IP address, but IP addresses are not allowed",
-        self::UNKNOWN_TLD             => "'%value%' appears to be a DNS hostname but cannot match TLD against known list",
         self::INVALID_DASH            => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position",
-        self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
-        self::UNDECIPHERABLE_TLD      => "'%value%' appears to be a DNS hostname but cannot extract TLD part",
         self::INVALID_HOSTNAME        => "'%value%' does not match the expected structure for a DNS hostname",
+        self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
         self::INVALID_LOCAL_NAME      => "'%value%' does not appear to be a valid local network name",
+        self::INVALID_URI             => "'%value%' does not appear to be a valid URI hostname",
+        self::IP_ADDRESS_NOT_ALLOWED  => "'%value%' appears to be an IP address, but IP addresses are not allowed",
         self::LOCAL_NAME_NOT_ALLOWED  => "'%value%' appears to be a local network name but local network names are not allowed",
-        self::CANNOT_DECODE_PUNYCODE  => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded",
+        self::UNDECIPHERABLE_TLD      => "'%value%' appears to be a DNS hostname but cannot extract TLD part",
+        self::UNKNOWN_TLD             => "'%value%' appears to be a DNS hostname but cannot match TLD against known list",
     );
 
     /**
@@ -101,6 +103,11 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
     const ALLOW_ALL   = 7;
 
     /**
+     * Allows all types of hostnames
+     */
+    const ALLOW_URI = 8;
+
+    /**
      * Array of valid top-level-domains
      *
      * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt  List of all TLDs by domain
@@ -617,6 +624,15 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
             $this->_error(self::INVALID_HOSTNAME);
         }
 
+        // Check for URI Syntax (RFC3986)
+        if ($this->_options['allow'] & self::ALLOW_URI) {
+            if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) {
+                return true;
+            } else {
+                $this->_error(self::INVALID_URI);
+            }
+        }
+
         // Check input against local network name schema; last chance to pass validation
         $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/';
         $status = @preg_match($regexLocal, $value);

+ 17 - 0
tests/Zend/Validate/HostnameTest.php

@@ -389,4 +389,21 @@ class Zend_Validate_HostnameTest extends PHPUnit_Framework_TestCase
     {
         $this->assertFalse($this->_validator->isValid('test.com / http://www.test.com'));
     }
+
+    /**
+     * @group ZF-10267
+     */
+    public function testURI()
+    {
+        $valuesExpected = array(
+            array(Zend_Validate_Hostname::ALLOW_URI, true, array('localhost', 'example.com', '~ex%20ample')),
+            array(Zend_Validate_Hostname::ALLOW_URI, false, array('§bad', 'don?t.know', 'thisisaverylonghostnamewhichextendstwohundredfiftysixcharactersandthereforshouldnotbeallowedbythisvalidatorbecauserfc3986limitstheallowedcharacterstoalimitoftwohunderedfiftysixcharactersinsumbutifthistestwouldfailthenitshouldreturntruewhichthrowsanexceptionbytheunittest')),
+        );
+        foreach ($valuesExpected as $element) {
+            $validator = new Zend_Validate_Hostname($element[0]);
+            foreach ($element[2] as $input) {
+                $this->assertEquals($element[1], $validator->isValid($input), implode("\n", $validator->getMessages()) . $input);
+            }
+        }
+    }
 }