MediaWiki  master
IP.php
Go to the documentation of this file.
1 <?php
25 
26 // Some regex definition to "play" with IP address and IP address ranges
27 
28 // An IPv4 address is made of 4 bytes from x00 to xFF which is d0 to d255
29 define( 'RE_IP_BYTE', '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])' );
30 define( 'RE_IP_ADD', RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE );
31 // An IPv4 range is an IP address and a prefix (d1 to d32)
32 define( 'RE_IP_PREFIX', '(3[0-2]|[12]?\d)' );
33 define( 'RE_IP_RANGE', RE_IP_ADD . '\/' . RE_IP_PREFIX );
34 
35 // An IPv6 address is made up of 8 words (each x0000 to xFFFF).
36 // However, the "::" abbreviation can be used on consecutive x0000 words.
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',
40  '(?:' . // starts with "::" (including "::")
41  ':(?::|(?::' . RE_IPV6_WORD . '){1,7})' .
42  '|' . // ends with "::" (except "::")
43  RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){0,6}::' .
44  '|' . // contains one "::" in the middle (the ^ makes the test fail if none found)
45  RE_IPV6_WORD . '(?::((?(-1)|:))?' . RE_IPV6_WORD . '){1,6}(?(-2)|^)' .
46  '|' . // contains no "::"
47  RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){7}' .
48  ')'
49 );
50 // An IPv6 range is an IP address and a prefix (d1 to d128)
51 define( 'RE_IPV6_RANGE', RE_IPV6_ADD . '\/' . RE_IPV6_PREFIX );
52 // For IPv6 canonicalization (NOT for strict validation; these are quite lax!)
53 define( 'RE_IPV6_GAP', ':(?:0+:)*(?::(?:0+:)*)?' );
54 define( 'RE_IPV6_V4_PREFIX', '0*' . RE_IPV6_GAP . '(?:ffff:)?' );
55 
56 // This might be useful for regexps used elsewhere, matches any IPv4 or IPv6 address or network
57 define( 'IP_ADDRESS_STRING',
58  '(?:' .
59  RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?' . // IPv4
60  '|' .
61  RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?' . // IPv6
62  ')'
63 );
64 
69 class IP {
70 
79  public static function isIPAddress( $ip ) {
80  return (bool)preg_match( '/^' . IP_ADDRESS_STRING . '$/', $ip );
81  }
82 
90  public static function isIPv6( $ip ) {
91  return (bool)preg_match( '/^' . RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?$/', $ip );
92  }
93 
101  public static function isIPv4( $ip ) {
102  return (bool)preg_match( '/^' . RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?$/', $ip );
103  }
104 
113  public static function isValid( $ip ) {
114  return ( preg_match( '/^' . RE_IP_ADD . '$/', $ip )
115  || preg_match( '/^' . RE_IPV6_ADD . '$/', $ip ) );
116  }
117 
127  public static function isValidBlock( $ipRange ) {
128  return self::isValidRange( $ipRange );
129  }
130 
140  public static function isValidRange( $ipRange ) {
141  return ( preg_match( '/^' . RE_IPV6_RANGE . '$/', $ipRange )
142  || preg_match( '/^' . RE_IP_RANGE . '$/', $ipRange ) );
143  }
144 
154  public static function sanitizeIP( $ip ) {
155  $ip = trim( $ip );
156  if ( $ip === '' ) {
157  return null;
158  }
159  /* If not an IP, just return trimmed value, since sanitizeIP() is called
160  * in a number of contexts where usernames are supplied as input.
161  */
162  if ( !self::isIPAddress( $ip ) ) {
163  return $ip;
164  }
165  if ( self::isIPv4( $ip ) ) {
166  // Remove leading 0's from octet representation of IPv4 address
167  $ip = preg_replace( '!(?:^|(?<=\.))0+(?=[1-9]|0[./]|0$)!', '', $ip );
168  return $ip;
169  }
170  // Remove any whitespaces, convert to upper case
171  $ip = strtoupper( $ip );
172  // Expand zero abbreviations
173  $abbrevPos = strpos( $ip, '::' );
174  if ( $abbrevPos !== false ) {
175  // We know this is valid IPv6. Find the last index of the
176  // address before any CIDR number (e.g. "a:b:c::/24").
177  $CIDRStart = strpos( $ip, "/" );
178  $addressEnd = ( $CIDRStart !== false )
179  ? $CIDRStart - 1
180  : strlen( $ip ) - 1;
181  // If the '::' is at the beginning...
182  if ( $abbrevPos == 0 ) {
183  $repeat = '0:';
184  $extra = ( $ip == '::' ) ? '0' : ''; // for the address '::'
185  $pad = 9; // 7+2 (due to '::')
186  // If the '::' is at the end...
187  } elseif ( $abbrevPos == ( $addressEnd - 1 ) ) {
188  $repeat = ':0';
189  $extra = '';
190  $pad = 9; // 7+2 (due to '::')
191  // If the '::' is in the middle...
192  } else {
193  $repeat = ':0';
194  $extra = ':';
195  $pad = 8; // 6+2 (due to '::')
196  }
197  $ip = str_replace( '::',
198  str_repeat( $repeat, $pad - substr_count( $ip, ':' ) ) . $extra,
199  $ip
200  );
201  }
202  // Remove leading zeros from each bloc as needed
203  $ip = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip );
204 
205  return $ip;
206  }
207 
215  public static function prettifyIP( $ip ) {
216  $ip = self::sanitizeIP( $ip ); // normalize (removes '::')
217  if ( self::isIPv6( $ip ) ) {
218  // Split IP into an address and a CIDR
219  if ( strpos( $ip, '/' ) !== false ) {
220  list( $ip, $cidr ) = explode( '/', $ip, 2 );
221  } else {
222  list( $ip, $cidr ) = [ $ip, '' ];
223  }
224  // Get the largest slice of words with multiple zeros
225  $offset = 0;
226  $longest = $longestPos = false;
227  while ( preg_match(
228  '!(?:^|:)0(?::0)+(?:$|:)!', $ip, $m, PREG_OFFSET_CAPTURE, $offset
229  ) ) {
230  list( $match, $pos ) = $m[0]; // full match
231  if ( strlen( $match ) > strlen( $longest ) ) {
232  $longest = $match;
233  $longestPos = $pos;
234  }
235  $offset = ( $pos + strlen( $match ) ); // advance
236  }
237  if ( $longest !== false ) {
238  // Replace this portion of the string with the '::' abbreviation
239  $ip = substr_replace( $ip, '::', $longestPos, strlen( $longest ) );
240  }
241  // Add any CIDR back on
242  if ( $cidr !== '' ) {
243  $ip = "{$ip}/{$cidr}";
244  }
245  // Convert to lower case to make it more readable
246  $ip = strtolower( $ip );
247  }
248 
249  return $ip;
250  }
251 
268  public static function splitHostAndPort( $both ) {
269  if ( substr( $both, 0, 1 ) === '[' ) {
270  if ( preg_match( '/^\[(' . RE_IPV6_ADD . ')\](?::(?P<port>\d+))?$/', $both, $m ) ) {
271  if ( isset( $m['port'] ) ) {
272  return [ $m[1], intval( $m['port'] ) ];
273  } else {
274  return [ $m[1], false ];
275  }
276  } else {
277  // Square bracket found but no IPv6
278  return false;
279  }
280  }
281  $numColons = substr_count( $both, ':' );
282  if ( $numColons >= 2 ) {
283  // Is it a bare IPv6 address?
284  if ( preg_match( '/^' . RE_IPV6_ADD . '$/', $both ) ) {
285  return [ $both, false ];
286  } else {
287  // Not valid IPv6, but too many colons for anything else
288  return false;
289  }
290  }
291  if ( $numColons >= 1 ) {
292  // Host:port?
293  $bits = explode( ':', $both );
294  if ( preg_match( '/^\d+/', $bits[1] ) ) {
295  return [ $bits[0], intval( $bits[1] ) ];
296  } else {
297  // Not a valid port
298  return false;
299  }
300  }
301 
302  // Plain hostname
303  return [ $both, false ];
304  }
305 
317  public static function combineHostAndPort( $host, $port, $defaultPort = false ) {
318  if ( strpos( $host, ':' ) !== false ) {
319  $host = "[$host]";
320  }
321  if ( $defaultPort !== false && $port == $defaultPort ) {
322  return $host;
323  } else {
324  return "$host:$port";
325  }
326  }
327 
334  public static function formatHex( $hex ) {
335  if ( substr( $hex, 0, 3 ) == 'v6-' ) { // IPv6
336  return self::hexToOctet( substr( $hex, 3 ) );
337  } else { // IPv4
338  return self::hexToQuad( $hex );
339  }
340  }
341 
348  public static function hexToOctet( $ip_hex ) {
349  // Pad hex to 32 chars (128 bits)
350  $ip_hex = str_pad( strtoupper( $ip_hex ), 32, '0', STR_PAD_LEFT );
351  // Separate into 8 words
352  $ip_oct = substr( $ip_hex, 0, 4 );
353  for ( $n = 1; $n < 8; $n++ ) {
354  $ip_oct .= ':' . substr( $ip_hex, 4 * $n, 4 );
355  }
356  // NO leading zeroes
357  $ip_oct = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip_oct );
358 
359  return $ip_oct;
360  }
361 
368  public static function hexToQuad( $ip_hex ) {
369  // Pad hex to 8 chars (32 bits)
370  $ip_hex = str_pad( strtoupper( $ip_hex ), 8, '0', STR_PAD_LEFT );
371  // Separate into four quads
372  $s = '';
373  for ( $i = 0; $i < 4; $i++ ) {
374  if ( $s !== '' ) {
375  $s .= '.';
376  }
377  $s .= base_convert( substr( $ip_hex, $i * 2, 2 ), 16, 10 );
378  }
379 
380  return $s;
381  }
382 
390  public static function isPublic( $ip ) {
391  static $privateSet = null;
392  if ( !$privateSet ) {
393  $privateSet = new IPSet( [
394  '10.0.0.0/8', # RFC 1918 (private)
395  '172.16.0.0/12', # RFC 1918 (private)
396  '192.168.0.0/16', # RFC 1918 (private)
397  '0.0.0.0/8', # this network
398  '127.0.0.0/8', # loopback
399  'fc00::/7', # RFC 4193 (local)
400  '0:0:0:0:0:0:0:1', # loopback
401  '169.254.0.0/16', # link-local
402  'fe80::/10', # link-local
403  ] );
404  }
405  return !$privateSet->match( $ip );
406  }
407 
419  public static function toHex( $ip ) {
420  if ( self::isIPv6( $ip ) ) {
421  $n = 'v6-' . self::IPv6ToRawHex( $ip );
422  } elseif ( self::isIPv4( $ip ) ) {
423  // T62035/T97897: An IP with leading 0's fails in ip2long sometimes (e.g. *.08),
424  // also double/triple 0 needs to be changed to just a single 0 for ip2long.
425  $ip = self::sanitizeIP( $ip );
426  $n = ip2long( $ip );
427  if ( $n < 0 ) {
428  $n += 2 ** 32;
429  # On 32-bit platforms (and on Windows), 2^32 does not fit into an int,
430  # so $n becomes a float. We convert it to string instead.
431  if ( is_float( $n ) ) {
432  $n = (string)$n;
433  }
434  }
435  if ( $n !== false ) {
436  # Floating points can handle the conversion; faster than Wikimedia\base_convert()
437  $n = strtoupper( str_pad( base_convert( $n, 10, 16 ), 8, '0', STR_PAD_LEFT ) );
438  }
439  } else {
440  $n = false;
441  }
442 
443  return $n;
444  }
445 
452  private static function IPv6ToRawHex( $ip ) {
453  $ip = self::sanitizeIP( $ip );
454  if ( !$ip ) {
455  return false;
456  }
457  $r_ip = '';
458  foreach ( explode( ':', $ip ) as $v ) {
459  $r_ip .= str_pad( $v, 4, 0, STR_PAD_LEFT );
460  }
461 
462  return $r_ip;
463  }
464 
472  public static function parseCIDR( $range ) {
473  if ( self::isIPv6( $range ) ) {
474  return self::parseCIDR6( $range );
475  }
476  $parts = explode( '/', $range, 2 );
477  if ( count( $parts ) != 2 ) {
478  return [ false, false ];
479  }
480  list( $network, $bits ) = $parts;
481  $network = ip2long( $network );
482  if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 32 ) {
483  if ( $bits == 0 ) {
484  $network = 0;
485  } else {
486  $network &= ~( ( 1 << ( 32 - $bits ) ) - 1 );
487  }
488  # Convert to unsigned
489  if ( $network < 0 ) {
490  $network += 2 ** 32;
491  }
492  } else {
493  $network = false;
494  $bits = false;
495  }
496 
497  return [ $network, $bits ];
498  }
499 
515  public static function parseRange( $range ) {
516  // CIDR notation
517  if ( strpos( $range, '/' ) !== false ) {
518  if ( self::isIPv6( $range ) ) {
519  return self::parseRange6( $range );
520  }
521  list( $network, $bits ) = self::parseCIDR( $range );
522  if ( $network === false ) {
523  $start = $end = false;
524  } else {
525  $start = sprintf( '%08X', $network );
526  $end = sprintf( '%08X', $network + 2 ** ( 32 - $bits ) - 1 );
527  }
528  // Explicit range
529  } elseif ( strpos( $range, '-' ) !== false ) {
530  list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
531  if ( self::isIPv6( $start ) && self::isIPv6( $end ) ) {
532  return self::parseRange6( $range );
533  }
534  if ( self::isIPv4( $start ) && self::isIPv4( $end ) ) {
535  $start = self::toHex( $start );
536  $end = self::toHex( $end );
537  if ( $start > $end ) {
538  $start = $end = false;
539  }
540  } else {
541  $start = $end = false;
542  }
543  } else {
544  # Single IP
545  $start = $end = self::toHex( $range );
546  }
547  if ( $start === false || $end === false ) {
548  return [ false, false ];
549  } else {
550  return [ $start, $end ];
551  }
552  }
553 
562  private static function parseCIDR6( $range ) {
563  # Explode into <expanded IP,range>
564  $parts = explode( '/', self::sanitizeIP( $range ), 2 );
565  if ( count( $parts ) != 2 ) {
566  return [ false, false ];
567  }
568  list( $network, $bits ) = $parts;
569  $network = self::IPv6ToRawHex( $network );
570  if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 128 ) {
571  if ( $bits == 0 ) {
572  $network = "0";
573  } else {
574  # Native 32 bit functions WONT work here!!!
575  # Convert to a padded binary number
576  $network = Wikimedia\base_convert( $network, 16, 2, 128 );
577  # Truncate the last (128-$bits) bits and replace them with zeros
578  $network = str_pad( substr( $network, 0, $bits ), 128, 0, STR_PAD_RIGHT );
579  # Convert back to an integer
580  $network = Wikimedia\base_convert( $network, 2, 10 );
581  }
582  } else {
583  $network = false;
584  $bits = false;
585  }
586 
587  return [ $network, (int)$bits ];
588  }
589 
603  private static function parseRange6( $range ) {
604  # Expand any IPv6 IP
605  $range = self::sanitizeIP( $range );
606  // CIDR notation...
607  if ( strpos( $range, '/' ) !== false ) {
608  list( $network, $bits ) = self::parseCIDR6( $range );
609  if ( $network === false ) {
610  $start = $end = false;
611  } else {
612  $start = Wikimedia\base_convert( $network, 10, 16, 32, false );
613  # Turn network to binary (again)
614  $end = Wikimedia\base_convert( $network, 10, 2, 128 );
615  # Truncate the last (128-$bits) bits and replace them with ones
616  $end = str_pad( substr( $end, 0, $bits ), 128, 1, STR_PAD_RIGHT );
617  # Convert to hex
618  $end = Wikimedia\base_convert( $end, 2, 16, 32, false );
619  # see toHex() comment
620  $start = "v6-$start";
621  $end = "v6-$end";
622  }
623  // Explicit range notation...
624  } elseif ( strpos( $range, '-' ) !== false ) {
625  list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
626  $start = self::toHex( $start );
627  $end = self::toHex( $end );
628  if ( $start > $end ) {
629  $start = $end = false;
630  }
631  } else {
632  # Single IP
633  $start = $end = self::toHex( $range );
634  }
635  if ( $start === false || $end === false ) {
636  return [ false, false ];
637  } else {
638  return [ $start, $end ];
639  }
640  }
641 
652  public static function isInRange( $addr, $range ) {
653  $hexIP = self::toHex( $addr );
654  list( $start, $end ) = self::parseRange( $range );
655 
656  return ( strcmp( $hexIP, $start ) >= 0 &&
657  strcmp( $hexIP, $end ) <= 0 );
658  }
659 
670  public static function isInRanges( $ip, $ranges ) {
671  foreach ( $ranges as $range ) {
672  if ( self::isInRange( $ip, $range ) ) {
673  return true;
674  }
675  }
676  return false;
677  }
678 
689  public static function canonicalize( $addr ) {
690  // remove zone info (T37738)
691  $addr = preg_replace( '/\%.*/', '', $addr );
692 
693  if ( self::isValid( $addr ) ) {
694  return $addr;
695  }
696  // Turn mapped addresses from ::ce:ffff:1.2.3.4 to 1.2.3.4
697  if ( strpos( $addr, ':' ) !== false && strpos( $addr, '.' ) !== false ) {
698  $addr = substr( $addr, strrpos( $addr, ':' ) + 1 );
699  if ( self::isIPv4( $addr ) ) {
700  return $addr;
701  }
702  }
703  // IPv6 loopback address
704  $m = [];
705  if ( preg_match( '/^0*' . RE_IPV6_GAP . '1$/', $addr, $m ) ) {
706  return '127.0.0.1';
707  }
708  // IPv4-mapped and IPv4-compatible IPv6 addresses
709  if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . '(' . RE_IP_ADD . ')$/i', $addr, $m ) ) {
710  return $m[1];
711  }
712  if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . RE_IPV6_WORD .
713  ':' . RE_IPV6_WORD . '$/i', $addr, $m )
714  ) {
715  return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
716  }
717 
718  return null; // give up
719  }
720 
727  public static function sanitizeRange( $range ) {
728  list( /*...*/, $bits ) = self::parseCIDR( $range );
729  list( $start, /*...*/ ) = self::parseRange( $range );
730  $start = self::formatHex( $start );
731  if ( $bits === false ) {
732  return $start; // wasn't actually a range
733  }
734 
735  return "$start/$bits";
736  }
737 
744  public static function getSubnet( $ip ) {
745  $matches = [];
746  $subnet = false;
747  if ( self::isIPv6( $ip ) ) {
748  $parts = self::parseRange( "$ip/64" );
749  $subnet = $parts[0];
750  } elseif ( preg_match( '/^(\d+\.\d+\.\d+)\.\d+$/', $ip, $matches ) ) {
751  // IPv4
752  $subnet = $matches[1];
753  }
754  return $subnet;
755  }
756 }
static isValidRange( $ipRange)
Validate an IP range (valid address with a valid CIDR prefix).
Definition: IP.php:138
static isIPAddress( $ip)
Determine if a string is as valid IP address or network (CIDR prefix).
Definition: IP.php:77
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
Definition: deferred.txt:11
static toHex( $ip)
Return a zero-padded upper case hexadecimal representation of an IP address.
Definition: IP.php:417
static parseRange( $range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
Definition: IP.php:513
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
static parseRange6( $range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
Definition: IP.php:601
const RE_IPV6_PREFIX
Definition: IP.php:38
const RE_IPV6_GAP
Definition: IP.php:52
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
Definition: memcached.txt:16
static canonicalize( $addr)
Convert some unusual representations of IPv4 addresses to their canonical dotted quad representation...
Definition: IP.php:687
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
Definition: hooks.txt:175
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...
Definition: IP.php:315
static IPv6ToRawHex( $ip)
Given an IPv6 address in octet notation, returns a pure hex string.
Definition: IP.php:450
const RE_IP_PREFIX
Definition: IP.php:32
static isValidBlock( $ipRange)
Validate an IP range (valid address with a valid CIDR prefix).
Definition: IP.php:125
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.
Definition: IP.php:725
static getSubnet( $ip)
Returns the subnet of a given IP.
Definition: IP.php:742
const IP_ADDRESS_STRING
Definition: IP.php:56
static hexToQuad( $ip_hex)
Converts a hexadecimal number to an IPv4 address in quad-dotted notation.
Definition: IP.php:366
static sanitizeIP( $ip)
Convert an IP into a verbose, uppercase, normalized form.
Definition: IP.php:152
static isValid( $ip)
Validate an IP address.
Definition: IP.php:111
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.
Definition: IP.php:266
static isInRange( $addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
Definition: IP.php:650
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
Definition: distributors.txt:9
static hexToOctet( $ip_hex)
Converts a hexadecimal number to an IPv6 address in octet notation.
Definition: IP.php:346
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
Definition: injection.txt:35
static isIPv6( $ip)
Given a string, determine if it as valid IP in IPv6 only.
Definition: IP.php:88
const RE_IP_BYTE
Definition: IP.php:29
static prettifyIP( $ip)
Prettify an IP for display to end users.
Definition: IP.php:213
static isIPv4( $ip)
Given a string, determine if it as valid IP in IPv4 only.
Definition: IP.php:99
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
Definition: hooks.txt:3043
const RE_IP_RANGE
Definition: IP.php:33
static isInRanges( $ip, $ranges)
Determines if an IP address is a list of CIDR a.b.c.d/n ranges.
Definition: IP.php:668
static parseCIDR6( $range)
Convert a network specification in IPv6 CIDR notation to an integer network and a number of bits...
Definition: IP.php:560
const RE_IPV6_ADD
Definition: IP.php:39
static parseCIDR( $range)
Convert a network specification in CIDR notation to an integer network and a number of bits...
Definition: IP.php:470
static formatHex( $hex)
Convert an IPv4 or IPv6 hexadecimal representation back to readable format.
Definition: IP.php:332
const RE_IPV6_RANGE
Definition: IP.php:50
const RE_IPV6_V4_PREFIX
Definition: IP.php:53
static isPublic( $ip)
Determine if an IP address really is an IP address, and if it is public, i.e.
Definition: IP.php:388
$matches