Ip.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Validate
  17. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * @see Zend_Validate_Abstract
  23. */
  24. require_once 'Zend/Validate/Abstract.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_Validate
  28. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Validate_Ip extends Zend_Validate_Abstract
  32. {
  33. const INVALID = 'ipInvalid';
  34. const NOT_IP_ADDRESS = 'notIpAddress';
  35. /**
  36. * @var array
  37. */
  38. protected $_messageTemplates = array(
  39. self::INVALID => "Invalid type given, value should be a string",
  40. self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address"
  41. );
  42. /**
  43. * internal options
  44. *
  45. * @var array
  46. */
  47. protected $_options = array(
  48. 'allowipv6' => true,
  49. 'allowipv4' => true
  50. );
  51. /**
  52. * Sets validator options
  53. *
  54. * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS)
  55. * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true)
  56. * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true)
  57. * @param Zend_Validate_Ip $ipValidator OPTIONAL
  58. * @return void
  59. * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs
  60. */
  61. public function __construct($options = array())
  62. {
  63. if ($options instanceof Zend_Config) {
  64. $options = $options->toArray();
  65. } else if (!is_array($options)) {
  66. $options = func_get_args();
  67. $temp['allowipv6'] = array_shift($options);
  68. if (!empty($options)) {
  69. $temp['allowipv4'] = array_shift($options);
  70. }
  71. $options = $temp;
  72. }
  73. $options += $this->_options;
  74. $this->setOptions($options);
  75. }
  76. /**
  77. * Returns all set options
  78. *
  79. * @return array
  80. */
  81. public function getOptions()
  82. {
  83. return $this->_options;
  84. }
  85. /**
  86. * Sets the options for this validator
  87. *
  88. * @param array $options
  89. * @return Zend_Validate_Ip
  90. */
  91. public function setOptions($options)
  92. {
  93. if (array_key_exists('allowipv6', $options)) {
  94. $this->_options['allowipv6'] = (boolean) $options['allowipv6'];
  95. }
  96. if (array_key_exists('allowipv4', $options)) {
  97. $this->_options['allowipv4'] = (boolean) $options['allowipv4'];
  98. }
  99. if (!$this->_options['allowipv4'] && !$this->_options['allowipv6']) {
  100. require_once 'Zend/Validate/Exception.php';
  101. throw new Zend_Validate_Exception('Nothing to validate. Check your options');
  102. }
  103. return $this;
  104. }
  105. /**
  106. * Defined by Zend_Validate_Interface
  107. *
  108. * Returns true if and only if $value is a valid IP address
  109. *
  110. * @param mixed $value
  111. * @return boolean
  112. */
  113. public function isValid($value)
  114. {
  115. if (!is_string($value)) {
  116. $this->_error(self::INVALID);
  117. return false;
  118. }
  119. $this->_setValue($value);
  120. if (($this->_options['allowipv4'] && !$this->_options['allowipv6'] && !$this->_validateIPv4($value)) ||
  121. (!$this->_options['allowipv4'] && $this->_options['allowipv6'] && !$this->_validateIPv6($value)) ||
  122. ($this->_options['allowipv4'] && $this->_options['allowipv6'] && !$this->_validateIPv4($value) && !$this->_validateIPv6($value))) {
  123. $this->_error(self::NOT_IP_ADDRESS);
  124. return false;
  125. }
  126. return true;
  127. }
  128. /**
  129. * Validates an IPv4 address
  130. *
  131. * @param string $value
  132. */
  133. protected function _validateIPv4($value) {
  134. $ip2long = ip2long($value);
  135. if($ip2long === false) {
  136. return false;
  137. }
  138. return $value == long2ip($ip2long);
  139. }
  140. /**
  141. * Validates an IPv6 address
  142. *
  143. * @param string $value Value to check against
  144. * @return boolean True when $value is a valid ipv6 address
  145. * False otherwise
  146. */
  147. protected function _validateIPv6($value) {
  148. if (strlen($value) < 3) {
  149. return $value == '::';
  150. }
  151. if (strpos($value, '.'))
  152. {
  153. $lastcolon = strrpos($value, ':');
  154. if (!($lastcolon && $this->_validateIPv4(substr($value, $lastcolon + 1)))) {
  155. return false;
  156. }
  157. $value = substr($value, 0, $lastcolon) . ':0:0';
  158. }
  159. if (strpos($value, '::') === false)
  160. {
  161. return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\Z/i', $value);
  162. }
  163. $colonCount = substr_count($value, ':');
  164. if ($colonCount < 8)
  165. {
  166. return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\Z/i', $value);
  167. }
  168. // special case with ending or starting double colon
  169. if ($colonCount == 8)
  170. {
  171. return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\Z/i', $value);
  172. }
  173. return false;
  174. }
  175. }