Ver Fonte

ZF-6363
Zend_Validate
Allow hostnames with ending '.'
Backported fix from ZF2 pull request #229


git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@24306 44c647ce-9c0f-0410-b52a-842ac1e357ba

adamlundrigan há 14 anos atrás
pai
commit
3b9f23fc0d
2 ficheiros alterados com 38 adições e 16 exclusões
  1. 23 12
      library/Zend/Validate/Hostname.php
  2. 15 4
      tests/Zend/Validate/HostnameTest.php

+ 23 - 12
library/Zend/Validate/Hostname.php

@@ -100,12 +100,12 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
     /**
      * Allows all types of hostnames
      */
-    const ALLOW_ALL   = 7;
+    const ALLOW_URI = 8;
 
     /**
      * Allows all types of hostnames
      */
-    const ALLOW_URI = 8;
+    const ALLOW_ALL = 15;
 
     /**
      * Array of valid top-level-domains
@@ -495,7 +495,6 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
      */
     public function isValid($value)
     {
-
         if (!is_string($value)) {
             $this->_error(self::INVALID);
             return false;
@@ -503,7 +502,6 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
 
         $this->_setValue($value);
         // Check input against IP address schema
-        
         if (preg_match('/^[0-9a-f:.]*$/i', $value) &&
             $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
             if (!($this->_options['allow'] & self::ALLOW_IP)) {
@@ -521,16 +519,29 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
         //     necessary to distinguish between the complete domain name and
         //     some local domain.
         //     
-        // Strip trailing '.' since it is not necessary to validate a non-IP
-        // hostname.
-        //
         // (see ZF-6363)
-        if (substr($value, -1) === '.') {
-            $value = substr($value, 0, strlen($value)-1);
-        }
         
-        // Check input against DNS hostname schema
+        // Local hostnames are allowed to be partitial (ending '.')
+        if ($this->_options['allow'] & self::ALLOW_LOCAL) {
+            if (substr($value, -1) === '.') {
+                $value = substr($value, 0, -1);
+                if (substr($value, -1) === '.') {
+                    // Empty hostnames (ending '..') are not allowed
+                    $this->_error(self::INVALID_LOCAL_NAME);
+                    return false;
+                }
+            }
+        }
+
         $domainParts = explode('.', $value);
+
+        // Prevent partitial IP V4 adresses (ending '.')
+        if ((count($domainParts) == 4) && preg_match('/^[0-9.a-e:.]*$/i', $value) &&
+            $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
+            $this->_error(self::INVALID_LOCAL_NAME);
+        }
+
+        // Check input against DNS hostname schema
         if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) {
             $status = false;
 
@@ -651,7 +662,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
         }
 
         // 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}$/';
+        $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/';
         $status = @preg_match($regexLocal, $value);
 
         // If the input passes as a local network name, and local network names are allowed, then the

+ 15 - 4
tests/Zend/Validate/HostnameTest.php

@@ -402,15 +402,26 @@ class Zend_Validate_HostnameTest extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * Ensure that a trailing "." in a hostname (but not ip) is permitted
+     * Ensure that a trailing "." in a local hostname is permitted
      *
      * @group ZF-6363
      */
     public function testTrailingDot()
     {
-        $this->assertTrue($this->_validator->isValid('example.com.'));
-        $this->assertFalse($this->_validator->isValid('example.com..'));
-        $this->assertFalse($this->_validator->isValid('1.2.3.4.'));
+        $valuesExpected = array(
+            array(Zend_Validate_Hostname::ALLOW_ALL, true, array('example.', 'example.com.', '~ex%20ample.com.')),
+            array(Zend_Validate_Hostname::ALLOW_ALL, false, array('example..',)),
+            array(Zend_Validate_Hostname::ALLOW_ALL, true, array('1.2.3.4.')),
+            array(Zend_Validate_Hostname::ALLOW_DNS, false, array('example..', '~ex%20ample..')),
+            array(Zend_Validate_Hostname::ALLOW_LOCAL, true, array('example.', 'example.com.')),
+        );
+
+        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);
+            }
+        }
     }
     
     /**