29 define(
'RE_IP_BYTE',
'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])' );
32 define(
'RE_IP_PREFIX',
'(3[0-2]|[12]?\d)' );
37 define(
'RE_IPV6_WORD',
'([0-9A-Fa-f]{1,4})' );
38 define(
'RE_IPV6_PREFIX',
'(12[0-8]|1[01][0-9]|[1-9]?\d)' );
39 define(
'RE_IPV6_ADD',
53 define(
'RE_IPV6_GAP',
':(?:0+:)*(?::(?:0+:)*)?' );
54 define(
'RE_IPV6_V4_PREFIX',
'0*' .
RE_IPV6_GAP .
'(?:ffff:)?' );
57 define(
'IP_ADDRESS_STRING',
92 public static function isIPv6( $ip ) {
103 public static function isIPv4( $ip ) {
115 public static function isValid( $ip ) {
116 return ( preg_match(
'/^' .
RE_IP_ADD .
'$/', $ip )
130 || preg_match(
'/^' .
RE_IP_BLOCK .
'$/', $ipblock ) );
150 if ( !self::isIPAddress( $ip ) ) {
153 if ( self::isIPv4( $ip ) ) {
155 $ip = preg_replace(
'/(?:^|(?<=\.))0+(?=[1-9]|0\.|0$)/',
'', $ip );
159 $ip = strtoupper( $ip );
161 $abbrevPos = strpos( $ip,
'::' );
162 if ( $abbrevPos !==
false ) {
165 $CIDRStart = strpos( $ip,
"/" );
166 $addressEnd = ( $CIDRStart !==
false )
170 if ( $abbrevPos == 0 ) {
172 $extra = ( $ip ==
'::' ) ?
'0' :
'';
175 } elseif ( $abbrevPos == ( $addressEnd - 1 ) ) {
185 $ip = str_replace(
'::',
186 str_repeat( $repeat, $pad - substr_count( $ip,
':' ) ) . $extra,
191 $ip = preg_replace(
'/(^|:)0+(' .
RE_IPV6_WORD .
')/',
'$1$2', $ip );
204 $ip = self::sanitizeIP( $ip );
205 if ( self::isIPv6( $ip ) ) {
207 if ( strpos( $ip,
'/' ) !==
false ) {
208 list( $ip, $cidr ) = explode(
'/', $ip, 2 );
210 list( $ip, $cidr ) = [ $ip,
'' ];
214 $longest = $longestPos =
false;
216 '!(?:^|:)0(?::0)+(?:$|:)!', $ip, $m, PREG_OFFSET_CAPTURE, $offset
218 list( $match, $pos ) = $m[0];
219 if ( strlen( $match ) > strlen( $longest ) ) {
223 $offset = ( $pos + strlen( $match ) );
225 if ( $longest !==
false ) {
227 $ip = substr_replace( $ip,
'::', $longestPos, strlen( $longest ) );
230 if ( $cidr !==
'' ) {
231 $ip =
"{$ip}/{$cidr}";
234 $ip = strtolower( $ip );
257 if ( substr( $both, 0, 1 ) ===
'[' ) {
258 if ( preg_match(
'/^\[(' .
RE_IPV6_ADD .
')\](?::(?P<port>\d+))?$/', $both, $m ) ) {
259 if ( isset( $m[
'port'] ) ) {
260 return [ $m[1], intval( $m[
'port'] ) ];
262 return [ $m[1],
false ];
269 $numColons = substr_count( $both,
':' );
270 if ( $numColons >= 2 ) {
272 if ( preg_match(
'/^' .
RE_IPV6_ADD .
'$/', $both ) ) {
273 return [ $both,
false ];
279 if ( $numColons >= 1 ) {
281 $bits = explode(
':', $both );
282 if ( preg_match(
'/^\d+/', $bits[1] ) ) {
283 return [ $bits[0], intval( $bits[1] ) ];
291 return [ $both,
false ];
306 if ( strpos( $host,
':' ) !==
false ) {
309 if ( $defaultPort !==
false && $port == $defaultPort ) {
312 return "$host:$port";
322 public static function formatHex( $hex ) {
323 if ( substr( $hex, 0, 3 ) ==
'v6-' ) {
324 return self::hexToOctet( substr( $hex, 3 ) );
326 return self::hexToQuad( $hex );
336 public static function hexToOctet( $ip_hex ) {
338 $ip_hex = str_pad( strtoupper( $ip_hex ), 32,
'0', STR_PAD_LEFT );
340 $ip_oct = substr( $ip_hex, 0, 4 );
341 for ( $n = 1; $n < 8; $n++ ) {
342 $ip_oct .=
':' . substr( $ip_hex, 4 * $n, 4 );
345 $ip_oct = preg_replace(
'/(^|:)0+(' .
RE_IPV6_WORD .
')/',
'$1$2', $ip_oct );
356 public static function hexToQuad( $ip_hex ) {
358 $ip_hex = str_pad( strtoupper( $ip_hex ), 8,
'0', STR_PAD_LEFT );
361 for ( $i = 0; $i < 4; $i++ ) {
365 $s .= base_convert( substr( $ip_hex, $i * 2, 2 ), 16, 10 );
378 public static function isPublic( $ip ) {
379 static $privateSet = null;
380 if ( !$privateSet ) {
381 $privateSet =
new IPSet( [
382 '10.0.0.0/8', # RFC 1918 (
private)
383 '172.16.0.0/12', # RFC 1918 (
private)
384 '192.168.0.0/16', # RFC 1918 (
private)
386 '127.0.0.0/8', # loopback
387 'fc00::/7', # RFC 4193 (local)
388 '0:0:0:0:0:0:0:1', # loopback
389 '169.254.0.0/16', #
link-local
390 'fe80::/10', #
link-local
393 return !$privateSet->match( $ip );
407 public static function toHex( $ip ) {
408 if ( self::isIPv6( $ip ) ) {
409 $n =
'v6-' . self::IPv6ToRawHex( $ip );
410 } elseif ( self::isIPv4( $ip ) ) {
413 $ip = self::sanitizeIP( $ip );
417 # On 32-bit platforms (and on Windows), 2^32 does not fit into an int,
418 # so $n becomes a float. We convert it to string instead.
419 if ( is_float( $n ) ) {
423 if ( $n !==
false ) {
424 # Floating points can handle the conversion; faster than Wikimedia\base_convert()
425 $n = strtoupper( str_pad( base_convert( $n, 10, 16 ), 8,
'0', STR_PAD_LEFT ) );
441 $ip = self::sanitizeIP( $ip );
446 foreach ( explode(
':', $ip )
as $v ) {
447 $r_ip .= str_pad( $v, 4, 0, STR_PAD_LEFT );
460 public static function parseCIDR( $range ) {
461 if ( self::isIPv6( $range ) ) {
462 return self::parseCIDR6( $range );
464 $parts = explode(
'/', $range, 2 );
465 if ( count( $parts ) != 2 ) {
466 return [
false,
false ];
468 list( $network, $bits ) = $parts;
469 $network = ip2long( $network );
470 if ( $network !==
false && is_numeric( $bits ) && $bits >= 0 && $bits <= 32 ) {
474 $network &= ~( ( 1 << ( 32 - $bits ) ) - 1 );
476 # Convert to unsigned
477 if ( $network < 0 ) {
478 $network += pow( 2, 32 );
485 return [ $network, $bits ];
505 if ( strpos( $range,
'/' ) !==
false ) {
506 if ( self::isIPv6( $range ) ) {
507 return self::parseRange6( $range );
509 list( $network, $bits ) = self::parseCIDR( $range );
510 if ( $network ===
false ) {
511 $start = $end =
false;
513 $start = sprintf(
'%08X', $network );
514 $end = sprintf(
'%08X', $network + pow( 2, ( 32 - $bits ) ) - 1 );
517 } elseif ( strpos( $range,
'-' ) !==
false ) {
518 list( $start, $end ) = array_map(
'trim', explode(
'-', $range, 2 ) );
519 if ( self::isIPv6( $start ) && self::isIPv6( $end ) ) {
520 return self::parseRange6( $range );
522 if ( self::isIPv4( $start ) && self::isIPv4( $end ) ) {
523 $start = self::toHex( $start );
524 $end = self::toHex( $end );
525 if ( $start > $end ) {
526 $start = $end =
false;
529 $start = $end =
false;
533 $start = $end = self::toHex( $range );
535 if ( $start ===
false || $end ===
false ) {
536 return [
false,
false ];
538 return [ $start, $end ];
550 private static function parseCIDR6( $range ) {
551 # Explode into <expanded IP,range>
553 if ( count( $parts ) != 2 ) {
554 return [
false,
false ];
556 list( $network, $bits ) = $parts;
557 $network = self::IPv6ToRawHex( $network );
558 if ( $network !==
false && is_numeric( $bits ) && $bits >= 0 && $bits <= 128 ) {
562 # Native 32 bit functions WONT work here!!!
563 # Convert to a padded binary number
564 $network = Wikimedia\base_convert( $network, 16, 2, 128 );
565 # Truncate the last (128-$bits) bits and replace them with zeros
566 $network = str_pad( substr( $network, 0, $bits ), 128, 0, STR_PAD_RIGHT );
567 # Convert back to an integer
568 $network = Wikimedia\base_convert( $network, 2, 10 );
575 return [ $network, (int)$bits ];
595 if ( strpos( $range,
'/' ) !==
false ) {
596 list( $network, $bits ) = self::parseCIDR6( $range );
597 if ( $network ===
false ) {
598 $start = $end =
false;
600 $start = Wikimedia\base_convert( $network, 10, 16, 32,
false );
601 # Turn network to binary (again)
602 $end = Wikimedia\base_convert( $network, 10, 2, 128 );
603 # Truncate the last (128-$bits) bits and replace them with ones
604 $end = str_pad( substr( $end, 0, $bits ), 128, 1, STR_PAD_RIGHT );
606 $end = Wikimedia\base_convert( $end, 2, 16, 32,
false );
607 # see toHex() comment
608 $start =
"v6-$start";
612 } elseif ( strpos( $range,
'-' ) !==
false ) {
613 list( $start, $end ) = array_map(
'trim', explode(
'-', $range, 2 ) );
614 $start = self::toHex( $start );
615 $end = self::toHex( $end );
616 if ( $start > $end ) {
617 $start = $end =
false;
621 $start = $end = self::toHex( $range );
623 if ( $start ===
false || $end ===
false ) {
624 return [
false,
false ];
626 return [ $start, $end ];
640 public static function isInRange( $addr, $range ) {
641 $hexIP = self::toHex( $addr );
642 list( $start, $end ) = self::parseRange( $range );
644 return ( strcmp( $hexIP, $start ) >= 0 &&
645 strcmp( $hexIP, $end ) <= 0 );
658 public static function isInRanges( $ip, $ranges ) {
659 foreach ( $ranges
as $range ) {
660 if ( self::isInRange( $ip, $range ) ) {
679 $addr = preg_replace(
'/\%.*/',
'', $addr );
681 if ( self::isValid( $addr ) ) {
685 if ( strpos( $addr,
':' ) !==
false && strpos( $addr,
'.' ) !==
false ) {
686 $addr = substr( $addr, strrpos( $addr,
':' ) + 1 );
687 if ( self::isIPv4( $addr ) ) {
693 if ( preg_match(
'/^0*' .
RE_IPV6_GAP .
'1$/', $addr, $m ) ) {
703 return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
716 list( , $bits ) = self::parseCIDR( $range );
717 list( $start, ) = self::parseRange( $range );
718 $start = self::formatHex( $start );
719 if ( $bits ===
false ) {
723 return "$start/$bits";
732 public static function getSubnet( $ip ) {
738 } elseif ( preg_match(
'/^(\d+\.\d+\.\d+)\.\d+$/', $ip,
$matches ) ) {
static hexToOctet($ip_hex)
Converts a hexadecimal number to an IPv6 address in octet notation.
static isInRanges($ip, $ranges)
Determines if an IP address is a list of CIDR a.b.c.d/n ranges.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
static sanitizeIP($ip)
Convert an IP into a verbose, uppercase, normalized form.
static isInRange($addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
static parseCIDR6($range)
Convert a network specification in IPv6 CIDR notation to an integer network and a number of bits...
static sanitizeRange($range)
Gets rid of unneeded numbers in quad-dotted/octet IP strings For example, 127.111.113.151/24 -> 127.111.113.0/24.
processing should stop and the error should be shown to the user * false
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
MediaWiki has optional support for a high distributed memory object caching system For general information on but for a larger site with heavy like it should help lighten the load on the database servers by caching data and objects in Ubuntu and probably other Linux distributions If there s no package available for your you can compile it from epoll rt patch for Linux is current Memcached and libevent are under BSD style licenses The server should run on Linux and other Unix like systems you can run multiple servers on one machine or on multiple machines on a network
static IPv6ToRawHex($ip)
Given an IPv6 address in octet notation, returns a pure hex string.
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
static isIPv6($ip)
Given a string, determine if it as valid IP in IPv6 only.
static isIPAddress($ip)
Determine if a string is as valid IP address or network (CIDR prefix).
static parseRange6($range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
static isPublic($ip)
Determine if an IP address really is an IP address, and if it is public, i.e.
static combineHostAndPort($host, $port, $defaultPort=false)
Given a host name and a port, combine them into host/port string like you might find in a URL...
static isValid($ip)
Validate an IP address.
static isIPv4($ip)
Given a string, determine if it as valid IP in IPv4 only.
static hexToQuad($ip_hex)
Converts a hexadecimal number to an IPv4 address in quad-dotted notation.
static toHex($ip)
Return a zero-padded upper case hexadecimal representation of an IP address.
static formatHex($hex)
Convert an IPv4 or IPv6 hexadecimal representation back to readable format.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
static canonicalize($addr)
Convert some unusual representations of IPv4 addresses to their canonical dotted quad representation...
static splitHostAndPort($both)
Given a host/port string, like one might find in the host part of a URL per RFC 2732, split the hostname part and the port part and return an array with an element for each.
A collection of public static functions to play with IP address and IP blocks.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
static parseRange($range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
static parseCIDR($range)
Convert a network specification in CIDR notation to an integer network and a number of bits...
usually copyright or history_copyright This message must be in HTML not wikitext if the section is included from a template to be included in the link
static getSubnet($ip)
Returns the subnet of a given IP.
static isValidBlock($ipblock)
Validate an IP Block (valid address WITH a valid prefix).
static prettifyIP($ip)
Prettify an IP for display to end users.