diff --git a/CHANGELOG.md b/CHANGELOG.md index 700c4888864b818c2e5e75233f0c2a3d7050f8bc..c2d56776b578e0e23804fe104efa7c05910ee771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ This is a changelog for Piwik platform developers. All changes for our HTTP API' ### Breaking Changes * Development related [console commands](http://developer.piwik.org/guides/piwik-on-the-command-line) are only available if the development mode is enabled. To enable the development mode execute `./console development:enable`. +### Deprecations +* Most methods of `Piwik\IP` have been deprecated in favor of the new [piwik/network](https://github.com/piwik/component-network) component. + +### Library updates +* Code for manipulating IP addresses has been moved to a separate standalone component: [piwik/network](https://github.com/piwik/component-network). Backward compatibility is kept in Piwik core. + ## Piwik 2.8.2 ### Library updates diff --git a/composer.json b/composer.json index 24e10fcedcfce82916aacca64aa904b14026eeac..47886d558bc53e56dfb0b4b2f6de244fcafd68d6 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,8 @@ "tedivm/jshrink": "~0.5.1", "mustangostang/spyc": "~0.5.0", "piwik/device-detector": "~2.0", - "piwik/decompress": "~0.1.1" + "piwik/decompress": "~0.1.1", + "piwik/network": "~0.1.0" }, "require-dev": { "aws/aws-sdk-php": "2.7.1", diff --git a/composer.lock b/composer.lock index 0180bb14819f36c286e9b266d291033ff711d28d..d522b5755dbf0b34e88c470944ff05031a7005df 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e8269e35cd792d2a4718e936459423bd", + "hash": "7fe1e059c2372246332679bfd15ca4a6", "packages": [ { "name": "leafo/lessphp", @@ -176,6 +176,38 @@ ], "time": "2014-10-06 20:13:03" }, + { + "name": "piwik/network", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/piwik/component-network.git", + "reference": "9037fa29509f86767e02ba58a57d4deb1d01a844" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/piwik/component-network/zipball/9037fa29509f86767e02ba58a57d4deb1d01a844", + "reference": "9037fa29509f86767e02ba58a57d4deb1d01a844", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Piwik\\Network\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "time": "2014-10-23 03:30:23" + }, { "name": "symfony/console", "version": "v2.5.5", diff --git a/core/IP.php b/core/IP.php index 691bc7442c19762df0a61e3a4793ae570d202139..10c2c62ef8d3a212125bc78a063f888e299e7445 100644 --- a/core/IP.php +++ b/core/IP.php @@ -9,6 +9,10 @@ namespace Piwik; +use Piwik\Network\IPUtils; +use Piwik\Network\IPv4; +use Piwik\Network\IPv6; + /** * Contains IP address helper functions (for both IPv4 and IPv6). * @@ -28,47 +32,18 @@ namespace Piwik; */ class IP { - const MAPPED_IPv4_START = '::ffff:'; - /** * Removes the port and the last portion of a CIDR IP address. * * @param string $ipString The IP address to sanitize. * @return string + * + * @deprecated Use IPUtils::sanitizeIp() instead + * @see \Piwik\Network\IPUtils */ public static function sanitizeIp($ipString) { - $ipString = trim($ipString); - - // CIDR notation, A.B.C.D/E - $posSlash = strrpos($ipString, '/'); - if ($posSlash !== false) { - $ipString = substr($ipString, 0, $posSlash); - } - - $posColon = strrpos($ipString, ':'); - $posDot = strrpos($ipString, '.'); - if ($posColon !== false) { - // IPv6 address with port, [A:B:C:D:E:F:G:H]:EEEE - $posRBrac = strrpos($ipString, ']'); - if ($posRBrac !== false && $ipString[0] == '[') { - $ipString = substr($ipString, 1, $posRBrac - 1); - } - - if ($posDot !== false) { - // IPv4 address with port, A.B.C.D:EEEE - if ($posColon > $posDot) { - $ipString = substr($ipString, 0, $posColon); - } - // else: Dotted quad IPv6 address, A:B:C:D:E:F:G.H.I.J - } else if (strpos($ipString, ':') === $posColon) { - $ipString = substr($ipString, 0, $posColon); - } - // else: IPv6 address, A:B:C:D:E:F:G:H - } - // else: IPv4 address, A.B.C.D - - return $ipString; + return IPUtils::sanitizeIp($ipString); } /** @@ -83,43 +58,15 @@ class IP * * @param string $ipRangeString IP address range * @return string|bool IP address range in CIDR notation OR false + * + * @deprecated Use IPUtils::sanitizeIpRange() instead + * @see \Piwik\Network\IPUtils */ public static function sanitizeIpRange($ipRangeString) { - $ipRangeString = trim($ipRangeString); - if (empty($ipRangeString)) { - return false; - } - - // IPv4 address with wildcards '*' - if (strpos($ipRangeString, '*') !== false) { - if (preg_match('~(^|\.)\*\.\d+(\.|$)~D', $ipRangeString)) { - return false; - } - - $bits = 32 - 8 * substr_count($ipRangeString, '*'); - $ipRangeString = str_replace('*', '0', $ipRangeString); - } + $result = IPUtils::sanitizeIpRange($ipRangeString); - // CIDR - if (($pos = strpos($ipRangeString, '/')) !== false) { - $bits = substr($ipRangeString, $pos + 1); - $ipRangeString = substr($ipRangeString, 0, $pos); - } - - // single IP - if (($ip = @inet_pton($ipRangeString)) === false) - return false; - - $maxbits = strlen($ip) * 8; - if (!isset($bits)) - $bits = $maxbits; - - if ($bits < 0 || $bits > $maxbits) { - return false; - } - - return "$ipRangeString/$bits"; + return $result === null ? false : $result; } /** @@ -127,12 +74,13 @@ class IP * * @param string $ipString IP address, either IPv4 or IPv6, e.g., `"127.0.0.1"`. * @return string Binary-safe string, e.g., `"\x7F\x00\x00\x01"`. + * + * @deprecated Use IPUtils::stringToBinaryIP() instead + * @see \Piwik\Network\IPUtils */ public static function P2N($ipString) { - // use @inet_pton() because it throws an exception and E_WARNING on invalid input - $ip = @inet_pton($ipString); - return $ip === false ? "\x00\x00\x00\x00" : $ip; + return IPUtils::stringToBinaryIP($ipString); } /** @@ -142,12 +90,12 @@ class IP * * @param string $ip IP address in network address format. * @return string IP address in presentation format. + * + * @deprecated Use IPUtils::binaryToStringIP() instead */ public static function N2P($ip) { - // use @inet_ntop() because it throws an exception and E_WARNING on invalid input - $ipStr = @inet_ntop($ip); - return $ipStr === false ? '0.0.0.0' : $ipStr; + return IPUtils::binaryToStringIP($ip); } /** @@ -155,10 +103,12 @@ class IP * * @param string $ip IP address in network address format. * @return string IP address in presentation format. + * + * @deprecated Will be removed */ public static function prettyPrint($ip) { - return self::N2P($ip); + return IPUtils::binaryToStringIP($ip); } /** @@ -167,27 +117,15 @@ class IP * * @param string $ip IP address in network address format. * @return bool True if IPv4, else false. + * + * @deprecated Will be removed + * @see \Piwik\Network\IP */ public static function isIPv4($ip) { - // in case mbstring overloads strlen function - $strlen = function_exists('mb_orig_strlen') ? 'mb_orig_strlen' : 'strlen'; - - // IPv4 - if ($strlen($ip) == 4) { - return true; - } + $ip = Network\IP::fromBinaryIP($ip); - // IPv6 - transitional address? - if ($strlen($ip) == 16) { - if (substr_compare($ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff", 0, 12) === 0 - || substr_compare($ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0, 12) === 0 - ) { - return true; - } - } - - return false; + return $ip instanceof IPv4; } /** @@ -200,12 +138,14 @@ class IP * * @param string $ip IPv4 address in network address format. * @return string IP address in presentation format. + * + * @deprecated This method was kept for backward compatibility and doesn't seem used */ public static function long2ip($ip) { // IPv4 if (strlen($ip) == 4) { - return self::N2P($ip); + return IPUtils::binaryToStringIP($ip); } // IPv6 - transitional address? @@ -214,7 +154,7 @@ class IP || substr_compare($ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0, 12) === 0 ) { // remap 128-bit IPv4-mapped and IPv4-compat addresses - return self::N2P(substr($ip, 12)); + return IPUtils::binaryToStringIP(substr($ip, 12)); } } @@ -227,10 +167,15 @@ class IP * * @param string $ip * @return bool + * + * @deprecated Will be removed + * @see \Piwik\Network\IP */ public static function isIPv6($ip) { - return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); + $ip = Network\IP::fromBinaryIP($ip); + + return $ip instanceof IPv6; } /** @@ -238,10 +183,19 @@ class IP * * @param string $ip * @return bool + * + * @deprecated Will be removed + * @see \Piwik\Network\IP */ public static function isMappedIPv4($ip) { - return substr($ip, 0, strlen(self::MAPPED_IPv4_START)) === self::MAPPED_IPv4_START; + $ip = Network\IP::fromStringIP($ip); + + if (! $ip instanceof IPv6) { + return false; + } + + return $ip->isMappedIPv4(); } /** @@ -249,10 +203,15 @@ class IP * * @param string $ip eg, `'::ffff:192.0.2.128'` * @return string eg, `'192.0.2.128'` + * + * @deprecated Use Piwik\Network\IP::toIPv4String() instead + * @see \Piwik\Network\IP */ public static function getIPv4FromMappedIPv6($ip) { - return substr($ip, strlen(self::MAPPED_IPv4_START)); + $ip = Network\IP::fromStringIP($ip); + + return $ip->toIPv4String(); } /** @@ -260,37 +219,15 @@ class IP * * @param array $ipRange An IP address range in presentation format. * @return array|bool Array `array($lowIp, $highIp)` in network address format, or false on failure. + * + * @deprecated Use Piwik\Network\IPUtils::getIPRangeBounds() instead + * @see \Piwik\Network\IPUtils */ public static function getIpsForRange($ipRange) { - if (strpos($ipRange, '/') === false) { - $ipRange = self::sanitizeIpRange($ipRange); - } - $pos = strpos($ipRange, '/'); - - $bits = substr($ipRange, $pos + 1); - $range = substr($ipRange, 0, $pos); - $high = $low = @inet_pton($range); - if ($low === false) { - return false; - } - - $lowLen = strlen($low); - $i = $lowLen - 1; - $bits = $lowLen * 8 - $bits; + $result = IPUtils::getIPRangeBounds($ipRange); - for ($n = (int)($bits / 8); $n > 0; $n--, $i--) { - $low[$i] = chr(0); - $high[$i] = chr(255); - } - - $n = $bits % 8; - if ($n) { - $low[$i] = chr(ord($low[$i]) & ~((1 << $n) - 1)); - $high[$i] = chr(ord($high[$i]) | ((1 << $n) - 1)); - } - - return array($low, $high); + return $result === null ? false : $result; } /** @@ -301,40 +238,15 @@ class IP * @param string $ip IP address in network address format * @param array $ipRanges List of IP address ranges * @return bool True if in any of the specified IP address ranges; else false. + * + * @deprecated Use Piwik\Network\IP::isInRanges() instead + * @see \Piwik\Network\IP */ public static function isIpInRange($ip, $ipRanges) { - $ipLen = strlen($ip); - if (empty($ip) || empty($ipRanges) || ($ipLen != 4 && $ipLen != 16)) { - return false; - } - - foreach ($ipRanges as $range) { - if (is_array($range)) { - // already split into low/high IP addresses - $range[0] = self::P2N($range[0]); - $range[1] = self::P2N($range[1]); - } else { - // expect CIDR format but handle some variations - $range = self::getIpsForRange($range); - } - if ($range === false) { - continue; - } - - $low = $range[0]; - $high = $range[1]; - if (strlen($low) != $ipLen) { - continue; - } + $ip = Network\IP::fromBinaryIP($ip); - // binary-safe string comparison - if ($ip >= $low && $ip <= $high) { - return true; - } - } - - return false; + return $ip->isInRanges($ipRanges); } /** @@ -356,7 +268,7 @@ class IP } $ipString = self::getNonProxyIpFromHeader($default, $clientHeaders); - return self::sanitizeIp($ipString); + return IPUtils::sanitizeIp($ipString); } /** @@ -406,7 +318,8 @@ class IP $elements = explode(',', $csv); for ($i = count($elements); $i--;) { $element = trim(Common::sanitizeInputValue($elements[$i])); - if (empty($excludedIps) || (!in_array($element, $excludedIps) && !self::isIpInRange(self::P2N(self::sanitizeIp($element)), $excludedIps))) { + $ip = \Piwik\Network\IP::fromStringIP(IPUtils::sanitizeIp($element)); + if (empty($excludedIps) || (!in_array($element, $excludedIps) && !$ip->isInRanges($excludedIps))) { return $element; } } @@ -415,16 +328,20 @@ class IP } /** - * Retirms the hostname for a given IP address. + * Returns the hostname for a given IP address. * * @param string $ipStr Human-readable IP address. * @return string The hostname or unmodified $ipStr on failure. + * + * @deprecated Use Piwik\Network\IP::getHostname() instead + * @see \Piwik\Network\IP */ public static function getHostByAddr($ipStr) { - // PHP's reverse lookup supports ipv4 and ipv6 - // except on Windows before PHP 5.3 - $host = strtolower(@gethostbyaddr($ipStr)); - return $host === '' ? $ipStr : $host; + $ip = Network\IP::fromStringIP($ipStr); + + $host = $ip->getHostname(); + + return $host === null ? $ipStr : $host; } } diff --git a/core/Tracker/Request.php b/core/Tracker/Request.php index 36b1e3a5b9e59b93cc73a8a095fd127085d1e0bf..b733ae30eae1c6d28b3d17f6dae53d83a367c024 100644 --- a/core/Tracker/Request.php +++ b/core/Tracker/Request.php @@ -13,6 +13,7 @@ use Piwik\Common; use Piwik\Config; use Piwik\Cookie; use Piwik\IP; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugins\CustomVariables\CustomVariables; use Piwik\Registry; @@ -563,9 +564,7 @@ class Request public function getIp() { - $ipString = $this->getIpString(); - $ip = IP::P2N($ipString); - return $ip; + return IPUtils::stringToBinaryIP($this->getIpString()); } public function getForcedUserId() diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index c8fb12d3897bef83f7c99157854423af4e09dccc..8bdf641ece08d250ce8c76c4405d38109d94a262 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -11,7 +11,7 @@ namespace Piwik\Tracker; use Piwik\Common; use Piwik\Config; -use Piwik\IP; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugin\Dimension\VisitDimension; use Piwik\Tracker; @@ -241,7 +241,7 @@ class Visit implements VisitInterface */ protected function handleExistingVisit($visitor, $action, $visitIsConverted) { - Common::printDebug("Visit is known (IP = " . IP::N2P($this->getVisitorIp()) . ")"); + Common::printDebug("Visit is known (IP = " . IPUtils::binaryToStringIP($this->getVisitorIp()) . ")"); $valuesToUpdate = $this->getExistingVisitFieldsToUpdate($visitor, $action, $visitIsConverted); @@ -301,7 +301,7 @@ class Visit implements VisitInterface */ protected function handleNewVisit($visitor, $action, $visitIsConverted) { - Common::printDebug("New Visit (IP = " . IP::N2P($this->getVisitorIp()) . ")"); + Common::printDebug("New Visit (IP = " . IPUtils::binaryToStringIP($this->getVisitorIp()) . ")"); $this->setNewVisitorInformation($visitor); @@ -467,7 +467,7 @@ class Visit implements VisitInterface $debugVisitInfo = $this->visitorInfo; $debugVisitInfo['idvisitor'] = bin2hex($debugVisitInfo['idvisitor']); $debugVisitInfo['config_id'] = bin2hex($debugVisitInfo['config_id']); - $debugVisitInfo['location_ip'] = IP::N2P($debugVisitInfo['location_ip']); + $debugVisitInfo['location_ip'] = IPUtils::binaryToStringIP($debugVisitInfo['location_ip']); Common::printDebug($debugVisitInfo); } diff --git a/core/Tracker/VisitExcluded.php b/core/Tracker/VisitExcluded.php index 48eb1e3db75e72434ef30299ca9c0303d84b5a02..ca481218cb9149ac96a2ecd5c7fd59e679984e59 100644 --- a/core/Tracker/VisitExcluded.php +++ b/core/Tracker/VisitExcluded.php @@ -213,8 +213,9 @@ class VisitExcluded $websiteAttributes = Cache::getCacheWebsiteAttributes($this->idSite); if (!empty($websiteAttributes['excluded_ips'])) { - if (IP::isIpInRange($this->ip, $websiteAttributes['excluded_ips'])) { - Common::printDebug('Visitor IP ' . IP::N2P($this->ip) . ' is excluded from being tracked'); + $ip = \Piwik\Network\IP::fromBinaryIP($this->ip); + if ($ip->isInRanges($websiteAttributes['excluded_ips'])) { + Common::printDebug('Visitor IP ' . $ip->toString() . ' is excluded from being tracked'); return true; } } diff --git a/core/Url.php b/core/Url.php index 1d34c17ca3b3c897476a0bb6de537bcf3ad48149..dd9503ca664bbe9fcf1a19604720ce5897f16dcd 100644 --- a/core/Url.php +++ b/core/Url.php @@ -10,6 +10,7 @@ namespace Piwik; use Exception; +use Piwik\Network\IPUtils; use Piwik\Session; /** @@ -547,7 +548,7 @@ class Url $disableHostCheck = Config::getInstance()->General['enable_trusted_host_check'] == 0; // compare scheme and host $parsedUrl = @parse_url($url); - $host = IP::sanitizeIp(@$parsedUrl['host']); + $host = IPUtils::sanitizeIp(@$parsedUrl['host']); return !empty($host) && ($disableHostCheck || in_array($host, $hosts)) && !empty($parsedUrl['scheme']) @@ -585,7 +586,7 @@ class Url */ public static function getHostSanitized($host) { - return IP::sanitizeIp($host); + return IPUtils::sanitizeIp($host); } protected static function getHostsFromConfig($domain, $key) diff --git a/misc/others/geoipUpdateRows.php b/misc/others/geoipUpdateRows.php index a7564d25ba3a2332efa74e87ed13134064ea49d4..5f36ed5e7d36528a10e2f2f4268e0cd19a29d94c 100755 --- a/misc/others/geoipUpdateRows.php +++ b/misc/others/geoipUpdateRows.php @@ -1,10 +1,8 @@ <?php use Piwik\Common; -use Piwik\Config; use Piwik\Db; -use Piwik\FrontController; -use Piwik\IP; use Piwik\Log; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp\Pecl; use Piwik\Plugins\UserCountry\LocationProvider; @@ -183,7 +181,7 @@ for (; $start < $end; $start += $limit) { continue; } - $ip = IP::N2P($row['location_ip']); + $ip = IPUtils::binaryToStringIP($row['location_ip']); $location = $provider->getLocation(array('ip' => $ip)); if (!empty($location[LocationProvider::COUNTRY_CODE_KEY])) { diff --git a/plugins/Live/Visitor.php b/plugins/Live/Visitor.php index 965a61ff8fc9e702576c2009761c3da778a43128..27873ec2a1f3d9660675a7b4be6b26556de64a56 100644 --- a/plugins/Live/Visitor.php +++ b/plugins/Live/Visitor.php @@ -13,7 +13,7 @@ use Piwik\DataAccess\LogAggregator; use Piwik\DataTable\Filter\ColumnDelete; use Piwik\Date; use Piwik\Db; -use Piwik\IP; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugins\CustomVariables\CustomVariables; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp; @@ -97,7 +97,7 @@ class Visitor implements VisitorInterface function getIp() { if (isset($this->details['location_ip'])) { - return IP::N2P($this->details['location_ip']); + return IPUtils::binaryToStringIP($this->details['location_ip']); } return null; } diff --git a/plugins/PrivacyManager/IPAnonymizer.php b/plugins/PrivacyManager/IPAnonymizer.php index de588c59fdb8dd94e9b65be668064a97aa8ad30a..a70312916f3fb26827ec661b9487eea6d9f5dd35 100644 --- a/plugins/PrivacyManager/IPAnonymizer.php +++ b/plugins/PrivacyManager/IPAnonymizer.php @@ -9,7 +9,7 @@ namespace Piwik\Plugins\PrivacyManager; use Piwik\Common; -use Piwik\IP; +use Piwik\Network\IP; /** * Anonymize visitor IP addresses to comply with the privacy laws/guidelines in countries, such as Germany. @@ -19,51 +19,36 @@ class IPAnonymizer /** * Internal function to mask portions of the visitor IP address * - * @param string $ip IP address in network address format + * @param IP $ip * @param int $maskLength Number of octets to reset - * @return string + * @return IP */ - public static function applyIPMask($ip, $maskLength) + public static function applyIPMask(IP $ip, $maskLength) { - // IPv4 or mapped IPv4 in IPv6 - if (IP::isIPv4($ip)) { - $i = strlen($ip); - if ($maskLength > $i) { - $maskLength = $i; - } + $newIpObject = $ip->anonymize($maskLength); - while ($maskLength-- > 0) { - $ip[--$i] = chr(0); - } - } else { - $masks = array( - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', - 'ffff:ffff:ffff:ffff::', - 'ffff:ffff:ffff:0000::', - 'ffff:ff00:0000:0000::' - ); - $ip = $ip & pack('a16', inet_pton($masks[$maskLength])); - } - return $ip; + return $newIpObject; } /** * Hook on Tracker.Visit.setVisitorIp to anomymize visitor IP addresses + * @param string $ip IP address in binary format (network format) */ public function setVisitorIpAddress(&$ip) { + $ipObject = IP::fromBinaryIP($ip); + if (!$this->isActive()) { - Common::printDebug("Visitor IP was _not_ anonymized: ". IP::N2P($ip)); + Common::printDebug("Visitor IP was _not_ anonymized: ". $ipObject->toString()); return; } - $originalIp = $ip; - $privacyConfig = new Config(); - $ip = self::applyIPMask($ip, $privacyConfig->ipAddressMaskLength); + $newIpObject = self::applyIPMask($ipObject, $privacyConfig->ipAddressMaskLength); + $ip = $newIpObject->toBinary(); - Common::printDebug("Visitor IP (was: ". IP::N2P($originalIp) .") has been anonymized: ". IP::N2P($ip)); + Common::printDebug("Visitor IP (was: ". $ipObject->toString() .") has been anonymized: ". $newIpObject->toString()); } /** diff --git a/plugins/PrivacyManager/tests/Unit/AnonymizeIPTest.php b/plugins/PrivacyManager/tests/Unit/AnonymizeIPTest.php index 0ed4e6e4ca7d9067f7839036709d7ab3a671fd24..d5e50e520923596f11f0cf5403e22efe52e315f6 100644 --- a/plugins/PrivacyManager/tests/Unit/AnonymizeIPTest.php +++ b/plugins/PrivacyManager/tests/Unit/AnonymizeIPTest.php @@ -8,7 +8,7 @@ namespace Piwik\Plugins\PrivacyManager\tests; -use Piwik\IP; +use Piwik\Network\IP; use Piwik\Plugins\PrivacyManager\IPAnonymizer; require_once PIWIK_INCLUDE_PATH . '/plugins/PrivacyManager/IPAnonymizer.php'; @@ -58,23 +58,26 @@ class AnonymizeIPTest extends \PHPUnit_Framework_TestCase * @dataProvider getipv4Addresses * @group Plugins */ - public function testApplyIPMask($ip, $expected) + public function testApplyIPMask($ipString, $expected) { + $ip = IP::fromStringIP($ipString); + // each IP is tested with 0 to 4 octets masked for ($maskLength = 0; $maskLength <= 4; $maskLength++) { - $res = IPAnonymizer::applyIPMask(IP::P2N($ip), $maskLength); - $this->assertEquals($expected[$maskLength], $res, "Got " . bin2hex($res) . ", Expected " . bin2hex($expected[$maskLength])); + $res = IPAnonymizer::applyIPMask($ip, $maskLength); + $this->assertEquals($expected[$maskLength], $res->toBinary(), "Got " . $res . ", Expected " . bin2hex($expected[$maskLength])); } // edge case (bounds check) - $this->assertEquals("\x00\x00\x00\x00", IPAnonymizer::applyIPMask(IP::P2N($ip), 5)); + $this->assertEquals("\x00\x00\x00\x00", IPAnonymizer::applyIPMask($ip, 5)->toBinary()); // mask IPv4 mapped addresses + $mappedIp = IP::fromStringIP('::ffff:' . $ipString); for ($maskLength = 0; $maskLength <= 4; $maskLength++) { - $res = IPAnonymizer::applyIPMask(IP::P2N('::ffff:' . $ip), $maskLength); - $this->assertEquals($res, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . $expected[$maskLength], "Got " . bin2hex($res) . ", Expected " . bin2hex($expected[$maskLength])); + $res = IPAnonymizer::applyIPMask($mappedIp, $maskLength); + $this->assertEquals("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . $expected[$maskLength], $res->toBinary(), "Got " . $res . ", Expected " . bin2hex($expected[$maskLength])); } - $this->assertEquals("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00", IPAnonymizer::applyIPMask(IP::P2N('::ffff:' . $ip), 5)); + $this->assertEquals("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00", IPAnonymizer::applyIPMask($mappedIp, 5)->toBinary()); } /** @@ -85,8 +88,8 @@ class AnonymizeIPTest extends \PHPUnit_Framework_TestCase { // each IP is tested with 0 to 4 octets masked for ($maskLength = 0; $maskLength < 4; $maskLength++) { - $res = IPAnonymizer::applyIPMask(IP::P2N($ip), $maskLength); - $this->assertEquals($expected[$maskLength], $res, "Got " . bin2hex($res) . ", Expected " . bin2hex($expected[$maskLength]) . ", Mask Level " . $maskLength); + $res = IPAnonymizer::applyIPMask(IP::fromStringIP($ip), $maskLength); + $this->assertEquals($expected[$maskLength], $res->toBinary(), "Got " . $res . ", Expected " . bin2hex($expected[$maskLength]) . ", Mask Level " . $maskLength); } } } \ No newline at end of file diff --git a/plugins/Provider/Columns/Provider.php b/plugins/Provider/Columns/Provider.php index c20b75ac9c041e2dcd55969301bc26fa692a318c..cba1b8b9f58df6bb51c34c9a6add5273551a4518 100644 --- a/plugins/Provider/Columns/Provider.php +++ b/plugins/Provider/Columns/Provider.php @@ -10,6 +10,7 @@ namespace Piwik\Plugins\Provider\Columns; use Piwik\Common; use Piwik\IP; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugin\Dimension\VisitDimension; use Piwik\Plugin\Segment; @@ -54,7 +55,7 @@ class Provider extends VisitDimension $ip = $request->getIp(); } - $ip = IP::N2P($ip); + $ip = IPUtils::binaryToStringIP($ip); // In case the IP was anonymized, we should not continue since the DNS reverse lookup will fail and this will slow down tracking if (substr($ip, -2, 2) == '.0') { diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index 08beed366f26fcde06dce4642590a92958b6beb4..02f50a1ece707336168eb4f155719b1f34759221 100644 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -15,6 +15,7 @@ use Piwik\Date; use Piwik\Db; use Piwik\IP; use Piwik\MetricsFormatter; +use Piwik\Network\IPUtils; use Piwik\Option; use Piwik\Piwik; use Piwik\ProxyHttp; @@ -745,12 +746,12 @@ class API extends \Piwik\Plugin\API */ public function getIpsForRange($ipRange) { - $range = IP::getIpsForRange($ipRange); - if ($range === false) { + $range = IPUtils::getIPRangeBounds($ipRange); + if ($range === null) { return false; } - return array(IP::N2P($range[0]), IP::N2P($range[1])); + return array(IPUtils::binaryToStringIP($range[0]), IPUtils::binaryToStringIP($range[1])); } /** @@ -1322,7 +1323,7 @@ class API extends \Piwik\Plugin\API */ private function isValidIp($ip) { - return IP::getIpsForRange($ip) !== false; + return IPUtils::getIPRangeBounds($ip) !== null; } /** diff --git a/plugins/UserCountry/Columns/Base.php b/plugins/UserCountry/Columns/Base.php index c3ee4611834e3b8041e4dd2897dccc72a6b59ffa..3e4678a0e98f0b67bdafacace53864603700f336 100644 --- a/plugins/UserCountry/Columns/Base.php +++ b/plugins/UserCountry/Columns/Base.php @@ -9,12 +9,12 @@ namespace Piwik\Plugins\UserCountry\Columns; use Piwik\Common; +use Piwik\Network\IPUtils; use Piwik\Plugin\Dimension\VisitDimension; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp; use Piwik\Plugins\UserCountry\LocationProvider; use Piwik\Plugins\PrivacyManager\Config as PrivacyManagerConfig; use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider; -use Piwik\IP; use Piwik\Tracker\Visitor; use Piwik\Tracker\Visit; use Piwik\Tracker\Request; @@ -111,7 +111,7 @@ abstract class Base extends VisitDimension $ip = $anonymizedIp; } - $ipAddress = IP::N2P($ip); + $ipAddress = IPUtils::binaryToStringIP($ip); return $ipAddress; } diff --git a/plugins/UserCountry/LocationProvider.php b/plugins/UserCountry/LocationProvider.php index d0ffd93f51da9f93f64feaa07a71bb6ee562dee9..a5a656c42f263bc9da546de3790df51184b2e48e 100755 --- a/plugins/UserCountry/LocationProvider.php +++ b/plugins/UserCountry/LocationProvider.php @@ -444,23 +444,17 @@ abstract class LocationProvider /** * Returns an IP address from an array that was passed into getLocation. This - * will return an IPv4 address or false if the address is IPv6 (IPv6 is not + * will return an IPv4 address or null if the address is IPv6 (IPv6 is not * supported yet). * * @param array $info Must have 'ip' key. - * @return string|bool + * @return string|null */ protected function getIpFromInfo($info) { - $ip = $info['ip']; - if (IP::isMappedIPv4($ip)) { - return IP::getIPv4FromMappedIPv6($ip); - } else if (IP::isIPv6($ip)) // IPv6 is not supported (yet) - { - return false; - } else { - return $ip; - } + $ip = \Piwik\Network\IP::fromStringIP($info['ip']); + + return $ip->toIPv4String(); } } diff --git a/tests/PHPUnit/Integration/Tracker/VisitTest.php b/tests/PHPUnit/Integration/Tracker/VisitTest.php index 0d1837e2c109f0f2e7936b1a431305ae1014401a..292b98737d03c485257f5641082c8a0389783341 100644 --- a/tests/PHPUnit/Integration/Tracker/VisitTest.php +++ b/tests/PHPUnit/Integration/Tracker/VisitTest.php @@ -5,8 +5,9 @@ * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ + use Piwik\Access; -use Piwik\IP; +use Piwik\Network\IPUtils; use Piwik\Plugins\SitesManager\API; use Piwik\Tracker\Request; use Piwik\Tracker\VisitExcluded; @@ -86,7 +87,7 @@ class Core_Tracker_VisitTest extends IntegrationTestCase // test that IPs within the range, or the given IP, are excluded foreach ($tests as $ip => $expected) { - $testIpIsExcluded = IP::P2N($ip); + $testIpIsExcluded = IPUtils::stringToBinaryIP($ip); $excluded = new VisitExcluded_public($request, $testIpIsExcluded); $this->assertSame($expected, $excluded->public_isVisitorIpExcluded($testIpIsExcluded)); @@ -195,7 +196,7 @@ class Core_Tracker_VisitTest extends IntegrationTestCase $request = new Request(array('idsite' => $idsite, 'bots' => 0)); foreach ($isIpBot as $ip => $isBot) { - $excluded = new VisitExcluded_public($request, IP::P2N($ip)); + $excluded = new VisitExcluded_public($request, IPUtils::stringToBinaryIP($ip)); $this->assertSame($isBot, $excluded->public_isNonHumanBot(), $ip); } diff --git a/tests/PHPUnit/Unit/IPTest.php b/tests/PHPUnit/Unit/IPTest.php index f12d37dfed2ef711fcefc98275591bb3ea6e9f92..39fd083e5f70e2588ee1d4e0a72ed51d1087a489 100644 --- a/tests/PHPUnit/Unit/IPTest.php +++ b/tests/PHPUnit/Unit/IPTest.php @@ -1,301 +1,17 @@ <?php -use Piwik\Common; -use Piwik\Config; -use Piwik\IP; -use Piwik\SettingsServer; - /** * Piwik - free/libre analytics platform * * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -class IPTest extends PHPUnit_Framework_TestCase -{ - /** - * Dataprovider for testSanitizeIp - */ - public function getIPData() - { - return array( // input, output - // single IPv4 address - array('127.0.0.1', '127.0.0.1'), - - // single IPv6 address (ambiguous) - array('::1', '::1'), - array('::ffff:127.0.0.1', '::ffff:127.0.0.1'), - array('2001:5c0:1000:b::90f8', '2001:5c0:1000:b::90f8'), - - // single IPv6 address - array('[::1]', '::1'), - array('[2001:5c0:1000:b::90f8]', '2001:5c0:1000:b::90f8'), - array('[::ffff:127.0.0.1]', '::ffff:127.0.0.1'), - - // single IPv4 address (CIDR notation) - array('192.168.1.1/32', '192.168.1.1'), - - // single IPv6 address (CIDR notation) - array('::1/128', '::1'), - array('::ffff:127.0.0.1/128', '::ffff:127.0.0.1'), - array('2001:5c0:1000:b::90f8/128', '2001:5c0:1000:b::90f8'), - - // IPv4 address with port - array('192.168.1.2:80', '192.168.1.2'), - - // IPv6 address with port - array('[::1]:80', '::1'), - array('[::ffff:127.0.0.1]:80', '::ffff:127.0.0.1'), - array('[2001:5c0:1000:b::90f8]:80', '2001:5c0:1000:b::90f8'), - - // hostnames with port? - array('localhost', 'localhost'), - array('localhost:80', 'localhost'), - array('www.example.com', 'www.example.com'), - array('example.com:80', 'example.com'), - array('example.com:8080', 'example.com'), - array('sub.example.com:8080', 'sub.example.com'), - ); - } - - /** - * @dataProvider getIPData - * @group Core - */ - public function testSanitizeIp($ip, $expected) - { - $this->assertEquals($expected, IP::sanitizeIp($ip)); - } - - /** - * Dataprovider for testSanitizeIpRange - */ - public function getIPRangeData() - { - return array( - array('', false), - array(' 127.0.0.1 ', '127.0.0.1/32'), - array('192.168.1.0', '192.168.1.0/32'), - array('192.168.1.1/24', '192.168.1.1/24'), - array('192.168.1.2/16', '192.168.1.2/16'), - array('192.168.1.3/8', '192.168.1.3/8'), - array('192.168.2.*', '192.168.2.0/24'), - array('192.169.*.*', '192.169.0.0/16'), - array('193.*.*.*', '193.0.0.0/8'), - array('*.*.*.*', '0.0.0.0/0'), - array('*.*.*.1', false), - array('*.*.1.1', false), - array('*.1.1.1', false), - array('1.*.1.1', false), - array('1.1.*.1', false), - array('1.*.*.1', false), - array('::1', '::1/128'), - array('::ffff:127.0.0.1', '::ffff:127.0.0.1/128'), - array('2001:5c0:1000:b::90f8', '2001:5c0:1000:b::90f8/128'), - array('::1/64', '::1/64'), - array('::ffff:127.0.0.1/64', '::ffff:127.0.0.1/64'), - array('2001:5c0:1000:b::90f8/64', '2001:5c0:1000:b::90f8/64'), - ); - } - - /** - * @dataProvider getIPRangeData - * @group Core - */ - public function testSanitizeIpRange($ip, $expected) - { - $this->assertEquals($expected, IP::sanitizeIpRange($ip)); - } - - /** - * Dataprovider for testP2N - */ - public function getP2NTestData() - { - return array( - // IPv4 - array('0.0.0.0', "\x00\x00\x00\x00"), - array('127.0.0.1', "\x7F\x00\x00\x01"), - array('192.168.1.12', "\xc0\xa8\x01\x0c"), - array('255.255.255.255', "\xff\xff\xff\xff"), - - // IPv6 - array('::', "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array('::1', "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), - array('::fffe:7f00:1', "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x7f\x00\x00\x01"), - array('::ffff:127.0.0.1', "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\x01"), - array('2001:5c0:1000:b::90f8', "\x20\x01\x05\xc0\x10\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x90\xf8"), - ); - } - - /** - * @dataProvider getP2NTestData - * @group Core - */ - public function testP2N($P, $N) - { - $this->assertEquals($N, IP::P2N($P)); - } - - /** - * Dataprovider for testP2NInvalidInput - */ - public function getP2NInvalidInputData() - { - return array( - // not a series of dotted numbers - array(null), - array(''), - array('alpha'), - array('...'), - - // missing an octet - array('.0.0.0'), - array('0..0.0'), - array('0.0..0'), - array('0.0.0.'), - - // octets must be 0-255 - array('-1.0.0.0'), - array('1.1.1.256'), - - // leading zeros not supported (i.e., can be ambiguous, e.g., octal) - array('07.07.07.07'), - ); - } - - /** - * @group Core - * - * @dataProvider getP2NInvalidInputData - */ - public function testP2NInvalidInput($P) - { - $this->assertEquals("\x00\x00\x00\x00", IP::P2N($P)); - } - - /** - * @group Core - */ - public function getN2PTestData() - { - // a valid network address is either 4 or 16 bytes; those lines are intentionally left blank ;) - return array( - array(null), - array(''), - array("\x01"), - array("\x01\x00"), - array("\x01\x00\x00"), - array("\x01\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - ); - } - - /** - * @dataProvider getP2NTestData - * @group Core - */ - public function testN2P($P, $N) - { - $this->assertEquals($P, IP::N2P($N), "$P vs" . IP::N2P($N)); - } - - /** - * @dataProvider getN2PTestData - * @group Core - */ - public function testN2PinvalidInput($N) - { - $this->assertEquals("0.0.0.0", IP::N2P($N), bin2hex($N)); - } - - /** - * @dataProvider getP2NTestData - * @group Core - */ - public function testPrettyPrint($P, $N) - { - $this->assertEquals($P, IP::prettyPrint($N), "$P vs" . IP::N2P($N)); - } - - /** - * @dataProvider getN2PTestData - * @group Core - */ - public function testPrettyPrintInvalidInput($N) - { - $this->assertEquals("0.0.0.0", IP::prettyPrint($N), bin2hex($N)); - } - - /** - * Dataprovider for IP4 test data - */ - public function getIPv4Data() - { - // a valid network address is either 4 or 16 bytes; those lines are intentionally left blank ;) - return array( - // invalid - array(null, false), - array("", false), - - // IPv4 - array("\x00\x00\x00\x00", true), - array("\x7f\x00\x00\x01", true), - - // IPv4-compatible (this transitional format is deprecated in RFC 4291, section 2.5.5.1) - array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x01", true), - - // IPv4-mapped (RFC 4291, 2.5.5.2) - array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xc0\xa8\x01\x02", true), - - // other IPv6 address - array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\xc0\xa8\x01\x03", false), - array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\xa8\x01\x04", false), - array("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x05", false), - - /* - * We assume all stored IP addresses (pre-Piwik 1.4) were converted from UNSIGNED INT to VARBINARY. - * The following is just for informational purposes. - */ - - // 192.168.1.0 - array('-1062731520', false), - array('3232235776', false), - - // 10.10.10.10 - array('168430090', false), - - // 0.0.39.15 - this is the ambiguous case (i.e., 4 char string) - array('9999', true), - array("\x39\x39\x39\x39", true), - - // 0.0.3.231 - array('999', false), - array("\x39\x39\x39", false), - ); - - } - - /** - * @dataProvider getIPv4Data - * @group Core - */ - public function testIsIPv4($ip, $bool) - { - $this->assertEquals($bool, IP::isIPv4($ip), bin2hex($ip)); - } +use Piwik\Common; +use Piwik\Config; +use Piwik\IP; +class IPTest extends PHPUnit_Framework_TestCase +{ /** * Dataprovider for long2ip test */ @@ -354,204 +70,6 @@ class IPTest extends PHPUnit_Framework_TestCase $this->assertEquals($P, Common::long2ip($N), bin2hex($N)); } - /** - * Dataprovider for ip range test - */ - public function getIPsForRangeTest() - { - return array( - - // invalid ranges - array(null, false), - array('', false), - array('0', false), - - // single IPv4 - array('127.0.0.1', array("\x7f\x00\x00\x01", "\x7f\x00\x00\x01")), - - // IPv4 with wildcards - array('192.168.1.*', array("\xc0\xa8\x01\x00", "\xc0\xa8\x01\xff")), - array('192.168.*.*', array("\xc0\xa8\x00\x00", "\xc0\xa8\xff\xff")), - array('192.*.*.*', array("\xc0\x00\x00\x00", "\xc0\xff\xff\xff")), - array('*.*.*.*', array("\x00\x00\x00\x00", "\xff\xff\xff\xff")), - - // single IPv4 in expected CIDR notation - array('192.168.1.1/24', array("\xc0\xa8\x01\x00", "\xc0\xa8\x01\xff")), - - array('192.168.1.127/32', array("\xc0\xa8\x01\x7f", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/31', array("\xc0\xa8\x01\x7e", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/30', array("\xc0\xa8\x01\x7c", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/29', array("\xc0\xa8\x01\x78", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/28', array("\xc0\xa8\x01\x70", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/27', array("\xc0\xa8\x01\x60", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/26', array("\xc0\xa8\x01\x40", "\xc0\xa8\x01\x7f")), - array('192.168.1.127/25', array("\xc0\xa8\x01\x00", "\xc0\xa8\x01\x7f")), - - array('192.168.1.255/32', array("\xc0\xa8\x01\xff", "\xc0\xa8\x01\xff")), - array('192.168.1.255/31', array("\xc0\xa8\x01\xfe", "\xc0\xa8\x01\xff")), - array('192.168.1.255/30', array("\xc0\xa8\x01\xfc", "\xc0\xa8\x01\xff")), - array('192.168.1.255/29', array("\xc0\xa8\x01\xf8", "\xc0\xa8\x01\xff")), - array('192.168.1.255/28', array("\xc0\xa8\x01\xf0", "\xc0\xa8\x01\xff")), - array('192.168.1.255/27', array("\xc0\xa8\x01\xe0", "\xc0\xa8\x01\xff")), - array('192.168.1.255/26', array("\xc0\xa8\x01\xc0", "\xc0\xa8\x01\xff")), - array('192.168.1.255/25', array("\xc0\xa8\x01\x80", "\xc0\xa8\x01\xff")), - - array('192.168.255.255/24', array("\xc0\xa8\xff\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/23', array("\xc0\xa8\xfe\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/22', array("\xc0\xa8\xfc\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/21', array("\xc0\xa8\xf8\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/20', array("\xc0\xa8\xf0\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/19', array("\xc0\xa8\xe0\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/18', array("\xc0\xa8\xc0\x00", "\xc0\xa8\xff\xff")), - array('192.168.255.255/17', array("\xc0\xa8\x80\x00", "\xc0\xa8\xff\xff")), - - // single IPv6 - array('::1', array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")), - - // single IPv6 in expected CIDR notation - array('::1/128', array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")), - array('::1/127', array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")), - array('::fffe:7f00:1/120', array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x7f\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x7f\x00\x00\xff")), - array('::ffff:127.0.0.1/120', array("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\xff")), - - array('2001:ca11:911::b0b:15:dead/128', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xad", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xad")), - array('2001:ca11:911::b0b:15:dead/127', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xac", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xad")), - array('2001:ca11:911::b0b:15:dead/126', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xac", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xaf")), - array('2001:ca11:911::b0b:15:dead/125', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xa8", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xaf")), - array('2001:ca11:911::b0b:15:dead/124', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xa0", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xaf")), - array('2001:ca11:911::b0b:15:dead/123', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xa0", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xbf")), - array('2001:ca11:911::b0b:15:dead/122', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\x80", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xbf")), - array('2001:ca11:911::b0b:15:dead/121', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\x80", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xff")), - array('2001:ca11:911::b0b:15:dead/120', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\xff")), - array('2001:ca11:911::b0b:15:dead/119', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xde\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdf\xff")), - array('2001:ca11:911::b0b:15:dead/118', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdc\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdf\xff")), - array('2001:ca11:911::b0b:15:dead/117', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xd8\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdf\xff")), - array('2001:ca11:911::b0b:15:dead/116', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xd0\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdf\xff")), - array('2001:ca11:911::b0b:15:dead/115', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xc0\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xdf\xff")), - array('2001:ca11:911::b0b:15:dead/114', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xc0\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xff\xff")), - array('2001:ca11:911::b0b:15:dead/113', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\x80\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xff\xff")), - array('2001:ca11:911::b0b:15:dead/112', array("\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\x00\x00", "\x20\x01\xca\x11\x09\x11\x00\x00\x00\x00\x0b\x0b\x00\x15\xff\xff")), - ); - } - - /** - * @dataProvider getIPsForRangeTest - * @group Core - */ - public function testGetIpsForRange($range, $expected) - { - $this->assertEquals($expected, IP::getIpsForRange($range)); - } - - /** - * Dataprovider for testIsIpInRange - */ - public function getIpsInRangeData() - { - return array( - array('192.168.1.10', array( - '192.168.1.9' => false, - '192.168.1.10' => true, - '192.168.1.11' => false, - - // IPv6 addresses (including IPv4 mapped) have to be compared against IPv6 address ranges - '::ffff:192.168.1.10' => false, - )), - - array('::ffff:192.168.1.10', array( - '::ffff:192.168.1.9' => false, - '::ffff:192.168.1.10' => true, - '::ffff:c0a8:010a' => true, - '0000:0000:0000:0000:0000:ffff:c0a8:010a' => true, - '::ffff:192.168.1.11' => false, - - // conversely, IPv4 addresses have to be compared against IPv4 address ranges - '192.168.1.10' => false, - )), - - array('192.168.1.10/32', array( - '192.168.1.9' => false, - '192.168.1.10' => true, - '192.168.1.11' => false, - )), - - array('192.168.1.10/31', array( - '192.168.1.9' => false, - '192.168.1.10' => true, - '192.168.1.11' => true, - '192.168.1.12' => false, - )), - - array('192.168.1.128/25', array( - '192.168.1.127' => false, - '192.168.1.128' => true, - '192.168.1.255' => true, - '192.168.2.0' => false, - )), - - array('192.168.1.10/24', array( - '192.168.0.255' => false, - '192.168.1.0' => true, - '192.168.1.1' => true, - '192.168.1.2' => true, - '192.168.1.3' => true, - '192.168.1.4' => true, - '192.168.1.7' => true, - '192.168.1.8' => true, - '192.168.1.15' => true, - '192.168.1.16' => true, - '192.168.1.31' => true, - '192.168.1.32' => true, - '192.168.1.63' => true, - '192.168.1.64' => true, - '192.168.1.127' => true, - '192.168.1.128' => true, - '192.168.1.255' => true, - '192.168.2.0' => false, - )), - - array('192.168.1.*', array( - '192.168.0.255' => false, - '192.168.1.0' => true, - '192.168.1.1' => true, - '192.168.1.2' => true, - '192.168.1.3' => true, - '192.168.1.4' => true, - '192.168.1.7' => true, - '192.168.1.8' => true, - '192.168.1.15' => true, - '192.168.1.16' => true, - '192.168.1.31' => true, - '192.168.1.32' => true, - '192.168.1.63' => true, - '192.168.1.64' => true, - '192.168.1.127' => true, - '192.168.1.128' => true, - '192.168.1.255' => true, - '192.168.2.0' => false, - )), - ); - } - - /** - * @group Core - * - * @dataProvider getIpsInRangeData - */ - public function testIsIpInRange($range, $test) - { - foreach ($test as $ip => $expected) { - // range as a string - $this->assertEquals($expected, IP::isIpInRange(IP::P2N($ip), array($range)), "$ip in $range"); - - // range as an array(low, high) - $aRange = IP::getIpsForRange($range); - $aRange[0] = IP::N2P($aRange[0]); - $aRange[1] = IP::N2P($aRange[1]); - $this->assertEquals($expected, IP::isIpInRange(IP::P2N($ip), array($aRange)), "$ip in $range"); - } - } - /** * Dataprovider for ip from header tests */ @@ -672,19 +190,4 @@ class IPTest extends PHPUnit_Framework_TestCase // with excluded Ips $this->assertEquals($expected, IP::getLastIpFromList($csv . ', 10.10.10.10', array('10.10.10.10'))); } - - /** - * @group Core - */ - public function testGetHostByAddr() - { - $hosts = array('localhost', 'localhost.localdomain', strtolower(@php_uname('n')), '127.0.0.1'); - $host = IP::getHostByAddr('127.0.0.1'); - $this->assertTrue(in_array(strtolower($host), $hosts), $host . ' -> localhost'); - - if (!SettingsServer::isWindows() || PHP_VERSION >= '5.3') { - $hosts = array('ip6-localhost', 'localhost', 'localhost.localdomain', strtolower(@php_uname('n')), '::1'); - $this->assertTrue(in_array(strtolower(IP::getHostByAddr('::1')), $hosts), '::1 -> ip6-localhost'); - } - } }