MediaWiki  1.23.14
GlobalFunctions.php
Go to the documentation of this file.
1 <?php
23 if ( !defined( 'MEDIAWIKI' ) ) {
24  die( "This file is part of MediaWiki, it is not a valid entry point" );
25 }
26 
27 // Hide compatibility functions from Doxygen
29 
37 if ( !function_exists( 'iconv' ) ) {
42  function iconv( $from, $to, $string ) {
43  return Fallback::iconv( $from, $to, $string );
44  }
45 }
46 
47 if ( !function_exists( 'mb_substr' ) ) {
52  function mb_substr( $str, $start, $count = 'end' ) {
53  return Fallback::mb_substr( $str, $start, $count );
54  }
55 
60  function mb_substr_split_unicode( $str, $splitPos ) {
61  return Fallback::mb_substr_split_unicode( $str, $splitPos );
62  }
63 }
64 
65 if ( !function_exists( 'mb_strlen' ) ) {
70  function mb_strlen( $str, $enc = '' ) {
71  return Fallback::mb_strlen( $str, $enc );
72  }
73 }
74 
75 if ( !function_exists( 'mb_strpos' ) ) {
80  function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
81  return Fallback::mb_strpos( $haystack, $needle, $offset, $encoding );
82  }
83 }
84 
85 if ( !function_exists( 'mb_strrpos' ) ) {
90  function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
91  return Fallback::mb_strrpos( $haystack, $needle, $offset, $encoding );
92  }
93 }
94 
95 // gzdecode function only exists in PHP >= 5.4.0
96 // http://php.net/gzdecode
97 if ( !function_exists( 'gzdecode' ) ) {
102  function gzdecode( $data ) {
103  return gzinflate( substr( $data, 10, -8 ) );
104  }
105 }
106 
107 // hash_equals function only exists in PHP >= 5.6.0
108 if ( !function_exists( 'hash_equals' ) ) {
124  function hash_equals( $known_string, $user_string ) {
125  // Strict type checking as in PHP's native implementation
126  if ( !is_string( $known_string ) ) {
127  trigger_error( 'hash_equals(): Expected known_string to be a string, ' .
128  gettype( $known_string ) . ' given', E_USER_WARNING );
129 
130  return false;
131  }
132 
133  if ( !is_string( $user_string ) ) {
134  trigger_error( 'hash_equals(): Expected user_string to be a string, ' .
135  gettype( $user_string ) . ' given', E_USER_WARNING );
136 
137  return false;
138  }
139 
140  // Note that we do one thing PHP doesn't: try to avoid leaking information about
141  // relative lengths of $known_string and $user_string, and of multiple $known_strings.
142  // However, lengths may still inevitably leak through, for example, CPU cache misses.
143  $known_string_len = strlen( $known_string );
144  $user_string_len = strlen( $user_string );
145  $result = $known_string_len ^ $user_string_len;
146  for ( $i = 0; $i < $user_string_len; $i++ ) {
147  $result |= ord( $known_string[$i % $known_string_len] ) ^ ord( $user_string[$i] );
148  }
149 
150  return ( $result === 0 );
151  }
152 }
154 
161 function wfArrayDiff2( $a, $b ) {
162  return array_udiff( $a, $b, 'wfArrayDiff2_cmp' );
163 }
164 
170 function wfArrayDiff2_cmp( $a, $b ) {
171  if ( is_string( $a ) && is_string( $b ) ) {
172  return strcmp( $a, $b );
173  } elseif ( count( $a ) !== count( $b ) ) {
174  return count( $a ) < count( $b ) ? -1 : 1;
175  } else {
176  reset( $a );
177  reset( $b );
178  while ( ( list( , $valueA ) = each( $a ) ) && ( list( , $valueB ) = each( $b ) ) ) {
179  $cmp = strcmp( $valueA, $valueB );
180  if ( $cmp !== 0 ) {
181  return $cmp;
182  }
183  }
184  return 0;
185  }
186 }
187 
198 function wfArrayLookup( $a, $b ) {
199  wfDeprecated( __FUNCTION__, '1.22' );
200  return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) );
201 }
202 
212 function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
213  if ( is_null( $changed ) ) {
214  throw new MWException( 'GlobalFunctions::wfAppendToArrayIfNotDefault got null' );
215  }
216  if ( $default[$key] !== $value ) {
217  $changed[$key] = $value;
218  }
219 }
220 
231 function wfArrayMerge( $array1 /*...*/ ) {
232  wfDeprecated( __FUNCTION__, '1.22' );
233  $args = func_get_args();
234  $args = array_reverse( $args, true );
235  $out = array();
236  foreach ( $args as $arg ) {
237  $out += $arg;
238  }
239  return $out;
240 }
241 
261 function wfMergeErrorArrays( /*...*/ ) {
262  $args = func_get_args();
263  $out = array();
264  foreach ( $args as $errors ) {
265  foreach ( $errors as $params ) {
266  # @todo FIXME: Sometimes get nested arrays for $params,
267  # which leads to E_NOTICEs
268  $spec = implode( "\t", $params );
269  $out[$spec] = $params;
270  }
271  }
272  return array_values( $out );
273 }
274 
283 function wfArrayInsertAfter( array $array, array $insert, $after ) {
284  // Find the offset of the element to insert after.
285  $keys = array_keys( $array );
286  $offsetByKey = array_flip( $keys );
287 
288  $offset = $offsetByKey[$after];
289 
290  // Insert at the specified offset
291  $before = array_slice( $array, 0, $offset + 1, true );
292  $after = array_slice( $array, $offset + 1, count( $array ) - $offset, true );
293 
294  $output = $before + $insert + $after;
295 
296  return $output;
297 }
298 
306 function wfObjectToArray( $objOrArray, $recursive = true ) {
307  $array = array();
308  if ( is_object( $objOrArray ) ) {
309  $objOrArray = get_object_vars( $objOrArray );
310  }
311  foreach ( $objOrArray as $key => $value ) {
312  if ( $recursive && ( is_object( $value ) || is_array( $value ) ) ) {
314  }
315 
316  $array[$key] = $value;
317  }
318 
319  return $array;
320 }
321 
329 function wfRandom() {
330  # The maximum random value is "only" 2^31-1, so get two random
331  # values to reduce the chance of dupes
332  $max = mt_getrandmax() + 1;
333  $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12, '.', '' );
334 
335  return $rand;
336 }
337 
348 function wfRandomString( $length = 32 ) {
349  $str = '';
350  for ( $n = 0; $n < $length; $n += 7 ) {
351  $str .= sprintf( '%07x', mt_rand() & 0xfffffff );
352  }
353  return substr( $str, 0, $length );
354 }
355 
378 function wfUrlencode( $s ) {
379  static $needle;
380 
381  if ( is_null( $s ) ) {
382  $needle = null;
383  return '';
384  }
385 
386  if ( is_null( $needle ) ) {
387  $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
388  if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
389  ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
390  ) {
391  $needle[] = '%3A';
392  }
393  }
394 
395  $s = urlencode( $s );
396  $s = str_ireplace(
397  $needle,
398  array( ';', '@', '$', '!', '*', '(', ')', ',', '/', ':' ),
399  $s
400  );
401 
402  return $s;
403 }
404 
415 function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
416  if ( !is_null( $array2 ) ) {
417  $array1 = $array1 + $array2;
418  }
419 
420  $cgi = '';
421  foreach ( $array1 as $key => $value ) {
422  if ( !is_null( $value ) && $value !== false ) {
423  if ( $cgi != '' ) {
424  $cgi .= '&';
425  }
426  if ( $prefix !== '' ) {
427  $key = $prefix . "[$key]";
428  }
429  if ( is_array( $value ) ) {
430  $firstTime = true;
431  foreach ( $value as $k => $v ) {
432  $cgi .= $firstTime ? '' : '&';
433  if ( is_array( $v ) ) {
434  $cgi .= wfArrayToCgi( $v, null, $key . "[$k]" );
435  } else {
436  $cgi .= urlencode( $key . "[$k]" ) . '=' . urlencode( $v );
437  }
438  $firstTime = false;
439  }
440  } else {
441  if ( is_object( $value ) ) {
442  $value = $value->__toString();
443  }
444  $cgi .= urlencode( $key ) . '=' . urlencode( $value );
445  }
446  }
447  }
448  return $cgi;
449 }
450 
460 function wfCgiToArray( $query ) {
461  if ( isset( $query[0] ) && $query[0] == '?' ) {
462  $query = substr( $query, 1 );
463  }
464  $bits = explode( '&', $query );
465  $ret = array();
466  foreach ( $bits as $bit ) {
467  if ( $bit === '' ) {
468  continue;
469  }
470  if ( strpos( $bit, '=' ) === false ) {
471  // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does)
472  $key = $bit;
473  $value = '';
474  } else {
475  list( $key, $value ) = explode( '=', $bit );
476  }
477  $key = urldecode( $key );
478  $value = urldecode( $value );
479  if ( strpos( $key, '[' ) !== false ) {
480  $keys = array_reverse( explode( '[', $key ) );
481  $key = array_pop( $keys );
482  $temp = $value;
483  foreach ( $keys as $k ) {
484  $k = substr( $k, 0, -1 );
485  $temp = array( $k => $temp );
486  }
487  if ( isset( $ret[$key] ) ) {
488  $ret[$key] = array_merge( $ret[$key], $temp );
489  } else {
490  $ret[$key] = $temp;
491  }
492  } else {
493  $ret[$key] = $value;
494  }
495  }
496  return $ret;
497 }
498 
507 function wfAppendQuery( $url, $query ) {
508  if ( is_array( $query ) ) {
510  }
511  if ( $query != '' ) {
512  if ( false === strpos( $url, '?' ) ) {
513  $url .= '?';
514  } else {
515  $url .= '&';
516  }
517  $url .= $query;
518  }
519  return $url;
520 }
521 
545 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
546  global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest;
547  if ( $defaultProto === PROTO_CANONICAL ) {
548  $serverUrl = $wgCanonicalServer;
549  } elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
550  // Make $wgInternalServer fall back to $wgServer if not set
551  $serverUrl = $wgInternalServer;
552  } else {
553  $serverUrl = $wgServer;
554  if ( $defaultProto === PROTO_CURRENT ) {
555  $defaultProto = $wgRequest->getProtocol() . '://';
556  }
557  }
558 
559  // Analyze $serverUrl to obtain its protocol
560  $bits = wfParseUrl( $serverUrl );
561  $serverHasProto = $bits && $bits['scheme'] != '';
562 
563  if ( $defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL ) {
564  if ( $serverHasProto ) {
565  $defaultProto = $bits['scheme'] . '://';
566  } else {
567  // $wgCanonicalServer or $wgInternalServer doesn't have a protocol.
568  // This really isn't supposed to happen. Fall back to HTTP in this
569  // ridiculous case.
570  $defaultProto = PROTO_HTTP;
571  }
572  }
573 
574  $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 );
575 
576  if ( substr( $url, 0, 2 ) == '//' ) {
577  $url = $defaultProtoWithoutSlashes . $url;
578  } elseif ( substr( $url, 0, 1 ) == '/' ) {
579  // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
580  // otherwise leave it alone.
581  $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url;
582  }
583 
584  $bits = wfParseUrl( $url );
585  if ( $bits && isset( $bits['path'] ) ) {
586  $bits['path'] = wfRemoveDotSegments( $bits['path'] );
587  return wfAssembleUrl( $bits );
588  } elseif ( $bits ) {
589  # No path to expand
590  return $url;
591  } elseif ( substr( $url, 0, 1 ) != '/' ) {
592  # URL is a relative path
593  return wfRemoveDotSegments( $url );
594  }
595 
596  # Expanded URL is not valid.
597  return false;
598 }
599 
613 function wfAssembleUrl( $urlParts ) {
614  $result = '';
615 
616  if ( isset( $urlParts['delimiter'] ) ) {
617  if ( isset( $urlParts['scheme'] ) ) {
618  $result .= $urlParts['scheme'];
619  }
620 
621  $result .= $urlParts['delimiter'];
622  }
623 
624  if ( isset( $urlParts['host'] ) ) {
625  if ( isset( $urlParts['user'] ) ) {
626  $result .= $urlParts['user'];
627  if ( isset( $urlParts['pass'] ) ) {
628  $result .= ':' . $urlParts['pass'];
629  }
630  $result .= '@';
631  }
632 
633  $result .= $urlParts['host'];
634 
635  if ( isset( $urlParts['port'] ) ) {
636  $result .= ':' . $urlParts['port'];
637  }
638  }
639 
640  if ( isset( $urlParts['path'] ) ) {
641  $result .= $urlParts['path'];
642  }
643 
644  if ( isset( $urlParts['query'] ) ) {
645  $result .= '?' . $urlParts['query'];
646  }
647 
648  if ( isset( $urlParts['fragment'] ) ) {
649  $result .= '#' . $urlParts['fragment'];
650  }
651 
652  return $result;
653 }
654 
665 function wfRemoveDotSegments( $urlPath ) {
666  $output = '';
667  $inputOffset = 0;
668  $inputLength = strlen( $urlPath );
669 
670  while ( $inputOffset < $inputLength ) {
671  $prefixLengthOne = substr( $urlPath, $inputOffset, 1 );
672  $prefixLengthTwo = substr( $urlPath, $inputOffset, 2 );
673  $prefixLengthThree = substr( $urlPath, $inputOffset, 3 );
674  $prefixLengthFour = substr( $urlPath, $inputOffset, 4 );
675  $trimOutput = false;
676 
677  if ( $prefixLengthTwo == './' ) {
678  # Step A, remove leading "./"
679  $inputOffset += 2;
680  } elseif ( $prefixLengthThree == '../' ) {
681  # Step A, remove leading "../"
682  $inputOffset += 3;
683  } elseif ( ( $prefixLengthTwo == '/.' ) && ( $inputOffset + 2 == $inputLength ) ) {
684  # Step B, replace leading "/.$" with "/"
685  $inputOffset += 1;
686  $urlPath[$inputOffset] = '/';
687  } elseif ( $prefixLengthThree == '/./' ) {
688  # Step B, replace leading "/./" with "/"
689  $inputOffset += 2;
690  } elseif ( $prefixLengthThree == '/..' && ( $inputOffset + 3 == $inputLength ) ) {
691  # Step C, replace leading "/..$" with "/" and
692  # remove last path component in output
693  $inputOffset += 2;
694  $urlPath[$inputOffset] = '/';
695  $trimOutput = true;
696  } elseif ( $prefixLengthFour == '/../' ) {
697  # Step C, replace leading "/../" with "/" and
698  # remove last path component in output
699  $inputOffset += 3;
700  $trimOutput = true;
701  } elseif ( ( $prefixLengthOne == '.' ) && ( $inputOffset + 1 == $inputLength ) ) {
702  # Step D, remove "^.$"
703  $inputOffset += 1;
704  } elseif ( ( $prefixLengthTwo == '..' ) && ( $inputOffset + 2 == $inputLength ) ) {
705  # Step D, remove "^..$"
706  $inputOffset += 2;
707  } else {
708  # Step E, move leading path segment to output
709  if ( $prefixLengthOne == '/' ) {
710  $slashPos = strpos( $urlPath, '/', $inputOffset + 1 );
711  } else {
712  $slashPos = strpos( $urlPath, '/', $inputOffset );
713  }
714  if ( $slashPos === false ) {
715  $output .= substr( $urlPath, $inputOffset );
716  $inputOffset = $inputLength;
717  } else {
718  $output .= substr( $urlPath, $inputOffset, $slashPos - $inputOffset );
719  $inputOffset += $slashPos - $inputOffset;
720  }
721  }
722 
723  if ( $trimOutput ) {
724  $slashPos = strrpos( $output, '/' );
725  if ( $slashPos === false ) {
726  $output = '';
727  } else {
728  $output = substr( $output, 0, $slashPos );
729  }
730  }
731  }
732 
733  return $output;
734 }
735 
743 function wfUrlProtocols( $includeProtocolRelative = true ) {
744  global $wgUrlProtocols;
745 
746  // Cache return values separately based on $includeProtocolRelative
747  static $withProtRel = null, $withoutProtRel = null;
748  $cachedValue = $includeProtocolRelative ? $withProtRel : $withoutProtRel;
749  if ( !is_null( $cachedValue ) ) {
750  return $cachedValue;
751  }
752 
753  // Support old-style $wgUrlProtocols strings, for backwards compatibility
754  // with LocalSettings files from 1.5
755  if ( is_array( $wgUrlProtocols ) ) {
756  $protocols = array();
757  foreach ( $wgUrlProtocols as $protocol ) {
758  // Filter out '//' if !$includeProtocolRelative
759  if ( $includeProtocolRelative || $protocol !== '//' ) {
760  $protocols[] = preg_quote( $protocol, '/' );
761  }
762  }
763 
764  $retval = implode( '|', $protocols );
765  } else {
766  // Ignore $includeProtocolRelative in this case
767  // This case exists for pre-1.6 compatibility, and we can safely assume
768  // that '//' won't appear in a pre-1.6 config because protocol-relative
769  // URLs weren't supported until 1.18
770  $retval = $wgUrlProtocols;
771  }
772 
773  // Cache return value
774  if ( $includeProtocolRelative ) {
775  $withProtRel = $retval;
776  } else {
777  $withoutProtRel = $retval;
778  }
779  return $retval;
780 }
781 
788 function wfUrlProtocolsWithoutProtRel() {
789  return wfUrlProtocols( false );
790 }
791 
803 function wfParseUrl( $url ) {
804  global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
805 
806  // Protocol-relative URLs are handled really badly by parse_url(). It's so
807  // bad that the easiest way to handle them is to just prepend 'http:' and
808  // strip the protocol out later.
809  $wasRelative = substr( $url, 0, 2 ) == '//';
810  if ( $wasRelative ) {
811  $url = "http:$url";
812  }
814  $bits = parse_url( $url );
816  // parse_url() returns an array without scheme for some invalid URLs, e.g.
817  // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
818  if ( !$bits || !isset( $bits['scheme'] ) ) {
819  return false;
820  }
821 
822  // parse_url() incorrectly handles schemes case-sensitively. Convert it to lowercase.
823  $bits['scheme'] = strtolower( $bits['scheme'] );
824 
825  // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
826  if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
827  $bits['delimiter'] = '://';
828  } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
829  $bits['delimiter'] = ':';
830  // parse_url detects for news: and mailto: the host part of an url as path
831  // We have to correct this wrong detection
832  if ( isset( $bits['path'] ) ) {
833  $bits['host'] = $bits['path'];
834  $bits['path'] = '';
835  }
836  } else {
837  return false;
838  }
839 
840  /* Provide an empty host for eg. file:/// urls (see bug 28627) */
841  if ( !isset( $bits['host'] ) ) {
842  $bits['host'] = '';
843 
844  // bug 45069
845  if ( isset( $bits['path'] ) ) {
846  /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
847  if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
848  $bits['path'] = '/' . $bits['path'];
849  }
850  } else {
851  $bits['path'] = '';
852  }
853  }
854 
855  // If the URL was protocol-relative, fix scheme and delimiter
856  if ( $wasRelative ) {
857  $bits['scheme'] = '';
858  $bits['delimiter'] = '//';
859  }
860  return $bits;
861 }
862 
873 function wfExpandIRI( $url ) {
874  return preg_replace_callback(
875  '/((?:%[89A-F][0-9A-F])+)/i',
876  'wfExpandIRI_callback',
877  wfExpandUrl( $url )
878  );
879 }
880 
886 function wfExpandIRI_callback( $matches ) {
887  return urldecode( $matches[1] );
888 }
889 
896 function wfMakeUrlIndexes( $url ) {
897  $bits = wfParseUrl( $url );
898 
899  // Reverse the labels in the hostname, convert to lower case
900  // For emails reverse domainpart only
901  if ( $bits['scheme'] == 'mailto' ) {
902  $mailparts = explode( '@', $bits['host'], 2 );
903  if ( count( $mailparts ) === 2 ) {
904  $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) );
905  } else {
906  // No domain specified, don't mangle it
907  $domainpart = '';
908  }
909  $reversedHost = $domainpart . '@' . $mailparts[0];
910  } else {
911  $reversedHost = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) );
912  }
913  // Add an extra dot to the end
914  // Why? Is it in wrong place in mailto links?
915  if ( substr( $reversedHost, -1, 1 ) !== '.' ) {
916  $reversedHost .= '.';
917  }
918  // Reconstruct the pseudo-URL
919  $prot = $bits['scheme'];
920  $index = $prot . $bits['delimiter'] . $reversedHost;
921  // Leave out user and password. Add the port, path, query and fragment
922  if ( isset( $bits['port'] ) ) {
923  $index .= ':' . $bits['port'];
924  }
925  if ( isset( $bits['path'] ) ) {
926  $index .= $bits['path'];
927  } else {
928  $index .= '/';
929  }
930  if ( isset( $bits['query'] ) ) {
931  $index .= '?' . $bits['query'];
932  }
933  if ( isset( $bits['fragment'] ) ) {
934  $index .= '#' . $bits['fragment'];
935  }
936 
937  if ( $prot == '' ) {
938  return array( "http:$index", "https:$index" );
939  } else {
940  return array( $index );
941  }
942 }
943 
950 function wfMatchesDomainList( $url, $domains ) {
951  $bits = wfParseUrl( $url );
952  if ( is_array( $bits ) && isset( $bits['host'] ) ) {
953  $host = '.' . $bits['host'];
954  foreach ( (array)$domains as $domain ) {
955  $domain = '.' . $domain;
956  if ( substr( $host, -strlen( $domain ) ) === $domain ) {
957  return true;
958  }
959  }
960  }
961  return false;
962 }
963 
981 function wfDebug( $text, $dest = 'all' ) {
982  global $wgDebugLogFile, $wgDebugRawPage, $wgDebugLogPrefix;
983 
984  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
985  return;
986  }
987 
988  // Turn $dest into a string if it's a boolean (for b/c)
989  if ( $dest === true ) {
990  $dest = 'all';
991  } elseif ( $dest === false ) {
992  $dest = 'log';
993  }
994 
995  $timer = wfDebugTimer();
996  if ( $timer !== '' ) {
997  $text = preg_replace( '/[^\n]/', $timer . '\0', $text, 1 );
998  }
999 
1000  if ( $dest === 'all' ) {
1001  MWDebug::debugMsg( $text );
1002  }
1003 
1004  if ( $wgDebugLogFile != '' ) {
1005  # Strip unprintables; they can switch terminal modes when binary data
1006  # gets dumped, which is pretty annoying.
1007  $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
1008  $text = $wgDebugLogPrefix . $text;
1009  wfErrorLog( $text, $wgDebugLogFile );
1010  }
1011 }
1012 
1017 function wfIsDebugRawPage() {
1018  static $cache;
1019  if ( $cache !== null ) {
1020  return $cache;
1021  }
1022  # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
1023  if ( ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' )
1024  || (
1025  isset( $_SERVER['SCRIPT_NAME'] )
1026  && substr( $_SERVER['SCRIPT_NAME'], -8 ) == 'load.php'
1027  )
1028  ) {
1029  $cache = true;
1030  } else {
1031  $cache = false;
1032  }
1033  return $cache;
1034 }
1035 
1041 function wfDebugTimer() {
1042  global $wgDebugTimestamps, $wgRequestTime;
1043 
1044  if ( !$wgDebugTimestamps ) {
1045  return '';
1046  }
1047 
1048  $prefix = sprintf( "%6.4f", microtime( true ) - $wgRequestTime );
1049  $mem = sprintf( "%5.1fM", ( memory_get_usage( true ) / ( 1024 * 1024 ) ) );
1050  return "$prefix $mem ";
1051 }
1052 
1058 function wfDebugMem( $exact = false ) {
1059  $mem = memory_get_usage();
1060  if ( !$exact ) {
1061  $mem = floor( $mem / 1024 ) . ' kilobytes';
1062  } else {
1063  $mem .= ' bytes';
1064  }
1065  wfDebug( "Memory usage: $mem\n" );
1066 }
1067 
1088 function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
1089  global $wgDebugLogGroups;
1090 
1091  $text = trim( $text ) . "\n";
1092 
1093  // Turn $dest into a string if it's a boolean (for b/c)
1094  if ( $dest === true ) {
1095  $dest = 'all';
1096  } elseif ( $dest === false ) {
1097  $dest = 'private';
1098  }
1099 
1100  if ( !isset( $wgDebugLogGroups[$logGroup] ) ) {
1101  if ( $dest !== 'private' ) {
1102  wfDebug( "[$logGroup] $text", $dest );
1103  }
1104  return;
1105  }
1106 
1107  if ( $dest === 'all' ) {
1108  MWDebug::debugMsg( "[$logGroup] $text" );
1109  }
1110 
1111  $logConfig = $wgDebugLogGroups[$logGroup];
1112  if ( $logConfig === false ) {
1113  return;
1114  }
1115  if ( is_array( $logConfig ) ) {
1116  if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
1117  return;
1118  }
1119  $destination = $logConfig['destination'];
1120  } else {
1121  $destination = strval( $logConfig );
1122  }
1123 
1124  $time = wfTimestamp( TS_DB );
1125  $wiki = wfWikiID();
1126  $host = wfHostname();
1127  wfErrorLog( "$time $host $wiki: $text", $destination );
1128 }
1129 
1135 function wfLogDBError( $text ) {
1136  global $wgDBerrorLog, $wgDBerrorLogTZ;
1137  static $logDBErrorTimeZoneObject = null;
1138 
1139  if ( $wgDBerrorLog ) {
1140  $host = wfHostname();
1141  $wiki = wfWikiID();
1142 
1143  if ( $wgDBerrorLogTZ && !$logDBErrorTimeZoneObject ) {
1144  $logDBErrorTimeZoneObject = new DateTimeZone( $wgDBerrorLogTZ );
1145  }
1146 
1147  // Workaround for https://bugs.php.net/bug.php?id=52063
1148  // Can be removed when min PHP > 5.3.2
1149  if ( $logDBErrorTimeZoneObject === null ) {
1150  $d = date_create( "now" );
1151  } else {
1152  $d = date_create( "now", $logDBErrorTimeZoneObject );
1153  }
1154 
1155  $date = $d->format( 'D M j G:i:s T Y' );
1156 
1157  $text = "$date\t$host\t$wiki\t" . trim( $text ) . "\n";
1158  wfErrorLog( $text, $wgDBerrorLog );
1159  }
1160 }
1161 
1175 function wfDeprecated( $function, $version = false, $component = false, $callerOffset = 2 ) {
1176  MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 );
1177 }
1178 
1189 function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
1190  MWDebug::warning( $msg, $callerOffset + 1, $level, 'auto' );
1191 }
1192 
1202 function wfLogWarning( $msg, $callerOffset = 1, $level = E_USER_WARNING ) {
1203  MWDebug::warning( $msg, $callerOffset + 1, $level, 'production' );
1204 }
1205 
1216 function wfErrorLog( $text, $file ) {
1217  if ( substr( $file, 0, 4 ) == 'udp:' ) {
1218  # Needs the sockets extension
1219  if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
1220  // IPv6 bracketed host
1221  $host = $m[2];
1222  $port = intval( $m[3] );
1223  $prefix = isset( $m[4] ) ? $m[4] : false;
1224  $domain = AF_INET6;
1225  } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
1226  $host = $m[2];
1227  if ( !IP::isIPv4( $host ) ) {
1228  $host = gethostbyname( $host );
1229  }
1230  $port = intval( $m[3] );
1231  $prefix = isset( $m[4] ) ? $m[4] : false;
1232  $domain = AF_INET;
1233  } else {
1234  throw new MWException( __METHOD__ . ': Invalid UDP specification' );
1235  }
1236 
1237  // Clean it up for the multiplexer
1238  if ( strval( $prefix ) !== '' ) {
1239  $text = preg_replace( '/^/m', $prefix . ' ', $text );
1240 
1241  // Limit to 64KB
1242  if ( strlen( $text ) > 65506 ) {
1243  $text = substr( $text, 0, 65506 );
1244  }
1245 
1246  if ( substr( $text, -1 ) != "\n" ) {
1247  $text .= "\n";
1248  }
1249  } elseif ( strlen( $text ) > 65507 ) {
1250  $text = substr( $text, 0, 65507 );
1251  }
1252 
1253  $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
1254  if ( !$sock ) {
1255  return;
1256  }
1257 
1258  socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
1259  socket_close( $sock );
1260  } else {
1262  $exists = file_exists( $file );
1263  $size = $exists ? filesize( $file ) : false;
1264  if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
1265  file_put_contents( $file, $text, FILE_APPEND );
1266  }
1268  }
1269 }
1270 
1274 function wfLogProfilingData() {
1275  global $wgRequestTime, $wgDebugLogFile, $wgDebugLogGroups, $wgDebugRawPage;
1276  global $wgProfileLimit, $wgUser, $wgRequest;
1277 
1278  StatCounter::singleton()->flush();
1279 
1280  $profiler = Profiler::instance();
1281 
1282  # Profiling must actually be enabled...
1283  if ( $profiler->isStub() ) {
1284  return;
1285  }
1286 
1287  // Get total page request time and only show pages that longer than
1288  // $wgProfileLimit time (default is 0)
1289  $elapsed = microtime( true ) - $wgRequestTime;
1290  if ( $elapsed <= $wgProfileLimit ) {
1291  return;
1292  }
1293 
1294  $profiler->logData();
1295 
1296  // Check whether this should be logged in the debug file.
1297  if ( isset( $wgDebugLogGroups['profileoutput'] )
1298  && $wgDebugLogGroups['profileoutput'] === false
1299  ) {
1300  // Explicitely disabled
1301  return;
1302  }
1303  if ( !isset( $wgDebugLogGroups['profileoutput'] ) && $wgDebugLogFile == '' ) {
1304  // Logging not enabled; no point going further
1305  return;
1306  }
1307  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
1308  return;
1309  }
1310 
1311  $forward = '';
1312  if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
1313  $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
1314  }
1315  if ( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
1316  $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP'];
1317  }
1318  if ( !empty( $_SERVER['HTTP_FROM'] ) ) {
1319  $forward .= ' from ' . $_SERVER['HTTP_FROM'];
1320  }
1321  if ( $forward ) {
1322  $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
1323  }
1324  // Don't load $wgUser at this late stage just for statistics purposes
1325  // @todo FIXME: We can detect some anons even if it is not loaded. See User::getId()
1326  if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
1327  $forward .= ' anon';
1328  }
1329 
1330  // Command line script uses a FauxRequest object which does not have
1331  // any knowledge about an URL and throw an exception instead.
1332  try {
1333  $requestUrl = $wgRequest->getRequestURL();
1334  } catch ( MWException $e ) {
1335  $requestUrl = 'n/a';
1336  }
1337 
1338  $log = sprintf( "%s\t%04.3f\t%s\n",
1339  gmdate( 'YmdHis' ), $elapsed,
1340  urldecode( $requestUrl . $forward ) );
1341 
1342  wfDebugLog( 'profileoutput', $log . $profiler->getOutput() );
1343 }
1344 
1352 function wfIncrStats( $key, $count = 1 ) {
1353  StatCounter::singleton()->incr( $key, $count );
1354 }
1355 
1361 function wfReadOnly() {
1362  return wfReadOnlyReason() !== false;
1363 }
1364 
1370 function wfReadOnlyReason() {
1371  global $wgReadOnly, $wgReadOnlyFile;
1372 
1373  if ( $wgReadOnly === null ) {
1374  // Set $wgReadOnly for faster access next time
1375  if ( is_file( $wgReadOnlyFile ) && filesize( $wgReadOnlyFile ) > 0 ) {
1376  $wgReadOnly = file_get_contents( $wgReadOnlyFile );
1377  } else {
1378  $wgReadOnly = false;
1379  }
1380  }
1381 
1382  return $wgReadOnly;
1383 }
1384 
1400 function wfGetLangObj( $langcode = false ) {
1401  # Identify which language to get or create a language object for.
1402  # Using is_object here due to Stub objects.
1403  if ( is_object( $langcode ) ) {
1404  # Great, we already have the object (hopefully)!
1405  return $langcode;
1406  }
1407 
1408  global $wgContLang, $wgLanguageCode;
1409  if ( $langcode === true || $langcode === $wgLanguageCode ) {
1410  # $langcode is the language code of the wikis content language object.
1411  # or it is a boolean and value is true
1412  return $wgContLang;
1413  }
1414 
1415  global $wgLang;
1416  if ( $langcode === false || $langcode === $wgLang->getCode() ) {
1417  # $langcode is the language code of user language object.
1418  # or it was a boolean and value is false
1419  return $wgLang;
1420  }
1421 
1422  $validCodes = array_keys( Language::fetchLanguageNames() );
1423  if ( in_array( $langcode, $validCodes ) ) {
1424  # $langcode corresponds to a valid language.
1425  return Language::factory( $langcode );
1426  }
1427 
1428  # $langcode is a string, but not a valid language code; use content language.
1429  wfDebug( "Invalid language code passed to wfGetLangObj, falling back to content language.\n" );
1430  return $wgContLang;
1431 }
1432 
1449 function wfMessage( $key /*...*/ ) {
1450  $params = func_get_args();
1451  array_shift( $params );
1452  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
1453  $params = $params[0];
1454  }
1455  return new Message( $key, $params );
1456 }
1457 
1470 function wfMessageFallback( /*...*/ ) {
1471  $args = func_get_args();
1472  return call_user_func_array( 'Message::newFallbackSequence', $args );
1473 }
1474 
1494 function wfMsg( $key ) {
1495  wfDeprecated( __METHOD__, '1.21' );
1496 
1497  $args = func_get_args();
1498  array_shift( $args );
1499  return wfMsgReal( $key, $args );
1500 }
1501 
1510 function wfMsgNoTrans( $key ) {
1511  wfDeprecated( __METHOD__, '1.21' );
1512 
1513  $args = func_get_args();
1514  array_shift( $args );
1515  return wfMsgReal( $key, $args, true, false, false );
1516 }
1517 
1543 function wfMsgForContent( $key ) {
1544  wfDeprecated( __METHOD__, '1.21' );
1545 
1546  global $wgForceUIMsgAsContentMsg;
1547  $args = func_get_args();
1548  array_shift( $args );
1549  $forcontent = true;
1550  if ( is_array( $wgForceUIMsgAsContentMsg )
1551  && in_array( $key, $wgForceUIMsgAsContentMsg )
1552  ) {
1553  $forcontent = false;
1554  }
1555  return wfMsgReal( $key, $args, true, $forcontent );
1556 }
1557 
1566 function wfMsgForContentNoTrans( $key ) {
1567  wfDeprecated( __METHOD__, '1.21' );
1568 
1569  global $wgForceUIMsgAsContentMsg;
1570  $args = func_get_args();
1571  array_shift( $args );
1572  $forcontent = true;
1573  if ( is_array( $wgForceUIMsgAsContentMsg )
1574  && in_array( $key, $wgForceUIMsgAsContentMsg )
1575  ) {
1576  $forcontent = false;
1577  }
1578  return wfMsgReal( $key, $args, true, $forcontent, false );
1579 }
1580 
1593 function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
1594  wfDeprecated( __METHOD__, '1.21' );
1595 
1596  wfProfileIn( __METHOD__ );
1597  $message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
1598  $message = wfMsgReplaceArgs( $message, $args );
1599  wfProfileOut( __METHOD__ );
1600  return $message;
1601 }
1602 
1615 function wfMsgGetKey( $key, $useDB = true, $langCode = false, $transform = true ) {
1616  wfDeprecated( __METHOD__, '1.21' );
1617 
1618  wfRunHooks( 'NormalizeMessageKey', array( &$key, &$useDB, &$langCode, &$transform ) );
1619 
1621  $message = $cache->get( $key, $useDB, $langCode );
1622  if ( $message === false ) {
1623  $message = '&lt;' . htmlspecialchars( $key ) . '&gt;';
1624  } elseif ( $transform ) {
1625  $message = $cache->transform( $message );
1626  }
1627  return $message;
1628 }
1629 
1638 function wfMsgReplaceArgs( $message, $args ) {
1639  # Fix windows line-endings
1640  # Some messages are split with explode("\n", $msg)
1641  $message = str_replace( "\r", '', $message );
1642 
1643  // Replace arguments
1644  if ( count( $args ) ) {
1645  if ( is_array( $args[0] ) ) {
1646  $args = array_values( $args[0] );
1647  }
1648  $replacementKeys = array();
1649  foreach ( $args as $n => $param ) {
1650  $replacementKeys['$' . ( $n + 1 )] = $param;
1651  }
1652  $message = strtr( $message, $replacementKeys );
1653  }
1654 
1655  return $message;
1656 }
1657 
1671 function wfMsgHtml( $key ) {
1672  wfDeprecated( __METHOD__, '1.21' );
1673 
1674  $args = func_get_args();
1675  array_shift( $args );
1676  return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key ) ), $args );
1677 }
1678 
1692 function wfMsgWikiHtml( $key ) {
1693  wfDeprecated( __METHOD__, '1.21' );
1694 
1695  $args = func_get_args();
1696  array_shift( $args );
1697  return wfMsgReplaceArgs(
1698  MessageCache::singleton()->parse( wfMsgGetKey( $key ), null,
1699  /* can't be set to false */ true, /* interface */ true )->getText(),
1700  $args );
1701 }
1702 
1726 function wfMsgExt( $key, $options ) {
1727  wfDeprecated( __METHOD__, '1.21' );
1728 
1729  $args = func_get_args();
1730  array_shift( $args );
1731  array_shift( $args );
1732  $options = (array)$options;
1733 
1734  foreach ( $options as $arrayKey => $option ) {
1735  if ( !preg_match( '/^[0-9]+|language$/', $arrayKey ) ) {
1736  # An unknown index, neither numeric nor "language"
1737  wfWarn( "wfMsgExt called with incorrect parameter key $arrayKey", 1, E_USER_WARNING );
1738  } elseif ( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option,
1739  array( 'parse', 'parseinline', 'escape', 'escapenoentities',
1740  'replaceafter', 'parsemag', 'content' ) ) ) {
1741  # A numeric index with unknown value
1742  wfWarn( "wfMsgExt called with incorrect parameter $option", 1, E_USER_WARNING );
1743  }
1744  }
1745 
1746  if ( in_array( 'content', $options, true ) ) {
1747  $forContent = true;
1748  $langCode = true;
1749  $langCodeObj = null;
1750  } elseif ( array_key_exists( 'language', $options ) ) {
1751  $forContent = false;
1752  $langCode = wfGetLangObj( $options['language'] );
1753  $langCodeObj = $langCode;
1754  } else {
1755  $forContent = false;
1756  $langCode = false;
1757  $langCodeObj = null;
1758  }
1759 
1760  $string = wfMsgGetKey( $key, /*DB*/true, $langCode, /*Transform*/false );
1761 
1762  if ( !in_array( 'replaceafter', $options, true ) ) {
1763  $string = wfMsgReplaceArgs( $string, $args );
1764  }
1765 
1766  $messageCache = MessageCache::singleton();
1767  $parseInline = in_array( 'parseinline', $options, true );
1768  if ( in_array( 'parse', $options, true ) || $parseInline ) {
1769  $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj );
1770  if ( $string instanceof ParserOutput ) {
1771  $string = $string->getText();
1772  }
1773 
1774  if ( $parseInline ) {
1775  $m = array();
1776  if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
1777  $string = $m[1];
1778  }
1779  }
1780  } elseif ( in_array( 'parsemag', $options, true ) ) {
1781  $string = $messageCache->transform( $string,
1782  !$forContent, $langCodeObj );
1783  }
1784 
1785  if ( in_array( 'escape', $options, true ) ) {
1786  $string = htmlspecialchars ( $string );
1787  } elseif ( in_array( 'escapenoentities', $options, true ) ) {
1788  $string = Sanitizer::escapeHtmlAllowEntities( $string );
1789  }
1790 
1791  if ( in_array( 'replaceafter', $options, true ) ) {
1792  $string = wfMsgReplaceArgs( $string, $args );
1793  }
1794 
1795  return $string;
1796 }
1797 
1808 function wfEmptyMsg( $key ) {
1809  wfDeprecated( __METHOD__, '1.21' );
1810 
1811  return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false;
1812 }
1813 
1822 function wfDebugDieBacktrace( $msg = '' ) {
1823  wfDeprecated( __FUNCTION__, '1.22' );
1824  throw new MWException( $msg );
1825 }
1826 
1834 function wfHostname() {
1835  static $host;
1836  if ( is_null( $host ) ) {
1837 
1838  # Hostname overriding
1839  global $wgOverrideHostname;
1840  if ( $wgOverrideHostname !== false ) {
1841  # Set static and skip any detection
1842  $host = $wgOverrideHostname;
1843  return $host;
1844  }
1845 
1846  if ( function_exists( 'posix_uname' ) ) {
1847  // This function not present on Windows
1848  $uname = posix_uname();
1849  } else {
1850  $uname = false;
1851  }
1852  if ( is_array( $uname ) && isset( $uname['nodename'] ) ) {
1853  $host = $uname['nodename'];
1854  } elseif ( getenv( 'COMPUTERNAME' ) ) {
1855  # Windows computer name
1856  $host = getenv( 'COMPUTERNAME' );
1857  } else {
1858  # This may be a virtual server.
1859  $host = $_SERVER['SERVER_NAME'];
1860  }
1861  }
1862  return $host;
1863 }
1864 
1874 function wfReportTime() {
1875  global $wgRequestTime, $wgShowHostnames;
1876 
1877  $responseTime = round( ( microtime( true ) - $wgRequestTime ) * 1000 );
1878  $reportVars = array( 'wgBackendResponseTime' => $responseTime );
1879  if ( $wgShowHostnames ) {
1880  $reportVars[ 'wgHostname' ] = wfHostname();
1881  }
1882  return Skin::makeVariablesScript( $reportVars );
1883 }
1884 
1900 function wfDebugBacktrace( $limit = 0 ) {
1901  static $disabled = null;
1902 
1903  if ( extension_loaded( 'Zend Optimizer' ) ) {
1904  wfDebug( "Zend Optimizer detected; skipping debug_backtrace for safety.\n" );
1905  return array();
1906  }
1907 
1908  if ( is_null( $disabled ) ) {
1909  $disabled = false;
1910  $functions = explode( ',', ini_get( 'disable_functions' ) );
1911  $functions = array_map( 'trim', $functions );
1912  $functions = array_map( 'strtolower', $functions );
1913  if ( in_array( 'debug_backtrace', $functions ) ) {
1914  wfDebug( "debug_backtrace is in disabled_functions\n" );
1915  $disabled = true;
1916  }
1917  }
1918  if ( $disabled ) {
1919  return array();
1920  }
1921 
1922  if ( $limit && version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
1923  return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit + 1 ), 1 );
1924  } else {
1925  return array_slice( debug_backtrace(), 1 );
1926  }
1927 }
1928 
1934 function wfBacktrace() {
1936 
1937  if ( $wgCommandLineMode ) {
1938  $msg = '';
1939  } else {
1940  $msg = "<ul>\n";
1941  }
1942  $backtrace = wfDebugBacktrace();
1943  foreach ( $backtrace as $call ) {
1944  if ( isset( $call['file'] ) ) {
1945  $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
1946  $file = $f[count( $f ) - 1];
1947  } else {
1948  $file = '-';
1949  }
1950  if ( isset( $call['line'] ) ) {
1951  $line = $call['line'];
1952  } else {
1953  $line = '-';
1954  }
1955  if ( $wgCommandLineMode ) {
1956  $msg .= "$file line $line calls ";
1957  } else {
1958  $msg .= '<li>' . $file . ' line ' . $line . ' calls ';
1959  }
1960  if ( !empty( $call['class'] ) ) {
1961  $msg .= $call['class'] . $call['type'];
1962  }
1963  $msg .= $call['function'] . '()';
1964 
1965  if ( $wgCommandLineMode ) {
1966  $msg .= "\n";
1967  } else {
1968  $msg .= "</li>\n";
1969  }
1970  }
1971  if ( $wgCommandLineMode ) {
1972  $msg .= "\n";
1973  } else {
1974  $msg .= "</ul>\n";
1975  }
1976 
1977  return $msg;
1978 }
1979 
1989 function wfGetCaller( $level = 2 ) {
1990  $backtrace = wfDebugBacktrace( $level + 1 );
1991  if ( isset( $backtrace[$level] ) ) {
1992  return wfFormatStackFrame( $backtrace[$level] );
1993  } else {
1994  return 'unknown';
1995  }
1996 }
1997 
2006 function wfGetAllCallers( $limit = 3 ) {
2007  $trace = array_reverse( wfDebugBacktrace() );
2008  if ( !$limit || $limit > count( $trace ) - 1 ) {
2009  $limit = count( $trace ) - 1;
2010  }
2011  $trace = array_slice( $trace, -$limit - 1, $limit );
2012  return implode( '/', array_map( 'wfFormatStackFrame', $trace ) );
2013 }
2014 
2021 function wfFormatStackFrame( $frame ) {
2022  return isset( $frame['class'] ) ?
2023  $frame['class'] . '::' . $frame['function'] :
2024  $frame['function'];
2025 }
2026 
2027 /* Some generic result counters, pulled out of SearchEngine */
2028 
2036 function wfShowingResults( $offset, $limit ) {
2037  return wfMessage( 'showingresults' )->numParams( $limit, $offset + 1 )->parse();
2038 }
2039 
2051 function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
2052  wfDeprecated( __METHOD__, '1.19' );
2053 
2054  global $wgLang;
2055 
2056  $query = wfCgiToArray( $query );
2057 
2058  if ( is_object( $link ) ) {
2059  $title = $link;
2060  } else {
2062  if ( is_null( $title ) ) {
2063  return false;
2064  }
2065  }
2066 
2067  return $wgLang->viewPrevNext( $title, $offset, $limit, $query, $atend );
2068 }
2069 
2077 function wfClientAcceptsGzip( $force = false ) {
2078  static $result = null;
2079  if ( $result === null || $force ) {
2080  $result = false;
2081  if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
2082  # @todo FIXME: We may want to blacklist some broken browsers
2083  $m = array();
2084  if ( preg_match(
2085  '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
2086  $_SERVER['HTTP_ACCEPT_ENCODING'],
2087  $m
2088  )
2089  ) {
2090  if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) {
2091  $result = false;
2092  return $result;
2093  }
2094  wfDebug( "wfClientAcceptsGzip: client accepts gzip.\n" );
2095  $result = true;
2096  }
2097  }
2098  }
2099  return $result;
2100 }
2101 
2111 function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
2112  global $wgRequest;
2113  return $wgRequest->getLimitOffset( $deflimit, $optionname );
2114 }
2115 
2125 function wfEscapeWikiText( $text ) {
2126  static $repl = null, $repl2 = null;
2127  if ( $repl === null ) {
2128  $repl = array(
2129  '"' => '&#34;', '&' => '&#38;', "'" => '&#39;', '<' => '&#60;',
2130  '=' => '&#61;', '>' => '&#62;', '[' => '&#91;', ']' => '&#93;',
2131  '{' => '&#123;', '|' => '&#124;', '}' => '&#125;', ';' => '&#59;',
2132  "\n#" => "\n&#35;", "\r#" => "\r&#35;",
2133  "\n*" => "\n&#42;", "\r*" => "\r&#42;",
2134  "\n:" => "\n&#58;", "\r:" => "\r&#58;",
2135  "\n " => "\n&#32;", "\r " => "\r&#32;",
2136  "\n\n" => "\n&#10;", "\r\n" => "&#13;\n",
2137  "\n\r" => "\n&#13;", "\r\r" => "\r&#13;",
2138  "\n\t" => "\n&#9;", "\r\t" => "\r&#9;", // "\n\t\n" is treated like "\n\n"
2139  "\n----" => "\n&#45;---", "\r----" => "\r&#45;---",
2140  '__' => '_&#95;', '://' => '&#58;//',
2141  );
2142 
2143  // We have to catch everything "\s" matches in PCRE
2144  foreach ( array( 'ISBN', 'RFC', 'PMID' ) as $magic ) {
2145  $repl["$magic "] = "$magic&#32;";
2146  $repl["$magic\t"] = "$magic&#9;";
2147  $repl["$magic\r"] = "$magic&#13;";
2148  $repl["$magic\n"] = "$magic&#10;";
2149  $repl["$magic\f"] = "$magic&#12;";
2150  }
2151 
2152  // And handle protocols that don't use "://"
2153  global $wgUrlProtocols;
2154  $repl2 = array();
2155  foreach ( $wgUrlProtocols as $prot ) {
2156  if ( substr( $prot, -1 ) === ':' ) {
2157  $repl2[] = preg_quote( substr( $prot, 0, -1 ), '/' );
2158  }
2159  }
2160  $repl2 = $repl2 ? '/\b(' . join( '|', $repl2 ) . '):/i' : '/^(?!)/';
2161  }
2162  $text = substr( strtr( "\n$text", $repl ), 1 );
2163  $text = preg_replace( $repl2, '$1&#58;', $text );
2164  return $text;
2165 }
2166 
2172 function wfTime() {
2173  wfDeprecated( __FUNCTION__, '1.22' );
2174  return microtime( true );
2175 }
2176 
2187 function wfSetVar( &$dest, $source, $force = false ) {
2188  $temp = $dest;
2189  if ( !is_null( $source ) || $force ) {
2190  $dest = $source;
2191  }
2192  return $temp;
2193 }
2194 
2204 function wfSetBit( &$dest, $bit, $state = true ) {
2205  $temp = (bool)( $dest & $bit );
2206  if ( !is_null( $state ) ) {
2207  if ( $state ) {
2208  $dest |= $bit;
2209  } else {
2210  $dest &= ~$bit;
2211  }
2212  }
2213  return $temp;
2214 }
2215 
2222 function wfVarDump( $var ) {
2223  global $wgOut;
2224  $s = str_replace( "\n", "<br />\n", var_export( $var, true ) . "\n" );
2225  if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) {
2226  print $s;
2227  } else {
2228  $wgOut->addHTML( $s );
2229  }
2230 }
2231 
2239 function wfHttpError( $code, $label, $desc ) {
2240  global $wgOut;
2241  $wgOut->disable();
2242  header( "HTTP/1.0 $code $label" );
2243  header( "Status: $code $label" );
2244  $wgOut->sendCacheControl();
2245 
2246  header( 'Content-type: text/html; charset=utf-8' );
2247  print "<!doctype html>" .
2248  '<html><head><title>' .
2249  htmlspecialchars( $label ) .
2250  '</title></head><body><h1>' .
2251  htmlspecialchars( $label ) .
2252  '</h1><p>' .
2253  nl2br( htmlspecialchars( $desc ) ) .
2254  "</p></body></html>\n";
2255 }
2256 
2274 function wfResetOutputBuffers( $resetGzipEncoding = true ) {
2275  if ( $resetGzipEncoding ) {
2276  // Suppress Content-Encoding and Content-Length
2277  // headers from 1.10+s wfOutputHandler
2278  global $wgDisableOutputCompression;
2279  $wgDisableOutputCompression = true;
2280  }
2281  while ( $status = ob_get_status() ) {
2282  if ( $status['type'] == 0 /* PHP_OUTPUT_HANDLER_INTERNAL */ ) {
2283  // Probably from zlib.output_compression or other
2284  // PHP-internal setting which can't be removed.
2285  //
2286  // Give up, and hope the result doesn't break
2287  // output behavior.
2288  break;
2289  }
2290  if ( !ob_end_clean() ) {
2291  // Could not remove output buffer handler; abort now
2292  // to avoid getting in some kind of infinite loop.
2293  break;
2294  }
2295  if ( $resetGzipEncoding ) {
2296  if ( $status['name'] == 'ob_gzhandler' ) {
2297  // Reset the 'Content-Encoding' field set by this handler
2298  // so we can start fresh.
2299  header_remove( 'Content-Encoding' );
2300  break;
2301  }
2302  }
2303  }
2304 }
2305 
2318 function wfClearOutputBuffers() {
2319  wfResetOutputBuffers( false );
2320 }
2321 
2330 function wfAcceptToPrefs( $accept, $def = '*/*' ) {
2331  # No arg means accept anything (per HTTP spec)
2332  if ( !$accept ) {
2333  return array( $def => 1.0 );
2334  }
2335 
2336  $prefs = array();
2337 
2338  $parts = explode( ',', $accept );
2339 
2340  foreach ( $parts as $part ) {
2341  # @todo FIXME: Doesn't deal with params like 'text/html; level=1'
2342  $values = explode( ';', trim( $part ) );
2343  $match = array();
2344  if ( count( $values ) == 1 ) {
2345  $prefs[$values[0]] = 1.0;
2346  } elseif ( preg_match( '/q\s*=\s*(\d*\.\d+)/', $values[1], $match ) ) {
2347  $prefs[$values[0]] = floatval( $match[1] );
2348  }
2349  }
2350 
2351  return $prefs;
2352 }
2353 
2366 function mimeTypeMatch( $type, $avail ) {
2367  if ( array_key_exists( $type, $avail ) ) {
2368  return $type;
2369  } else {
2370  $parts = explode( '/', $type );
2371  if ( array_key_exists( $parts[0] . '/*', $avail ) ) {
2372  return $parts[0] . '/*';
2373  } elseif ( array_key_exists( '*/*', $avail ) ) {
2374  return '*/*';
2375  } else {
2376  return null;
2377  }
2378  }
2379 }
2380 
2394 function wfNegotiateType( $cprefs, $sprefs ) {
2395  $combine = array();
2396 
2397  foreach ( array_keys( $sprefs ) as $type ) {
2398  $parts = explode( '/', $type );
2399  if ( $parts[1] != '*' ) {
2400  $ckey = mimeTypeMatch( $type, $cprefs );
2401  if ( $ckey ) {
2402  $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
2403  }
2404  }
2405  }
2406 
2407  foreach ( array_keys( $cprefs ) as $type ) {
2408  $parts = explode( '/', $type );
2409  if ( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) {
2410  $skey = mimeTypeMatch( $type, $sprefs );
2411  if ( $skey ) {
2412  $combine[$type] = $sprefs[$skey] * $cprefs[$type];
2413  }
2414  }
2415  }
2416 
2417  $bestq = 0;
2418  $besttype = null;
2419 
2420  foreach ( array_keys( $combine ) as $type ) {
2421  if ( $combine[$type] > $bestq ) {
2422  $besttype = $type;
2423  $bestq = $combine[$type];
2424  }
2425  }
2426 
2427  return $besttype;
2428 }
2429 
2435 function wfSuppressWarnings( $end = false ) {
2436  static $suppressCount = 0;
2437  static $originalLevel = false;
2438 
2439  if ( $end ) {
2440  if ( $suppressCount ) {
2441  --$suppressCount;
2442  if ( !$suppressCount ) {
2443  error_reporting( $originalLevel );
2444  }
2445  }
2446  } else {
2447  if ( !$suppressCount ) {
2448  $originalLevel = error_reporting( E_ALL & ~(
2449  E_WARNING |
2450  E_NOTICE |
2451  E_USER_WARNING |
2452  E_USER_NOTICE |
2453  E_DEPRECATED |
2454  E_USER_DEPRECATED |
2455  E_STRICT
2456  ) );
2457  }
2458  ++$suppressCount;
2459  }
2460 }
2461 
2465 function wfRestoreWarnings() {
2466  wfSuppressWarnings( true );
2467 }
2468 
2469 # Autodetect, convert and provide timestamps of various types
2470 
2474 define( 'TS_UNIX', 0 );
2475 
2479 define( 'TS_MW', 1 );
2480 
2484 define( 'TS_DB', 2 );
2485 
2489 define( 'TS_RFC2822', 3 );
2490 
2496 define( 'TS_ISO_8601', 4 );
2497 
2505 define( 'TS_EXIF', 5 );
2506 
2510 define( 'TS_ORACLE', 6 );
2511 
2515 define( 'TS_POSTGRES', 7 );
2516 
2520 define( 'TS_ISO_8601_BASIC', 9 );
2521 
2531 function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
2532  try {
2533  $timestamp = new MWTimestamp( $ts );
2534  return $timestamp->getTimestamp( $outputtype );
2535  } catch ( TimestampException $e ) {
2536  wfDebug( "wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n" );
2537  return false;
2538  }
2539 }
2540 
2549 function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
2550  if ( is_null( $ts ) ) {
2551  return null;
2552  } else {
2553  return wfTimestamp( $outputtype, $ts );
2554  }
2555 }
2556 
2562 function wfTimestampNow() {
2563  # return NOW
2564  return wfTimestamp( TS_MW, time() );
2565 }
2566 
2572 function wfIsWindows() {
2573  static $isWindows = null;
2574  if ( $isWindows === null ) {
2575  $isWindows = substr( php_uname(), 0, 7 ) == 'Windows';
2576  }
2577  return $isWindows;
2578 }
2579 
2585 function wfIsHHVM() {
2586  return defined( 'HHVM_VERSION' );
2587 }
2588 
2595 function swap( &$x, &$y ) {
2596  $z = $x;
2597  $x = $y;
2598  $y = $z;
2599 }
2600 
2612 function wfTempDir() {
2613  global $wgTmpDirectory;
2614 
2615  if ( $wgTmpDirectory !== false ) {
2616  return $wgTmpDirectory;
2617  }
2618 
2619  $tmpDir = array_map( "getenv", array( 'TMPDIR', 'TMP', 'TEMP' ) );
2620 
2621  foreach ( $tmpDir as $tmp ) {
2622  if ( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
2623  return $tmp;
2624  }
2625  }
2626  return sys_get_temp_dir();
2627 }
2628 
2638 function wfMkdirParents( $dir, $mode = null, $caller = null ) {
2639  global $wgDirectoryMode;
2640 
2641  if ( FileBackend::isStoragePath( $dir ) ) { // sanity
2642  throw new MWException( __FUNCTION__ . " given storage path '$dir'." );
2643  }
2644 
2645  if ( !is_null( $caller ) ) {
2646  wfDebug( "$caller: called wfMkdirParents($dir)\n" );
2647  }
2648 
2649  if ( strval( $dir ) === '' || ( file_exists( $dir ) && is_dir( $dir ) ) ) {
2650  return true;
2651  }
2652 
2653  $dir = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $dir );
2654 
2655  if ( is_null( $mode ) ) {
2656  $mode = $wgDirectoryMode;
2657  }
2658 
2659  // Turn off the normal warning, we're doing our own below
2661  $ok = mkdir( $dir, $mode, true ); // PHP5 <3
2663 
2664  if ( !$ok ) {
2665  //directory may have been created on another request since we last checked
2666  if ( is_dir( $dir ) ) {
2667  return true;
2668  }
2669 
2670  // PHP doesn't report the path in its warning message, so add our own to aid in diagnosis.
2671  wfLogWarning( sprintf( "failed to mkdir \"%s\" mode 0%o", $dir, $mode ) );
2672  }
2673  return $ok;
2674 }
2675 
2680 function wfRecursiveRemoveDir( $dir ) {
2681  wfDebug( __FUNCTION__ . "( $dir )\n" );
2682  // taken from http://de3.php.net/manual/en/function.rmdir.php#98622
2683  if ( is_dir( $dir ) ) {
2684  $objects = scandir( $dir );
2685  foreach ( $objects as $object ) {
2686  if ( $object != "." && $object != ".." ) {
2687  if ( filetype( $dir . '/' . $object ) == "dir" ) {
2688  wfRecursiveRemoveDir( $dir . '/' . $object );
2689  } else {
2690  unlink( $dir . '/' . $object );
2691  }
2692  }
2693  }
2694  reset( $objects );
2695  rmdir( $dir );
2696  }
2697 }
2698 
2705 function wfPercent( $nr, $acc = 2, $round = true ) {
2706  $ret = sprintf( "%.${acc}f", $nr );
2707  return $round ? round( $ret, $acc ) . '%' : "$ret%";
2708 }
2709 
2733 function wfIniGetBool( $setting ) {
2734  $val = strtolower( ini_get( $setting ) );
2735  // 'on' and 'true' can't have whitespace around them, but '1' can.
2736  return $val == 'on'
2737  || $val == 'true'
2738  || $val == 'yes'
2739  || preg_match( "/^\s*[+-]?0*[1-9]/", $val ); // approx C atoi() function
2740 }
2741 
2753 function wfEscapeShellArg( /*...*/ ) {
2755 
2756  $args = func_get_args();
2757  $first = true;
2758  $retVal = '';
2759  foreach ( $args as $arg ) {
2760  if ( !$first ) {
2761  $retVal .= ' ';
2762  } else {
2763  $first = false;
2764  }
2765 
2766  if ( wfIsWindows() ) {
2767  // Escaping for an MSVC-style command line parser and CMD.EXE
2768  // @codingStandardsIgnoreStart For long URLs
2769  // Refs:
2770  // * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html
2771  // * http://technet.microsoft.com/en-us/library/cc723564.aspx
2772  // * Bug #13518
2773  // * CR r63214
2774  // Double the backslashes before any double quotes. Escape the double quotes.
2775  // @codingStandardsIgnoreEnd
2776  $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE );
2777  $arg = '';
2778  $iteration = 0;
2779  foreach ( $tokens as $token ) {
2780  if ( $iteration % 2 == 1 ) {
2781  // Delimiter, a double quote preceded by zero or more slashes
2782  $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"';
2783  } elseif ( $iteration % 4 == 2 ) {
2784  // ^ in $token will be outside quotes, need to be escaped
2785  $arg .= str_replace( '^', '^^', $token );
2786  } else { // $iteration % 4 == 0
2787  // ^ in $token will appear inside double quotes, so leave as is
2788  $arg .= $token;
2789  }
2790  $iteration++;
2791  }
2792  // Double the backslashes before the end of the string, because
2793  // we will soon add a quote
2794  $m = array();
2795  if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
2796  $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
2797  }
2798 
2799  // Add surrounding quotes
2800  $retVal .= '"' . $arg . '"';
2801  } else {
2802  $retVal .= escapeshellarg( $arg );
2803  }
2804  }
2805  return $retVal;
2806 }
2807 
2814 function wfShellExecDisabled() {
2815  static $disabled = null;
2816  if ( is_null( $disabled ) ) {
2817  $disabled = false;
2818  if ( wfIniGetBool( 'safe_mode' ) ) {
2819  wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
2820  $disabled = 'safemode';
2821  } else {
2822  $functions = explode( ',', ini_get( 'disable_functions' ) );
2823  $functions = array_map( 'trim', $functions );
2824  $functions = array_map( 'strtolower', $functions );
2825  if ( in_array( 'proc_open', $functions ) ) {
2826  wfDebug( "proc_open is in disabled_functions\n" );
2827  $disabled = 'disabled';
2828  }
2829  }
2830  }
2831  return $disabled;
2832 }
2833 
2852 function wfShellExec( $cmd, &$retval = null, $environ = array(),
2853  $limits = array(), $options = array()
2854 ) {
2855  global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
2856  $wgMaxShellWallClockTime, $wgShellCgroup;
2857 
2858  $disabled = wfShellExecDisabled();
2859  if ( $disabled ) {
2860  $retval = 1;
2861  return $disabled == 'safemode' ?
2862  'Unable to run external programs in safe mode.' :
2863  'Unable to run external programs, proc_open() is disabled.';
2864  }
2865 
2866  $includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
2867 
2869 
2870  $envcmd = '';
2871  foreach ( $environ as $k => $v ) {
2872  if ( wfIsWindows() ) {
2873  /* Surrounding a set in quotes (method used by wfEscapeShellArg) makes the quotes themselves
2874  * appear in the environment variable, so we must use carat escaping as documented in
2875  * http://technet.microsoft.com/en-us/library/cc723564.aspx
2876  * Note however that the quote isn't listed there, but is needed, and the parentheses
2877  * are listed there but doesn't appear to need it.
2878  */
2879  $envcmd .= "set $k=" . preg_replace( '/([&|()<>^"])/', '^\\1', $v ) . '&& ';
2880  } else {
2881  /* Assume this is a POSIX shell, thus required to accept variable assignments before the command
2882  * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_09_01
2883  */
2884  $envcmd .= "$k=" . escapeshellarg( $v ) . ' ';
2885  }
2886  }
2887  $cmd = $envcmd . $cmd;
2888 
2889  $useLogPipe = false;
2890  if ( php_uname( 's' ) == 'Linux' ) {
2891  $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
2892  if ( isset( $limits['walltime'] ) ) {
2893  $wallTime = intval( $limits['walltime'] );
2894  } elseif ( isset( $limits['time'] ) ) {
2895  $wallTime = $time;
2896  } else {
2897  $wallTime = intval( $wgMaxShellWallClockTime );
2898  }
2899  $mem = intval ( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
2900  $filesize = intval ( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
2901 
2902  if ( $time > 0 || $mem > 0 || $filesize > 0 || $wallTime > 0 ) {
2903  $cmd = '/bin/bash ' . escapeshellarg( "$IP/includes/limit.sh" ) . ' ' .
2904  escapeshellarg( $cmd ) . ' ' .
2905  escapeshellarg(
2906  "MW_INCLUDE_STDERR=" . ( $includeStderr ? '1' : '' ) . ';' .
2907  "MW_CPU_LIMIT=$time; " .
2908  'MW_CGROUP=' . escapeshellarg( $wgShellCgroup ) . '; ' .
2909  "MW_MEM_LIMIT=$mem; " .
2910  "MW_FILE_SIZE_LIMIT=$filesize; " .
2911  "MW_WALL_CLOCK_LIMIT=$wallTime; " .
2912  "MW_USE_LOG_PIPE=yes"
2913  );
2914  $useLogPipe = true;
2915  } elseif ( $includeStderr ) {
2916  $cmd .= ' 2>&1';
2917  }
2918  } elseif ( $includeStderr ) {
2919  $cmd .= ' 2>&1';
2920  }
2921  wfDebug( "wfShellExec: $cmd\n" );
2922 
2923  // Don't try to execute commands that exceed Linux's MAX_ARG_STRLEN.
2924  // Other platforms may be more accomodating, but we don't want to be
2925  // accomodating, because very long commands probably include user
2926  // input. See T129506.
2927  if ( strlen( $cmd ) > SHELL_MAX_ARG_STRLEN ) {
2928  throw new Exception( __METHOD__ . '(): total length of $cmd must not exceed SHELL_MAX_ARG_STRLEN' );
2929  }
2930 
2931  $desc = array(
2932  0 => array( 'file', 'php://stdin', 'r' ),
2933  1 => array( 'pipe', 'w' ),
2934  2 => array( 'file', 'php://stderr', 'w' ) );
2935  if ( $useLogPipe ) {
2936  $desc[3] = array( 'pipe', 'w' );
2937  }
2938  $pipes = null;
2939  $proc = proc_open( $cmd, $desc, $pipes );
2940  if ( !$proc ) {
2941  wfDebugLog( 'exec', "proc_open() failed: $cmd" );
2942  $retval = -1;
2943  return '';
2944  }
2945  $outBuffer = $logBuffer = '';
2946  $emptyArray = array();
2947  $status = false;
2948  $logMsg = false;
2949 
2950  // According to the documentation, it is possible for stream_select()
2951  // to fail due to EINTR. I haven't managed to induce this in testing
2952  // despite sending various signals. If it did happen, the error
2953  // message would take the form:
2954  //
2955  // stream_select(): unable to select [4]: Interrupted system call (max_fd=5)
2956  //
2957  // where [4] is the value of the macro EINTR and "Interrupted system
2958  // call" is string which according to the Linux manual is "possibly"
2959  // localised according to LC_MESSAGES.
2960  $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
2961  $eintrMessage = "stream_select(): unable to select [$eintr]";
2962 
2963  // Build a table mapping resource IDs to pipe FDs to work around a
2964  // PHP 5.3 issue in which stream_select() does not preserve array keys
2965  // <https://bugs.php.net/bug.php?id=53427>.
2966  $fds = array();
2967  foreach ( $pipes as $fd => $pipe ) {
2968  $fds[(int)$pipe] = $fd;
2969  }
2970 
2971  $running = true;
2972  $timeout = null;
2973  $numReadyPipes = 0;
2974 
2975  while ( $running === true || $numReadyPipes !== 0 ) {
2976  if ( $running ) {
2977  $status = proc_get_status( $proc );
2978  // If the process has terminated, switch to nonblocking selects
2979  // for getting any data still waiting to be read.
2980  if ( !$status['running'] ) {
2981  $running = false;
2982  $timeout = 0;
2983  }
2984  }
2985 
2986  $readyPipes = $pipes;
2987 
2988  // Clear last error
2989  @trigger_error( '' );
2990  $numReadyPipes = @stream_select( $readyPipes, $emptyArray, $emptyArray, $timeout );
2991  if ( $numReadyPipes === false ) {
2992  $error = error_get_last();
2993  if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
2994  continue;
2995  } else {
2996  trigger_error( $error['message'], E_USER_WARNING );
2997  $logMsg = $error['message'];
2998  break;
2999  }
3000  }
3001  foreach ( $readyPipes as $pipe ) {
3002  $block = fread( $pipe, 65536 );
3003  $fd = $fds[(int)$pipe];
3004  if ( $block === '' ) {
3005  // End of file
3006  fclose( $pipes[$fd] );
3007  unset( $pipes[$fd] );
3008  if ( !$pipes ) {
3009  break 2;
3010  }
3011  } elseif ( $block === false ) {
3012  // Read error
3013  $logMsg = "Error reading from pipe";
3014  break 2;
3015  } elseif ( $fd == 1 ) {
3016  // From stdout
3017  $outBuffer .= $block;
3018  } elseif ( $fd == 3 ) {
3019  // From log FD
3020  $logBuffer .= $block;
3021  if ( strpos( $block, "\n" ) !== false ) {
3022  $lines = explode( "\n", $logBuffer );
3023  $logBuffer = array_pop( $lines );
3024  foreach ( $lines as $line ) {
3025  wfDebugLog( 'exec', $line );
3026  }
3027  }
3028  }
3029  }
3030  }
3031 
3032  foreach ( $pipes as $pipe ) {
3033  fclose( $pipe );
3034  }
3035 
3036  // Use the status previously collected if possible, since proc_get_status()
3037  // just calls waitpid() which will not return anything useful the second time.
3038  if ( $running ) {
3039  $status = proc_get_status( $proc );
3040  }
3041 
3042  if ( $logMsg !== false ) {
3043  // Read/select error
3044  $retval = -1;
3045  proc_close( $proc );
3046  } elseif ( $status['signaled'] ) {
3047  $logMsg = "Exited with signal {$status['termsig']}";
3048  $retval = 128 + $status['termsig'];
3049  proc_close( $proc );
3050  } else {
3051  if ( $status['running'] ) {
3052  $retval = proc_close( $proc );
3053  } else {
3054  $retval = $status['exitcode'];
3055  proc_close( $proc );
3056  }
3057  if ( $retval == 127 ) {
3058  $logMsg = "Possibly missing executable file";
3059  } elseif ( $retval >= 129 && $retval <= 192 ) {
3060  $logMsg = "Probably exited with signal " . ( $retval - 128 );
3061  }
3062  }
3063 
3064  if ( $logMsg !== false ) {
3065  wfDebugLog( 'exec', "$logMsg: $cmd" );
3066  }
3067 
3068  return $outBuffer;
3069 }
3070 
3085 function wfShellExecWithStderr( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
3086  return wfShellExec( $cmd, $retval, $environ, $limits, array( 'duplicateStderr' => true ) );
3087 }
3088 
3093 function wfInitShellLocale() {
3094  static $done = false;
3095  if ( $done ) {
3096  return;
3097  }
3098  $done = true;
3099  global $wgShellLocale;
3100  if ( !wfIniGetBool( 'safe_mode' ) ) {
3101  putenv( "LC_CTYPE=$wgShellLocale" );
3102  setlocale( LC_CTYPE, $wgShellLocale );
3103  }
3104 }
3105 
3111 function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) {
3112  return wfShellWikiCmd( $script, $parameters, $options );
3113 }
3114 
3127 function wfShellWikiCmd( $script, array $parameters = array(), array $options = array() ) {
3128  global $wgPhpCli;
3129  // Give site config file a chance to run the script in a wrapper.
3130  // The caller may likely want to call wfBasename() on $script.
3131  wfRunHooks( 'wfShellWikiCmd', array( &$script, &$parameters, &$options ) );
3132  $cmd = isset( $options['php'] ) ? array( $options['php'] ) : array( $wgPhpCli );
3133  if ( isset( $options['wrapper'] ) ) {
3134  $cmd[] = $options['wrapper'];
3135  }
3136  $cmd[] = $script;
3137  // Escape each parameter for shell
3138  return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
3139 }
3140 
3151 function wfMerge( $old, $mine, $yours, &$result ) {
3152  global $wgDiff3;
3153 
3154  # This check may also protect against code injection in
3155  # case of broken installations.
3157  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
3159 
3160  if ( !$haveDiff3 ) {
3161  wfDebug( "diff3 not found\n" );
3162  return false;
3163  }
3164 
3165  # Make temporary files
3166  $td = wfTempDir();
3167  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3168  $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
3169  $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
3170 
3171  # NOTE: diff3 issues a warning to stderr if any of the files does not end with
3172  # a newline character. To avoid this, we normalize the trailing whitespace before
3173  # creating the diff.
3174 
3175  fwrite( $oldtextFile, rtrim( $old ) . "\n" );
3176  fclose( $oldtextFile );
3177  fwrite( $mytextFile, rtrim( $mine ) . "\n" );
3178  fclose( $mytextFile );
3179  fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
3180  fclose( $yourtextFile );
3181 
3182  # Check for a conflict
3183  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
3184  wfEscapeShellArg( $mytextName ) . ' ' .
3185  wfEscapeShellArg( $oldtextName ) . ' ' .
3186  wfEscapeShellArg( $yourtextName );
3187  $handle = popen( $cmd, 'r' );
3188 
3189  if ( fgets( $handle, 1024 ) ) {
3190  $conflict = true;
3191  } else {
3192  $conflict = false;
3193  }
3194  pclose( $handle );
3195 
3196  # Merge differences
3197  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
3198  wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
3199  $handle = popen( $cmd, 'r' );
3200  $result = '';
3201  do {
3202  $data = fread( $handle, 8192 );
3203  if ( strlen( $data ) == 0 ) {
3204  break;
3205  }
3206  $result .= $data;
3207  } while ( true );
3208  pclose( $handle );
3209  unlink( $mytextName );
3210  unlink( $oldtextName );
3211  unlink( $yourtextName );
3212 
3213  if ( $result === '' && $old !== '' && !$conflict ) {
3214  wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
3215  $conflict = true;
3216  }
3217  return !$conflict;
3218 }
3219 
3229 function wfDiff( $before, $after, $params = '-u' ) {
3230  if ( $before == $after ) {
3231  return '';
3232  }
3233 
3234  global $wgDiff;
3236  $haveDiff = $wgDiff && file_exists( $wgDiff );
3238 
3239  # This check may also protect against code injection in
3240  # case of broken installations.
3241  if ( !$haveDiff ) {
3242  wfDebug( "diff executable not found\n" );
3243  $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) );
3244  $format = new UnifiedDiffFormatter();
3245  return $format->format( $diffs );
3246  }
3247 
3248  # Make temporary files
3249  $td = wfTempDir();
3250  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3251  $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' );
3252 
3253  fwrite( $oldtextFile, $before );
3254  fclose( $oldtextFile );
3255  fwrite( $newtextFile, $after );
3256  fclose( $newtextFile );
3257 
3258  // Get the diff of the two files
3259  $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName );
3260 
3261  $h = popen( $cmd, 'r' );
3262 
3263  $diff = '';
3264 
3265  do {
3266  $data = fread( $h, 8192 );
3267  if ( strlen( $data ) == 0 ) {
3268  break;
3269  }
3270  $diff .= $data;
3271  } while ( true );
3272 
3273  // Clean up
3274  pclose( $h );
3275  unlink( $oldtextName );
3276  unlink( $newtextName );
3277 
3278  // Kill the --- and +++ lines. They're not useful.
3279  $diff_lines = explode( "\n", $diff );
3280  if ( strpos( $diff_lines[0], '---' ) === 0 ) {
3281  unset( $diff_lines[0] );
3282  }
3283  if ( strpos( $diff_lines[1], '+++' ) === 0 ) {
3284  unset( $diff_lines[1] );
3285  }
3286 
3287  $diff = implode( "\n", $diff_lines );
3288 
3289  return $diff;
3290 }
3291 
3308 function wfUsePHP( $req_ver ) {
3309  $php_ver = PHP_VERSION;
3310 
3311  if ( version_compare( $php_ver, (string)$req_ver, '<' ) ) {
3312  throw new MWException( "PHP $req_ver required--this is only $php_ver" );
3313  }
3314 }
3315 
3338 function wfUseMW( $req_ver ) {
3339  global $wgVersion;
3340 
3341  if ( version_compare( $wgVersion, (string)$req_ver, '<' ) ) {
3342  throw new MWException( "MediaWiki $req_ver required--this is only $wgVersion" );
3343  }
3344 }
3345 
3358 function wfBaseName( $path, $suffix = '' ) {
3359  if ( $suffix == '' ) {
3360  $encSuffix = '';
3361  } else {
3362  $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
3363  }
3364 
3365  $matches = array();
3366  if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
3367  return $matches[1];
3368  } else {
3369  return '';
3370  }
3371 }
3372 
3382 function wfRelativePath( $path, $from ) {
3383  // Normalize mixed input on Windows...
3384  $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
3385  $from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
3386 
3387  // Trim trailing slashes -- fix for drive root
3388  $path = rtrim( $path, DIRECTORY_SEPARATOR );
3389  $from = rtrim( $from, DIRECTORY_SEPARATOR );
3390 
3391  $pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
3392  $against = explode( DIRECTORY_SEPARATOR, $from );
3393 
3394  if ( $pieces[0] !== $against[0] ) {
3395  // Non-matching Windows drive letters?
3396  // Return a full path.
3397  return $path;
3398  }
3399 
3400  // Trim off common prefix
3401  while ( count( $pieces ) && count( $against )
3402  && $pieces[0] == $against[0] ) {
3403  array_shift( $pieces );
3404  array_shift( $against );
3405  }
3406 
3407  // relative dots to bump us to the parent
3408  while ( count( $against ) ) {
3409  array_unshift( $pieces, '..' );
3410  array_shift( $against );
3411  }
3412 
3413  array_push( $pieces, wfBaseName( $path ) );
3414 
3415  return implode( DIRECTORY_SEPARATOR, $pieces );
3416 }
3417 
3433 function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
3434  $lowercase = true, $engine = 'auto'
3435 ) {
3436  $input = (string)$input;
3437  if (
3438  $sourceBase < 2 ||
3439  $sourceBase > 36 ||
3440  $destBase < 2 ||
3441  $destBase > 36 ||
3442  $sourceBase != (int)$sourceBase ||
3443  $destBase != (int)$destBase ||
3444  $pad != (int)$pad ||
3445  !preg_match(
3446  "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i",
3447  $input
3448  )
3449  ) {
3450  return false;
3451  }
3452 
3453  static $baseChars = array(
3454  10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f',
3455  16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l',
3456  22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r',
3457  28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x',
3458  34 => 'y', 35 => 'z',
3459 
3460  '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5,
3461  '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11,
3462  'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17,
3463  'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23,
3464  'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29,
3465  'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35
3466  );
3467 
3468  if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
3469  $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
3470  } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
3471  $decimal = '0';
3472  foreach ( str_split( strtolower( $input ) ) as $char ) {
3473  $decimal = bcmul( $decimal, $sourceBase );
3474  $decimal = bcadd( $decimal, $baseChars[$char] );
3475  }
3476 
3477  for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
3478  $result .= $baseChars[bcmod( $decimal, $destBase )];
3479  }
3480 
3481  $result = strrev( $result );
3482  } else {
3483  $inDigits = array();
3484  foreach ( str_split( strtolower( $input ) ) as $char ) {
3485  $inDigits[] = $baseChars[$char];
3486  }
3487 
3488  // Iterate over the input, modulo-ing out an output digit
3489  // at a time until input is gone.
3490  $result = '';
3491  while ( $inDigits ) {
3492  $work = 0;
3493  $workDigits = array();
3494 
3495  // Long division...
3496  foreach ( $inDigits as $digit ) {
3497  $work *= $sourceBase;
3498  $work += $digit;
3499 
3500  if ( $workDigits || $work >= $destBase ) {
3501  $workDigits[] = (int)( $work / $destBase );
3502  }
3503  $work %= $destBase;
3504  }
3505 
3506  // All that division leaves us with a remainder,
3507  // which is conveniently our next output digit.
3508  $result .= $baseChars[$work];
3509 
3510  // And we continue!
3511  $inDigits = $workDigits;
3512  }
3513 
3514  $result = strrev( $result );
3515  }
3516 
3517  if ( !$lowercase ) {
3518  $result = strtoupper( $result );
3519  }
3520 
3521  return str_pad( $result, $pad, '0', STR_PAD_LEFT );
3522 }
3523 
3529 function wfCheckEntropy() {
3530  return (
3531  ( wfIsWindows() && version_compare( PHP_VERSION, '5.3.3', '>=' ) )
3532  || ini_get( 'session.entropy_file' )
3533  )
3534  && intval( ini_get( 'session.entropy_length' ) ) >= 32;
3535 }
3536 
3541 function wfFixSessionID() {
3542  // If the cookie or session id is already set we already have a session and should abort
3543  if ( isset( $_COOKIE[session_name()] ) || session_id() ) {
3544  return;
3545  }
3546 
3547  // PHP's built-in session entropy is enabled if:
3548  // - entropy_file is set or you're on Windows with php 5.3.3+
3549  // - AND entropy_length is > 0
3550  // We treat it as disabled if it doesn't have an entropy length of at least 32
3551  $entropyEnabled = wfCheckEntropy();
3552 
3553  // If built-in entropy is not enabled or not sufficient override PHP's
3554  // built in session id generation code
3555  if ( !$entropyEnabled ) {
3556  wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, " .
3557  "overriding session id generation using our cryptrand source.\n" );
3558  session_id( MWCryptRand::generateHex( 32 ) );
3559  }
3560 }
3561 
3567 function wfResetSessionID() {
3568  global $wgCookieSecure;
3569  $oldSessionId = session_id();
3570  $cookieParams = session_get_cookie_params();
3571  if ( wfCheckEntropy() && $wgCookieSecure == $cookieParams['secure'] ) {
3572  session_regenerate_id( false );
3573  } else {
3574  $tmp = $_SESSION;
3575  session_destroy();
3577  $_SESSION = $tmp;
3578  }
3579  $newSessionId = session_id();
3580  wfRunHooks( 'ResetSessionID', array( $oldSessionId, $newSessionId ) );
3581 }
3582 
3588 function wfSetupSession( $sessionId = false ) {
3589  global $wgSessionsInMemcached, $wgSessionsInObjectCache, $wgCookiePath, $wgCookieDomain,
3590  $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler;
3591  if ( $wgSessionsInObjectCache || $wgSessionsInMemcached ) {
3593  } elseif ( $wgSessionHandler && $wgSessionHandler != ini_get( 'session.save_handler' ) ) {
3594  # Only set this if $wgSessionHandler isn't null and session.save_handler
3595  # hasn't already been set to the desired value (that causes errors)
3596  ini_set( 'session.save_handler', $wgSessionHandler );
3597  }
3598  session_set_cookie_params(
3599  0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly );
3600  session_cache_limiter( 'private, must-revalidate' );
3601  if ( $sessionId ) {
3602  session_id( $sessionId );
3603  } else {
3604  wfFixSessionID();
3605  }
3607  session_start();
3609 }
3610 
3617 function wfGetPrecompiledData( $name ) {
3618  global $IP;
3619 
3620  $file = "$IP/serialized/$name";
3621  if ( file_exists( $file ) ) {
3622  $blob = file_get_contents( $file );
3623  if ( $blob ) {
3624  return unserialize( $blob );
3625  }
3626  }
3627  return false;
3628 }
3629 
3636 function wfMemcKey( /*...*/ ) {
3637  global $wgCachePrefix;
3638  $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
3639  $args = func_get_args();
3640  $key = $prefix . ':' . implode( ':', $args );
3641  $key = str_replace( ' ', '_', $key );
3642  return $key;
3643 }
3644 
3653 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
3654  $args = array_slice( func_get_args(), 2 );
3655  if ( $prefix ) {
3656  $key = "$db-$prefix:" . implode( ':', $args );
3657  } else {
3658  $key = $db . ':' . implode( ':', $args );
3659  }
3660  return str_replace( ' ', '_', $key );
3661 }
3662 
3669 function wfWikiID() {
3670  global $wgDBprefix, $wgDBname;
3671  if ( $wgDBprefix ) {
3672  return "$wgDBname-$wgDBprefix";
3673  } else {
3674  return $wgDBname;
3675  }
3676 }
3677 
3685 function wfSplitWikiID( $wiki ) {
3686  $bits = explode( '-', $wiki, 2 );
3687  if ( count( $bits ) < 2 ) {
3688  $bits[] = '';
3689  }
3690  return $bits;
3691 }
3692 
3715 function &wfGetDB( $db, $groups = array(), $wiki = false ) {
3716  return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
3717 }
3718 
3725 function wfGetLB( $wiki = false ) {
3726  return wfGetLBFactory()->getMainLB( $wiki );
3727 }
3728 
3734 function &wfGetLBFactory() {
3735  return LBFactory::singleton();
3736 }
3737 
3758 function wfFindFile( $title, $options = array() ) {
3759  return RepoGroup::singleton()->findFile( $title, $options );
3760 }
3761 
3769 function wfLocalFile( $title ) {
3770  return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
3771 }
3772 
3779 function wfQueriesMustScale() {
3780  global $wgMiserMode;
3781  return $wgMiserMode
3782  || ( SiteStats::pages() > 100000
3783  && SiteStats::edits() > 1000000
3784  && SiteStats::users() > 10000 );
3785 }
3786 
3795 function wfScript( $script = 'index' ) {
3796  global $wgScriptPath, $wgScriptExtension, $wgScript, $wgLoadScript;
3797  if ( $script === 'index' ) {
3798  return $wgScript;
3799  } elseif ( $script === 'load' ) {
3800  return $wgLoadScript;
3801  } else {
3802  return "{$wgScriptPath}/{$script}{$wgScriptExtension}";
3803  }
3804 }
3805 
3811 function wfGetScriptUrl() {
3812  if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
3813  #
3814  # as it was called, minus the query string.
3815  #
3816  # Some sites use Apache rewrite rules to handle subdomains,
3817  # and have PHP set up in a weird way that causes PHP_SELF
3818  # to contain the rewritten URL instead of the one that the
3819  # outside world sees.
3820  #
3821  # If in this mode, use SCRIPT_URL instead, which mod_rewrite
3822  # provides containing the "before" URL.
3823  return $_SERVER['SCRIPT_NAME'];
3824  } else {
3825  return $_SERVER['URL'];
3826  }
3827 }
3828 
3836 function wfBoolToStr( $value ) {
3837  return $value ? 'true' : 'false';
3838 }
3839 
3845 function wfGetNull() {
3846  return wfIsWindows() ? 'NUL' : '/dev/null';
3847 }
3848 
3860 function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
3861  if ( $cluster !== false ) {
3862  $lb = wfGetLBFactory()->getExternalLB( $cluster );
3863  } else {
3864  $lb = wfGetLB( $wiki );
3865  }
3866 
3867  // bug 27975 - Don't try to wait for slaves if there are none
3868  // Prevents permission error when getting master position
3869  if ( $lb->getServerCount() > 1 ) {
3870  $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
3871  $pos = $dbw->getMasterPos();
3872  // The DBMS may not support getMasterPos() or the whole
3873  // load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
3874  if ( $pos !== false ) {
3875  $lb->waitForAll( $pos );
3876  }
3877  }
3878 }
3879 
3887 function wfCountDown( $seconds ) {
3888  for ( $i = $seconds; $i >= 0; $i-- ) {
3889  if ( $i != $seconds ) {
3890  echo str_repeat( "\x08", strlen( $i + 1 ) );
3891  }
3892  echo $i;
3893  flush();
3894  if ( $i ) {
3895  sleep( 1 );
3896  }
3897  }
3898  echo "\n";
3899 }
3900 
3909 function wfStripIllegalFilenameChars( $name ) {
3910  global $wgIllegalFileChars;
3911  $illegalFileChars = $wgIllegalFileChars ? "|[" . $wgIllegalFileChars . "]" : '';
3912  $name = wfBaseName( $name );
3913  $name = preg_replace(
3914  "/[^" . Title::legalChars() . "]" . $illegalFileChars . "/",
3915  '-',
3916  $name
3917  );
3918  return $name;
3919 }
3920 
3926 function wfMemoryLimit() {
3927  global $wgMemoryLimit;
3928  $memlimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
3929  if ( $memlimit != -1 ) {
3930  $conflimit = wfShorthandToInteger( $wgMemoryLimit );
3931  if ( $conflimit == -1 ) {
3932  wfDebug( "Removing PHP's memory limit\n" );
3934  ini_set( 'memory_limit', $conflimit );
3936  return $conflimit;
3937  } elseif ( $conflimit > $memlimit ) {
3938  wfDebug( "Raising PHP's memory limit to $conflimit bytes\n" );
3940  ini_set( 'memory_limit', $conflimit );
3942  return $conflimit;
3943  }
3944  }
3945  return $memlimit;
3946 }
3947 
3955 function wfShorthandToInteger( $string = '', $default = -1 ) {
3956  $string = trim( $string );
3957  if ( $string === '' ) {
3958  return $default;
3959  }
3960  $last = $string[strlen( $string ) - 1];
3961  $val = intval( $string );
3962  switch ( $last ) {
3963  case 'g':
3964  case 'G':
3965  $val *= 1024;
3966  // break intentionally missing
3967  case 'm':
3968  case 'M':
3969  $val *= 1024;
3970  // break intentionally missing
3971  case 'k':
3972  case 'K':
3973  $val *= 1024;
3974  }
3975 
3976  return $val;
3977 }
3978 
3986 function wfBCP47( $code ) {
3987  $codeSegment = explode( '-', $code );
3988  $codeBCP = array();
3989  foreach ( $codeSegment as $segNo => $seg ) {
3990  // when previous segment is x, it is a private segment and should be lc
3991  if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
3992  $codeBCP[$segNo] = strtolower( $seg );
3993  // ISO 3166 country code
3994  } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
3995  $codeBCP[$segNo] = strtoupper( $seg );
3996  // ISO 15924 script code
3997  } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
3998  $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
3999  // Use lowercase for other cases
4000  } else {
4001  $codeBCP[$segNo] = strtolower( $seg );
4002  }
4003  }
4004  $langCode = implode( '-', $codeBCP );
4005  return $langCode;
4006 }
4007 
4014 function wfGetCache( $inputType ) {
4015  return ObjectCache::getInstance( $inputType );
4016 }
4017 
4023 function wfGetMainCache() {
4026 }
4027 
4033 function wfGetMessageCacheStorage() {
4034  global $wgMessageCacheType;
4035  return ObjectCache::getInstance( $wgMessageCacheType );
4036 }
4037 
4043 function wfGetParserCacheStorage() {
4044  global $wgParserCacheType;
4045  return ObjectCache::getInstance( $wgParserCacheType );
4046 }
4047 
4053 function wfGetLangConverterCacheStorage() {
4054  global $wgLanguageConverterCacheType;
4055  return ObjectCache::getInstance( $wgLanguageConverterCacheType );
4056 }
4057 
4067 function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null ) {
4068  return Hooks::run( $event, $args, $deprecatedVersion );
4069 }
4070 
4085 function wfUnpack( $format, $data, $length = false ) {
4086  if ( $length !== false ) {
4087  $realLen = strlen( $data );
4088  if ( $realLen < $length ) {
4089  throw new MWException( "Tried to use wfUnpack on a "
4090  . "string of length $realLen, but needed one "
4091  . "of at least length $length."
4092  );
4093  }
4094  }
4095 
4097  $result = unpack( $format, $data );
4099 
4100  if ( $result === false ) {
4101  // If it cannot extract the packed data.
4102  throw new MWException( "unpack could not unpack binary data" );
4103  }
4104  return $result;
4105 }
4106 
4121 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
4122  static $badImageCache = null; // based on bad_image_list msg
4123  wfProfileIn( __METHOD__ );
4124 
4125  # Handle redirects
4126  $redirectTitle = RepoGroup::singleton()->checkRedirect( Title::makeTitle( NS_FILE, $name ) );
4127  if ( $redirectTitle ) {
4128  $name = $redirectTitle->getDBkey();
4129  }
4130 
4131  # Run the extension hook
4132  $bad = false;
4133  if ( !wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {
4134  wfProfileOut( __METHOD__ );
4135  return $bad;
4136  }
4137 
4138  $cacheable = ( $blacklist === null );
4139  if ( $cacheable && $badImageCache !== null ) {
4140  $badImages = $badImageCache;
4141  } else { // cache miss
4142  if ( $blacklist === null ) {
4143  $blacklist = wfMessage( 'bad_image_list' )->inContentLanguage()->plain(); // site list
4144  }
4145  # Build the list now
4146  $badImages = array();
4147  $lines = explode( "\n", $blacklist );
4148  foreach ( $lines as $line ) {
4149  # List items only
4150  if ( substr( $line, 0, 1 ) !== '*' ) {
4151  continue;
4152  }
4153 
4154  # Find all links
4155  $m = array();
4156  if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
4157  continue;
4158  }
4159 
4160  $exceptions = array();
4161  $imageDBkey = false;
4162  foreach ( $m[1] as $i => $titleText ) {
4163  $title = Title::newFromText( $titleText );
4164  if ( !is_null( $title ) ) {
4165  if ( $i == 0 ) {
4166  $imageDBkey = $title->getDBkey();
4167  } else {
4168  $exceptions[$title->getPrefixedDBkey()] = true;
4169  }
4170  }
4171  }
4172 
4173  if ( $imageDBkey !== false ) {
4174  $badImages[$imageDBkey] = $exceptions;
4175  }
4176  }
4177  if ( $cacheable ) {
4178  $badImageCache = $badImages;
4179  }
4180  }
4181 
4182  $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
4183  $bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
4184  wfProfileOut( __METHOD__ );
4185  return $bad;
4186 }
4187 
4195 function wfCanIPUseHTTPS( $ip ) {
4196  $canDo = true;
4197  wfRunHooks( 'CanIPUseHTTPS', array( $ip, &$canDo ) );
4198  return !!$canDo;
4199 }
4200 
4208 function wfGetIP() {
4209  wfDeprecated( __METHOD__, '1.19' );
4210  global $wgRequest;
4211  return $wgRequest->getIP();
4212 }
4213 
4222 function wfIsTrustedProxy( $ip ) {
4223  $trusted = wfIsConfiguredProxy( $ip );
4224  wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
4225  return $trusted;
4226 }
4227 
4235 function wfIsConfiguredProxy( $ip ) {
4236  global $wgSquidServers, $wgSquidServersNoPurge;
4237 
4238  // quick check of known proxy servers
4239  $trusted = in_array( $ip, $wgSquidServers )
4240  || in_array( $ip, $wgSquidServersNoPurge );
4241 
4242  if ( !$trusted ) {
4243  // slightly slower check to see if the ip is listed directly or in a CIDR
4244  // block in $wgSquidServersNoPurge
4245  foreach ( $wgSquidServersNoPurge as $block ) {
4246  if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
4247  $trusted = true;
4248  break;
4249  }
4250  }
4251  }
4252  return $trusted;
4253 }
wfMsgNoTrans
wfMsgNoTrans( $key)
Same as above except doesn't transform the message.
Definition: GlobalFunctions.php:1509
wfMessage
wfMessage( $key)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1448
StatCounter\singleton
static singleton()
Definition: StatCounter.php:46
wfFixSessionID
wfFixSessionID()
Override session_id before session startup if php's built-in session generation code is not secure.
Definition: GlobalFunctions.php:3540
wfGetIP
wfGetIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Definition: GlobalFunctions.php:4207
MWTimestamp
Library for creating and parsing MW-style timestamps.
Definition: MWTimestamp.php:31
wfUseMW
wfUseMW( $req_ver)
This function works like "use VERSION" in Perl except it checks the version of MediaWiki,...
Definition: GlobalFunctions.php:3337
wfArrayInsertAfter
wfArrayInsertAfter(array $array, array $insert, $after)
Insert array into another array after the specified KEY
Definition: GlobalFunctions.php:282
Title\makeTitle
static & makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:398
$wgUser
$wgUser
Definition: Setup.php:572
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. $title:Title object for the current page $request:WebRequest $ignoreRedirect:boolean to skip redirect check $target:Title/string of redirect target $article:Article object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) $article:article(object) being checked 'IsTrustedProxy':Override the result of wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of User::isValidEmailAddr(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetMagic':DEPRECATED, use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetSpecialPageAliases':DEPRECATED, use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1528
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:189
wfPercent
wfPercent( $nr, $acc=2, $round=true)
Definition: GlobalFunctions.php:2704
DB_MASTER
const DB_MASTER
Definition: Defines.php:56
wfShellExec
wfShellExec( $cmd, &$retval=null, $environ=array(), $limits=array(), $options=array())
Execute a shell command, with time and memory limits mirrored from the PHP configuration if supported...
Definition: GlobalFunctions.php:2851
wfResetOutputBuffers
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
Definition: GlobalFunctions.php:2273
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:271
wfBCP47
wfBCP47( $code)
Get the normalised IETF language tag See unit test for examples.
Definition: GlobalFunctions.php:3985
RepoGroup\singleton
static singleton()
Get a RepoGroup instance.
Definition: RepoGroup.php:53
wfCanIPUseHTTPS
wfCanIPUseHTTPS( $ip)
Determine whether the client at a given source IP is likely to be able to access the wiki via HTTPS.
Definition: GlobalFunctions.php:4194
wfMergeErrorArrays
wfMergeErrorArrays()
Merge arrays in the style of getUserPermissionsErrors, with duplicate removal e.g.
Definition: GlobalFunctions.php:260
ParserOutput
Definition: ParserOutput.php:24
wfMsgForContent
wfMsgForContent( $key)
Get a message from anywhere, for the current global language set with $wgLanguageCode.
Definition: GlobalFunctions.php:1542
wfErrorLog
wfErrorLog( $text, $file)
Log to a file without getting "file size exceeded" signals.
Definition: GlobalFunctions.php:1215
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
wfShellMaintenanceCmd
wfShellMaintenanceCmd( $script, array $parameters=array(), array $options=array())
Alias to wfShellWikiCmd()
Definition: GlobalFunctions.php:3110
SiteStats\users
static users()
Definition: SiteStats.php:140
PROTO_INTERNAL
const PROTO_INTERNAL
Definition: Defines.php:272
wfDiff
wfDiff( $before, $after, $params='-u')
Returns unified plain-text diff of two texts.
Definition: GlobalFunctions.php:3228
wfMerge
wfMerge( $old, $mine, $yours, &$result)
wfMerge attempts to merge differences between three texts.
Definition: GlobalFunctions.php:3150
wfSetupSession
wfSetupSession( $sessionId=false)
Initialise php session.
Definition: GlobalFunctions.php:3587
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:127
wfMkdirParents
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
Definition: GlobalFunctions.php:2637
LBFactory\singleton
static & singleton()
Get an LBFactory instance.
Definition: LBFactory.php:46
wfDebugBacktrace
wfDebugBacktrace( $limit=0)
Safety wrapper for debug_backtrace().
Definition: GlobalFunctions.php:1899
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:2186
wfGetLB
wfGetLB( $wiki=false)
Get a load balancer object.
Definition: GlobalFunctions.php:3724
wfCheckLimits
wfCheckLimits( $deflimit=50, $optionname='rclimit')
Obtain the offset and limit values from the request string; used in special pages.
Definition: GlobalFunctions.php:2110
wfFormatStackFrame
wfFormatStackFrame( $frame)
Return a string representation of frame.
Definition: GlobalFunctions.php:2020
$last
$last
Definition: profileinfo.php:365
wfGetDB
& wfGetDB( $db, $groups=array(), $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3714
wfRemoveDotSegments
wfRemoveDotSegments( $urlPath)
Remove all dot-segments in the provided URL path.
Definition: GlobalFunctions.php:664
wfSetBit
wfSetBit(&$dest, $bit, $state=true)
As for wfSetVar except setting a bit.
Definition: GlobalFunctions.php:2203
$timestamp
if( $limit) $timestamp
Definition: importImages.php:104
$f
$f
Definition: UtfNormalTest2.php:38
wfEmptyMsg
wfEmptyMsg( $key)
Since wfMsg() and co suck, they don't return false if the message key they looked up didn't exist but...
Definition: GlobalFunctions.php:1807
wfNegotiateType
wfNegotiateType( $cprefs, $sprefs)
Returns the 'best' match between a client's requested internet media types and the server's list of a...
Definition: GlobalFunctions.php:2393
wfMakeUrlIndexes
wfMakeUrlIndexes( $url)
Make URL indexes, appropriate for the el_index field of externallinks.
Definition: GlobalFunctions.php:895
Fallback\mb_substr_split_unicode
static mb_substr_split_unicode( $str, $splitPos)
Definition: Fallback.php:85
wfTime
wfTime()
Get the current unix timestamp with microseconds.
Definition: GlobalFunctions.php:2171
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
SiteStats\pages
static pages()
Definition: SiteStats.php:132
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all')
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:1087
wfUnpack
wfUnpack( $format, $data, $length=false)
Wrapper around php's unpack.
Definition: GlobalFunctions.php:4084
wfProfileIn
wfProfileIn( $functionname)
Begin profiling of a function.
Definition: Profiler.php:33
$n
$n
Definition: RandomTest.php:76
wfObjectToArray
wfObjectToArray( $objOrArray, $recursive=true)
Recursively converts the parameter (an object) to an array with the same data.
Definition: GlobalFunctions.php:305
$ret
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1530
MWDebug\debugMsg
static debugMsg( $str)
This is a method to pass messages from wfDebug to the pretty debugger.
Definition: Debug.php:316
wfSuppressWarnings
wfSuppressWarnings( $end=false)
Reference-counted warning suppression.
Definition: GlobalFunctions.php:2434
$from
$from
Definition: importImages.php:90
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:377
wfArrayDiff2_cmp
wfArrayDiff2_cmp( $a, $b)
Definition: GlobalFunctions.php:169
wfGetScriptUrl
wfGetScriptUrl()
Get the script URL.
Definition: GlobalFunctions.php:3810
Fallback\mb_strpos
static mb_strpos( $haystack, $needle, $offset=0, $encoding='')
Fallback implementation of mb_strpos, hardcoded to UTF-8.
Definition: Fallback.php:160
$time
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1358
wfArrayDiff2
if(!defined( 'MEDIAWIKI')) wfArrayDiff2( $a, $b)
Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
Definition: GlobalFunctions.php:160
wfBaseName
wfBaseName( $path, $suffix='')
Return the final portion of a pathname.
Definition: GlobalFunctions.php:3357
wfQueriesMustScale
wfQueriesMustScale()
Should low-performance queries be disabled?
Definition: GlobalFunctions.php:3778
NS_FILE
const NS_FILE
Definition: Defines.php:85
$params
$params
Definition: styleTest.css.php:40
$limit
if( $sleep) $limit
Definition: importImages.php:99
wfHostname
wfHostname()
Fetch server name for use in error reporting etc.
Definition: GlobalFunctions.php:1833
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1360
wfMsgReplaceArgs
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
Definition: GlobalFunctions.php:1637
wfShellExecWithStderr
wfShellExecWithStderr( $cmd, &$retval=null, $environ=array(), $limits=array())
Execute a shell command, returning both stdout and stderr.
Definition: GlobalFunctions.php:3084
wfUsePHP
wfUsePHP( $req_ver)
This function works like "use VERSION" in Perl, the program will die with a backtrace if the current ...
Definition: GlobalFunctions.php:3307
wfGetCache
wfGetCache( $inputType)
Get a cache object.
Definition: GlobalFunctions.php:4013
wfIsConfiguredProxy
wfIsConfiguredProxy( $ip)
Checks if an IP matches a proxy we've configured.
Definition: GlobalFunctions.php:4234
wfSplitWikiID
wfSplitWikiID( $wiki)
Split a wiki ID into DB name and table prefix.
Definition: GlobalFunctions.php:3684
$s
$s
Definition: mergeMessageFileList.php:156
TS_DB
const TS_DB
MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
Definition: GlobalFunctions.php:2483
wfArrayMerge
wfArrayMerge( $array1)
Backwards array plus for people who haven't bothered to read the PHP manual XXX: will not darn your s...
Definition: GlobalFunctions.php:230
MWCryptRand\generateHex
static generateHex( $chars, $forceStrong=false)
Generate a run of (ideally) cryptographically random data and return it in hexadecimal string format.
Definition: MWCryptRand.php:514
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1201
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
$link
set to $title object and return false for a match for latest after cache objects are set use the ContentHandler facility to handle CSS and JavaScript for highlighting & $link
Definition: hooks.txt:2160
wfExpandIRI
wfExpandIRI( $url)
Take a URL, make sure it's expanded to fully qualified, and replace any encoded non-ASCII Unicode cha...
Definition: GlobalFunctions.php:872
wfMessageFallback
wfMessageFallback()
This function accepts multiple message keys and returns a message instance for the first message whic...
Definition: GlobalFunctions.php:1469
wfArrayLookup
wfArrayLookup( $a, $b)
Array lookup Returns an array where the values in array $b are replaced by the values in array $a wit...
Definition: GlobalFunctions.php:197
wfMsgReal
wfMsgReal( $key, $args, $useDB=true, $forContent=false, $transform=true)
Really get a message.
Definition: GlobalFunctions.php:1592
wfBoolToStr
wfBoolToStr( $value)
Convenience function converts boolean values into "true" or "false" (string) values.
Definition: GlobalFunctions.php:3835
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:506
wfBacktrace
wfBacktrace()
Get a debug backtrace as a string.
Definition: GlobalFunctions.php:1933
wfParseUrl
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
Definition: GlobalFunctions.php:802
$lb
if( $wgAPIRequestLog) $lb
Definition: api.php:126
wfGetMainCache
wfGetMainCache()
Get the main cache object.
Definition: GlobalFunctions.php:4022
MWException
MediaWiki exception.
Definition: MWException.php:26
wfStripIllegalFilenameChars
wfStripIllegalFilenameChars( $name)
Replace all invalid characters with - Additional characters can be defined in $wgIllegalFileChars (se...
Definition: GlobalFunctions.php:3908
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3635
$out
$out
Definition: UtfNormalGenerate.php:167
mimeTypeMatch
mimeTypeMatch( $type, $avail)
Checks if a given MIME type matches any of the keys in the given array.
Definition: GlobalFunctions.php:2365
wfMsgHtml
wfMsgHtml( $key)
Return an HTML-escaped version of a message.
Definition: GlobalFunctions.php:1670
$wgDBname
controlled by $wgMainCacheType controlled by $wgParserCacheType controlled by $wgMessageCacheType If you set CACHE_NONE to one of the three control default value for MediaWiki still create a but requests to it are no ops and we always fall through to the database If the cache daemon can t be it should also disable itself fairly smoothly By $wgMemc is used but when it is $parserMemc or $messageMemc this is mentioned $wgDBname
Definition: memcached.txt:96
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1174
wfRestoreWarnings
wfRestoreWarnings()
Restore error level to previous value.
Definition: GlobalFunctions.php:2464
Language\fetchLanguageNames
static fetchLanguageNames( $inLanguage=null, $include='mw')
Get an array of language names, indexed by code.
Definition: Language.php:875
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:3794
wfIncrStats
wfIncrStats( $key, $count=1)
Increment a statistics counter.
Definition: GlobalFunctions.php:1351
FileBackend\isStoragePath
static isStoragePath( $path)
Check if a given path is a "mwstore://" path.
Definition: FileBackend.php:1330
$blob
$blob
Definition: testCompression.php:61
$wgCommandLineMode
global $wgCommandLineMode
Definition: Setup.php:408
wfShellExecDisabled
wfShellExecDisabled()
Check if wfShellExec() is effectively disabled via php.ini config.
Definition: GlobalFunctions.php:2813
wfUrlProtocolsWithoutProtRel
wfUrlProtocolsWithoutProtRel()
Like wfUrlProtocols(), but excludes '//' from the protocol list.
Definition: GlobalFunctions.php:787
$wgRequestTime
$wgRequestTime
Definition: WebStart.php:72
wfDebugDieBacktrace
wfDebugDieBacktrace( $msg='')
Throw a debugging exception.
Definition: GlobalFunctions.php:1821
wfTimestampOrNull
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
Definition: GlobalFunctions.php:2548
SHELL_MAX_ARG_STRLEN
const SHELL_MAX_ARG_STRLEN
Definition: Defines.php:317
swap
swap(&$x, &$y)
Swap two variables.
Definition: GlobalFunctions.php:2594
wfProfileOut
wfProfileOut( $functionname='missing')
Stop profiling of a function.
Definition: Profiler.php:46
$wgOut
$wgOut
Definition: Setup.php:582
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:270
wfMsgWikiHtml
wfMsgWikiHtml( $key)
Return an HTML version of message Parameter replacements, if any, are done after parsing the wiki-tex...
Definition: GlobalFunctions.php:1691
ObjectCache\getInstance
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:39
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4066
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1399
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:459
$lines
$lines
Definition: router.php:65
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
MWDebug\deprecated
static deprecated( $function, $version=false, $component=false, $callerOffset=2)
Show a warning that $function is deprecated.
Definition: Debug.php:187
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
IP\isInRange
static isInRange( $addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
Definition: IP.php:717
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:2561
wfMemoryLimit
wfMemoryLimit()
Set PHP's memory limit to the larger of php.ini or $wgMemoryLimit;.
Definition: GlobalFunctions.php:3925
wfWaitForSlaves
wfWaitForSlaves( $maxLag=false, $wiki=false, $cluster=false)
Modern version of wfWaitForSlaves().
Definition: GlobalFunctions.php:3859
wfForeignMemcKey
wfForeignMemcKey( $db, $prefix)
Get a cache key for a foreign DB.
Definition: GlobalFunctions.php:3652
wfAcceptToPrefs
wfAcceptToPrefs( $accept, $def=' */*')
Converts an Accept-* header into an array mapping string values to quality factors.
Definition: GlobalFunctions.php:2329
list
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
wfExpandIRI_callback
wfExpandIRI_callback( $matches)
Private callback for wfExpandIRI.
Definition: GlobalFunctions.php:885
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:188
MessageCache\singleton
static singleton()
Get the signleton instance of this class.
Definition: MessageCache.php:101
wfIsDebugRawPage
wfIsDebugRawPage()
Returns true if debug logging should be suppressed if $wgDebugRawPage = false.
Definition: GlobalFunctions.php:1016
UnifiedDiffFormatter
A formatter that outputs unified diffs.
Definition: UnifiedDiffFormatter.php:31
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:1530
wfDebugTimer
wfDebugTimer()
Get microsecond timestamps for debug logs.
Definition: GlobalFunctions.php:1040
$ok
$ok
Definition: UtfNormalTest.php:71
wfShellWikiCmd
wfShellWikiCmd( $script, array $parameters=array(), array $options=array())
Generate a shell-escaped command line string to run a MediaWiki cli script.
Definition: GlobalFunctions.php:3126
wfUrlProtocols
wfUrlProtocols( $includeProtocolRelative=true)
Returns a regular expression of url protocols.
Definition: GlobalFunctions.php:742
$line
$line
Definition: cdb.php:57
wfIsBadImage
wfIsBadImage( $name, $contextTitle=false, $blacklist=null)
Determine if an image exists on the 'bad image list'.
Definition: GlobalFunctions.php:4120
TS_MW
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
Definition: GlobalFunctions.php:2478
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
wfWikiID
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
Definition: GlobalFunctions.php:3668
$title
presenting them properly to the user as errors is done by the caller $title
Definition: hooks.txt:1324
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:336
wfClearOutputBuffers
wfClearOutputBuffers()
More legible than passing a 'false' parameter to wfResetOutputBuffers():
Definition: GlobalFunctions.php:2317
$matches
if(!defined( 'MEDIAWIKI')) if(!isset( $wgVersion)) $matches
Definition: NoLocalSettings.php:33
$size
$size
Definition: RandomTest.php:75
$value
$value
Definition: styleTest.css.php:45
wfClientAcceptsGzip
wfClientAcceptsGzip( $force=false)
Definition: GlobalFunctions.php:2076
wfLogDBError
wfLogDBError( $text)
Log for database errors.
Definition: GlobalFunctions.php:1134
ObjectCacheSessionHandler\install
static install()
Install a session handler for the current web request.
Definition: ObjectCacheSessionHandler.php:34
Fallback\mb_strlen
static mb_strlen( $str, $enc='')
Fallback implementation of mb_strlen, hardcoded to UTF-8.
Definition: Fallback.php:136
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:2571
wfEscapeShellArg
wfEscapeShellArg()
Windows-compatible version of escapeshellarg() Windows doesn't recognise single-quotes in the shell,...
Definition: GlobalFunctions.php:2752
wfDebugMem
wfDebugMem( $exact=false)
Send a line giving PHP memory usage.
Definition: GlobalFunctions.php:1057
wfInitShellLocale
wfInitShellLocale()
Workaround for http://bugs.php.net/bug.php?id=45132 escapeshellarg() destroys non-ASCII characters if...
Definition: GlobalFunctions.php:3092
PROTO_HTTP
const PROTO_HTTP
Definition: Defines.php:267
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:2124
$version
$version
Definition: parserTests.php:86
Skin\makeVariablesScript
static makeVariablesScript( $data)
Definition: Skin.php:398
wfAppendToArrayIfNotDefault
wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed)
Appends to second array if $value differs from that in $default.
Definition: GlobalFunctions.php:211
wfVarDump
wfVarDump( $var)
A wrapper around the PHP function var_export().
Definition: GlobalFunctions.php:2221
wfGetParserCacheStorage
wfGetParserCacheStorage()
Get the cache object used by the parser cache.
Definition: GlobalFunctions.php:4042
wfMsgExt
wfMsgExt( $key, $options)
Returns message in the requested format.
Definition: GlobalFunctions.php:1725
wfGetNull
wfGetNull()
Get a platform-independent path to the null file, e.g.
Definition: GlobalFunctions.php:3844
TimestampException
Definition: TimestampException.php:6
$exceptions
$exceptions
Definition: Utf8Test.php:72
Hooks\run
static run( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:136
wfIniGetBool
wfIniGetBool( $setting)
Safety wrapper around ini_get() for boolean settings.
Definition: GlobalFunctions.php:2732
wfIsTrustedProxy
wfIsTrustedProxy( $ip)
Checks if an IP is a trusted proxy provider.
Definition: GlobalFunctions.php:4221
wfMsgGetKey
wfMsgGetKey( $key, $useDB=true, $langCode=false, $transform=true)
Fetch a message string value, but don't replace any keys yet.
Definition: GlobalFunctions.php:1614
IP\isIPv4
static isIPv4( $ip)
Given a string, determine if it as valid IP in IPv4 only.
Definition: IP.php:96
wfReportTime
wfReportTime()
Returns a script tag that stores the amount of time it took MediaWiki to handle the request in millis...
Definition: GlobalFunctions.php:1873
wfGetAllCallers
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
Definition: GlobalFunctions.php:2005
$file
if(PHP_SAPI !='cli') $file
Definition: UtfNormalTest2.php:30
$count
$count
Definition: UtfNormalTest2.php:96
wfGetMessageCacheStorage
wfGetMessageCacheStorage()
Get the cache object used by the message cache.
Definition: GlobalFunctions.php:4032
$args
if( $line===false) $args
Definition: cdb.php:62
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:3954
Fallback\mb_strrpos
static mb_strrpos( $haystack, $needle, $offset=0, $encoding='')
Fallback implementation of mb_strrpos, hardcoded to UTF-8.
Definition: Fallback.php:181
$wgLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as $wgLang
Definition: design.txt:56
wfRandom
wfRandom()
Get a random decimal value between 0 and 1, in a way not likely to give duplicate values for any real...
Definition: GlobalFunctions.php:328
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:2611
wfGetLangConverterCacheStorage
wfGetLangConverterCacheStorage()
Get the cache object used by the language converter.
Definition: GlobalFunctions.php:4052
wfHttpError
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
Definition: GlobalFunctions.php:2238
wfReadOnlyReason
wfReadOnlyReason()
Get the value of $wgReadOnly or the contents of $wgReadOnlyFile.
Definition: GlobalFunctions.php:1369
wfGetLBFactory
& wfGetLBFactory()
Get the load balancer factory object.
Definition: GlobalFunctions.php:3733
wfMatchesDomainList
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
Definition: GlobalFunctions.php:949
$cache
$cache
Definition: mcc.php:32
$dir
if(count( $args)==0) $dir
Definition: importImages.php:49
wfGetPrecompiledData
wfGetPrecompiledData( $name)
Get an object from the precompiled serialized directory.
Definition: GlobalFunctions.php:3616
wfBaseConvert
wfBaseConvert( $input, $sourceBase, $destBase, $pad=1, $lowercase=true, $engine='auto')
Convert an arbitrarily-long digit string from one numeric base to another, optionally zero-padding to...
Definition: GlobalFunctions.php:3432
wfRecursiveRemoveDir
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
Definition: GlobalFunctions.php:2679
wfCheckEntropy
wfCheckEntropy()
Check if there is sufficient entropy in php's built-in session generation.
Definition: GlobalFunctions.php:3528
TS_UNIX
const TS_UNIX
Unix time - the number of seconds since 1970-01-01 00:00:00 UTC.
Definition: GlobalFunctions.php:2473
$output
& $output
Definition: hooks.txt:375
$path
$path
Definition: NoLocalSettings.php:35
$wgMainCacheType
CACHE_MEMCACHED $wgMainCacheType
Definition: memcached.txt:63
as
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
wfFindFile
wfFindFile( $title, $options=array())
Find a file.
Definition: GlobalFunctions.php:3757
$keys
$keys
Definition: testCompression.php:63
wfViewPrevNext
wfViewPrevNext( $offset, $limit, $link, $query='', $atend=false)
Generate (prev x| next x) (20|50|100...) type links for paging.
Definition: GlobalFunctions.php:2050
$source
if(PHP_SAPI !='cli') $source
Definition: mwdoc-filter.php:18
wfAssembleUrl
wfAssembleUrl( $urlParts)
This function will reassemble a URL parsed with wfParseURL.
Definition: GlobalFunctions.php:612
wfRelativePath
wfRelativePath( $path, $from)
Generate a relative path name to the given file.
Definition: GlobalFunctions.php:3381
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:184
wfWarn
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
Definition: GlobalFunctions.php:1188
Title\legalChars
static legalChars()
Get a regex character class describing the legal characters in a link.
Definition: Title.php:529
MWDebug\warning
static warning( $msg, $callerOffset=1, $level=E_USER_NOTICE, $log='auto')
Adds a warning entry to the log.
Definition: Debug.php:144
$error
usually copyright or history_copyright This message must be in HTML not wikitext $subpages will be ignored and the rest of subPageSubtitle() will run. 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink' whether MediaWiki currently thinks this is a CSS JS page Hooks may change this value to override the return value of Title::isCssOrJsPage(). 'TitleIsAlwaysKnown' whether MediaWiki currently thinks this page is known isMovable() always returns false. $title whether MediaWiki currently thinks this page is movable Hooks may change this value to override the return value of Title::isMovable(). 'TitleIsWikitextPage' whether MediaWiki currently thinks this is a wikitext page Hooks may change this value to override the return value of Title::isWikitextPage() 'TitleMove' use UploadVerification and UploadVerifyFile instead where the first element is the message key and the remaining elements are used as parameters to the message based on mime etc Preferred in most cases over UploadVerification object with all info about the upload string as detected by MediaWiki Handlers will typically only apply for specific mime types object & $error
Definition: hooks.txt:2584
$query
return true to allow those checks to and false if checking is done use this to change the tables headers temp or archived zone change it to an object instance and return false override the list derivative used the name of the old file when set the default code will be skipped add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1105
wfIsHHVM
wfIsHHVM()
Check if we are running under HHVM.
Definition: GlobalFunctions.php:2584
$IP
$IP
Definition: WebStart.php:92
wfLocalFile
wfLocalFile( $title)
Get an object referring to a locally registered file.
Definition: GlobalFunctions.php:3768
wfShowingResults
wfShowingResults( $offset, $limit)
Definition: GlobalFunctions.php:2035
wfResetSessionID
wfResetSessionID()
Reset the session_id.
Definition: GlobalFunctions.php:3566
$retval
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account incomplete not yet checked for validity & $retval
Definition: hooks.txt:237
wfGetCaller
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
Definition: GlobalFunctions.php:1988
Fallback\iconv
static iconv( $from, $to, $string)
Definition: Fallback.php:34
wfMsg
wfMsg( $key)
Get a message from anywhere, for the current user language.
Definition: GlobalFunctions.php:1493
SiteStats\edits
static edits()
Definition: SiteStats.php:116
Fallback\mb_substr
static mb_substr( $str, $start, $count='end')
Fallback implementation for mb_substr, hardcoded to UTF-8.
Definition: Fallback.php:66
Sanitizer\escapeHtmlAllowEntities
static escapeHtmlAllowEntities( $html)
Given HTML input, escape with htmlspecialchars but un-escape entities.
Definition: Sanitizer.php:1158
wfMsgForContentNoTrans
wfMsgForContentNoTrans( $key)
Same as above except doesn't transform the message.
Definition: GlobalFunctions.php:1565
wfCountDown
wfCountDown( $seconds)
Count down from $seconds to zero on the terminal, with a one-second pause between showing each number...
Definition: GlobalFunctions.php:3886
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:544
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:1632
wfLogProfilingData
wfLogProfilingData()
Definition: GlobalFunctions.php:1273
$changed
$changed
Definition: UtfNormalGenerate.php:130
Diff
Class representing a 'diff' between two sequences of strings.
Definition: DairikiDiff.php:705
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes two arrays as input, and returns a CGI-style string, e.g.
Definition: GlobalFunctions.php:414
wfRandomString
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Definition: GlobalFunctions.php:347
$type
$type
Definition: testCompression.php:46