MediaWiki  1.23.12
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 
38 if ( !function_exists( 'iconv' ) ) {
43  function iconv( $from, $to, $string ) {
44  return Fallback::iconv( $from, $to, $string );
45  }
46 }
47 
48 if ( !function_exists( 'mb_substr' ) ) {
53  function mb_substr( $str, $start, $count = 'end' ) {
54  return Fallback::mb_substr( $str, $start, $count );
55  }
56 
61  function mb_substr_split_unicode( $str, $splitPos ) {
62  return Fallback::mb_substr_split_unicode( $str, $splitPos );
63  }
64 }
65 
66 if ( !function_exists( 'mb_strlen' ) ) {
71  function mb_strlen( $str, $enc = '' ) {
72  return Fallback::mb_strlen( $str, $enc );
73  }
74 }
75 
76 if ( !function_exists( 'mb_strpos' ) ) {
81  function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
82  return Fallback::mb_strpos( $haystack, $needle, $offset, $encoding );
83  }
84 }
85 
86 if ( !function_exists( 'mb_strrpos' ) ) {
91  function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
92  return Fallback::mb_strrpos( $haystack, $needle, $offset, $encoding );
93  }
94 }
95 
96 // gzdecode function only exists in PHP >= 5.4.0
97 // http://php.net/gzdecode
98 if ( !function_exists( 'gzdecode' ) ) {
103  function gzdecode( $data ) {
104  return gzinflate( substr( $data, 10, -8 ) );
105  }
106 }
107 
108 // hash_equals function only exists in PHP >= 5.6.0
109 if ( !function_exists( 'hash_equals' ) ) {
125  function hash_equals( $known_string, $user_string ) {
126  // Strict type checking as in PHP's native implementation
127  if ( !is_string( $known_string ) ) {
128  trigger_error( 'hash_equals(): Expected known_string to be a string, ' .
129  gettype( $known_string ) . ' given', E_USER_WARNING );
130 
131  return false;
132  }
133 
134  if ( !is_string( $user_string ) ) {
135  trigger_error( 'hash_equals(): Expected user_string to be a string, ' .
136  gettype( $user_string ) . ' given', E_USER_WARNING );
137 
138  return false;
139  }
140 
141  // Note that we do one thing PHP doesn't: try to avoid leaking information about
142  // relative lengths of $known_string and $user_string, and of multiple $known_strings.
143  // However, lengths may still inevitably leak through, for example, CPU cache misses.
144  $known_string_len = strlen( $known_string );
145  $user_string_len = strlen( $user_string );
146  $result = $known_string_len ^ $user_string_len;
147  for ( $i = 0; $i < $user_string_len; $i++ ) {
148  $result |= ord( $known_string[$i % $known_string_len] ) ^ ord( $user_string[$i] );
149  }
150 
151  return ( $result === 0 );
152  }
153 }
155 
162 function wfArrayDiff2( $a, $b ) {
163  return array_udiff( $a, $b, 'wfArrayDiff2_cmp' );
164 }
165 
171 function wfArrayDiff2_cmp( $a, $b ) {
172  if ( is_string( $a ) && is_string( $b ) ) {
173  return strcmp( $a, $b );
174  } elseif ( count( $a ) !== count( $b ) ) {
175  return count( $a ) < count( $b ) ? -1 : 1;
176  } else {
177  reset( $a );
178  reset( $b );
179  while ( ( list( , $valueA ) = each( $a ) ) && ( list( , $valueB ) = each( $b ) ) ) {
180  $cmp = strcmp( $valueA, $valueB );
181  if ( $cmp !== 0 ) {
182  return $cmp;
183  }
184  }
185  return 0;
186  }
187 }
188 
199 function wfArrayLookup( $a, $b ) {
200  wfDeprecated( __FUNCTION__, '1.22' );
201  return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) );
202 }
203 
213 function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
214  if ( is_null( $changed ) ) {
215  throw new MWException( 'GlobalFunctions::wfAppendToArrayIfNotDefault got null' );
216  }
217  if ( $default[$key] !== $value ) {
218  $changed[$key] = $value;
219  }
220 }
221 
232 function wfArrayMerge( $array1 /*...*/ ) {
233  wfDeprecated( __FUNCTION__, '1.22' );
234  $args = func_get_args();
235  $args = array_reverse( $args, true );
236  $out = array();
237  foreach ( $args as $arg ) {
238  $out += $arg;
239  }
240  return $out;
241 }
242 
262 function wfMergeErrorArrays( /*...*/ ) {
263  $args = func_get_args();
264  $out = array();
265  foreach ( $args as $errors ) {
266  foreach ( $errors as $params ) {
267  # @todo FIXME: Sometimes get nested arrays for $params,
268  # which leads to E_NOTICEs
269  $spec = implode( "\t", $params );
270  $out[$spec] = $params;
271  }
272  }
273  return array_values( $out );
274 }
275 
284 function wfArrayInsertAfter( array $array, array $insert, $after ) {
285  // Find the offset of the element to insert after.
286  $keys = array_keys( $array );
287  $offsetByKey = array_flip( $keys );
288 
289  $offset = $offsetByKey[$after];
290 
291  // Insert at the specified offset
292  $before = array_slice( $array, 0, $offset + 1, true );
293  $after = array_slice( $array, $offset + 1, count( $array ) - $offset, true );
294 
295  $output = $before + $insert + $after;
296 
297  return $output;
298 }
299 
307 function wfObjectToArray( $objOrArray, $recursive = true ) {
308  $array = array();
309  if ( is_object( $objOrArray ) ) {
310  $objOrArray = get_object_vars( $objOrArray );
311  }
312  foreach ( $objOrArray as $key => $value ) {
313  if ( $recursive && ( is_object( $value ) || is_array( $value ) ) ) {
315  }
316 
317  $array[$key] = $value;
318  }
319 
320  return $array;
321 }
322 
330 function wfRandom() {
331  # The maximum random value is "only" 2^31-1, so get two random
332  # values to reduce the chance of dupes
333  $max = mt_getrandmax() + 1;
334  $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12, '.', '' );
335 
336  return $rand;
337 }
338 
349 function wfRandomString( $length = 32 ) {
350  $str = '';
351  for ( $n = 0; $n < $length; $n += 7 ) {
352  $str .= sprintf( '%07x', mt_rand() & 0xfffffff );
353  }
354  return substr( $str, 0, $length );
355 }
356 
379 function wfUrlencode( $s ) {
380  static $needle;
381 
382  if ( is_null( $s ) ) {
383  $needle = null;
384  return '';
385  }
386 
387  if ( is_null( $needle ) ) {
388  $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
389  if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
390  ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
391  ) {
392  $needle[] = '%3A';
393  }
394  }
395 
396  $s = urlencode( $s );
397  $s = str_ireplace(
398  $needle,
399  array( ';', '@', '$', '!', '*', '(', ')', ',', '/', ':' ),
400  $s
401  );
402 
403  return $s;
404 }
405 
416 function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
417  if ( !is_null( $array2 ) ) {
418  $array1 = $array1 + $array2;
419  }
420 
421  $cgi = '';
422  foreach ( $array1 as $key => $value ) {
423  if ( !is_null( $value ) && $value !== false ) {
424  if ( $cgi != '' ) {
425  $cgi .= '&';
426  }
427  if ( $prefix !== '' ) {
428  $key = $prefix . "[$key]";
429  }
430  if ( is_array( $value ) ) {
431  $firstTime = true;
432  foreach ( $value as $k => $v ) {
433  $cgi .= $firstTime ? '' : '&';
434  if ( is_array( $v ) ) {
435  $cgi .= wfArrayToCgi( $v, null, $key . "[$k]" );
436  } else {
437  $cgi .= urlencode( $key . "[$k]" ) . '=' . urlencode( $v );
438  }
439  $firstTime = false;
440  }
441  } else {
442  if ( is_object( $value ) ) {
443  $value = $value->__toString();
444  }
445  $cgi .= urlencode( $key ) . '=' . urlencode( $value );
446  }
447  }
448  }
449  return $cgi;
450 }
451 
461 function wfCgiToArray( $query ) {
462  if ( isset( $query[0] ) && $query[0] == '?' ) {
463  $query = substr( $query, 1 );
464  }
465  $bits = explode( '&', $query );
466  $ret = array();
467  foreach ( $bits as $bit ) {
468  if ( $bit === '' ) {
469  continue;
470  }
471  if ( strpos( $bit, '=' ) === false ) {
472  // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does)
473  $key = $bit;
474  $value = '';
475  } else {
476  list( $key, $value ) = explode( '=', $bit );
477  }
478  $key = urldecode( $key );
479  $value = urldecode( $value );
480  if ( strpos( $key, '[' ) !== false ) {
481  $keys = array_reverse( explode( '[', $key ) );
482  $key = array_pop( $keys );
483  $temp = $value;
484  foreach ( $keys as $k ) {
485  $k = substr( $k, 0, -1 );
486  $temp = array( $k => $temp );
487  }
488  if ( isset( $ret[$key] ) ) {
489  $ret[$key] = array_merge( $ret[$key], $temp );
490  } else {
491  $ret[$key] = $temp;
492  }
493  } else {
494  $ret[$key] = $value;
495  }
496  }
497  return $ret;
498 }
499 
508 function wfAppendQuery( $url, $query ) {
509  if ( is_array( $query ) ) {
511  }
512  if ( $query != '' ) {
513  if ( false === strpos( $url, '?' ) ) {
514  $url .= '?';
515  } else {
516  $url .= '&';
517  }
518  $url .= $query;
519  }
520  return $url;
521 }
522 
546 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
547  global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest;
548  if ( $defaultProto === PROTO_CANONICAL ) {
549  $serverUrl = $wgCanonicalServer;
550  } elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
551  // Make $wgInternalServer fall back to $wgServer if not set
552  $serverUrl = $wgInternalServer;
553  } else {
554  $serverUrl = $wgServer;
555  if ( $defaultProto === PROTO_CURRENT ) {
556  $defaultProto = $wgRequest->getProtocol() . '://';
557  }
558  }
559 
560  // Analyze $serverUrl to obtain its protocol
561  $bits = wfParseUrl( $serverUrl );
562  $serverHasProto = $bits && $bits['scheme'] != '';
563 
564  if ( $defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL ) {
565  if ( $serverHasProto ) {
566  $defaultProto = $bits['scheme'] . '://';
567  } else {
568  // $wgCanonicalServer or $wgInternalServer doesn't have a protocol.
569  // This really isn't supposed to happen. Fall back to HTTP in this
570  // ridiculous case.
571  $defaultProto = PROTO_HTTP;
572  }
573  }
574 
575  $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 );
576 
577  if ( substr( $url, 0, 2 ) == '//' ) {
578  $url = $defaultProtoWithoutSlashes . $url;
579  } elseif ( substr( $url, 0, 1 ) == '/' ) {
580  // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
581  // otherwise leave it alone.
582  $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url;
583  }
584 
585  $bits = wfParseUrl( $url );
586  if ( $bits && isset( $bits['path'] ) ) {
587  $bits['path'] = wfRemoveDotSegments( $bits['path'] );
588  return wfAssembleUrl( $bits );
589  } elseif ( $bits ) {
590  # No path to expand
591  return $url;
592  } elseif ( substr( $url, 0, 1 ) != '/' ) {
593  # URL is a relative path
594  return wfRemoveDotSegments( $url );
595  }
596 
597  # Expanded URL is not valid.
598  return false;
599 }
600 
614 function wfAssembleUrl( $urlParts ) {
615  $result = '';
616 
617  if ( isset( $urlParts['delimiter'] ) ) {
618  if ( isset( $urlParts['scheme'] ) ) {
619  $result .= $urlParts['scheme'];
620  }
621 
622  $result .= $urlParts['delimiter'];
623  }
624 
625  if ( isset( $urlParts['host'] ) ) {
626  if ( isset( $urlParts['user'] ) ) {
627  $result .= $urlParts['user'];
628  if ( isset( $urlParts['pass'] ) ) {
629  $result .= ':' . $urlParts['pass'];
630  }
631  $result .= '@';
632  }
633 
634  $result .= $urlParts['host'];
635 
636  if ( isset( $urlParts['port'] ) ) {
637  $result .= ':' . $urlParts['port'];
638  }
639  }
640 
641  if ( isset( $urlParts['path'] ) ) {
642  $result .= $urlParts['path'];
643  }
644 
645  if ( isset( $urlParts['query'] ) ) {
646  $result .= '?' . $urlParts['query'];
647  }
648 
649  if ( isset( $urlParts['fragment'] ) ) {
650  $result .= '#' . $urlParts['fragment'];
651  }
652 
653  return $result;
654 }
655 
666 function wfRemoveDotSegments( $urlPath ) {
667  $output = '';
668  $inputOffset = 0;
669  $inputLength = strlen( $urlPath );
670 
671  while ( $inputOffset < $inputLength ) {
672  $prefixLengthOne = substr( $urlPath, $inputOffset, 1 );
673  $prefixLengthTwo = substr( $urlPath, $inputOffset, 2 );
674  $prefixLengthThree = substr( $urlPath, $inputOffset, 3 );
675  $prefixLengthFour = substr( $urlPath, $inputOffset, 4 );
676  $trimOutput = false;
677 
678  if ( $prefixLengthTwo == './' ) {
679  # Step A, remove leading "./"
680  $inputOffset += 2;
681  } elseif ( $prefixLengthThree == '../' ) {
682  # Step A, remove leading "../"
683  $inputOffset += 3;
684  } elseif ( ( $prefixLengthTwo == '/.' ) && ( $inputOffset + 2 == $inputLength ) ) {
685  # Step B, replace leading "/.$" with "/"
686  $inputOffset += 1;
687  $urlPath[$inputOffset] = '/';
688  } elseif ( $prefixLengthThree == '/./' ) {
689  # Step B, replace leading "/./" with "/"
690  $inputOffset += 2;
691  } elseif ( $prefixLengthThree == '/..' && ( $inputOffset + 3 == $inputLength ) ) {
692  # Step C, replace leading "/..$" with "/" and
693  # remove last path component in output
694  $inputOffset += 2;
695  $urlPath[$inputOffset] = '/';
696  $trimOutput = true;
697  } elseif ( $prefixLengthFour == '/../' ) {
698  # Step C, replace leading "/../" with "/" and
699  # remove last path component in output
700  $inputOffset += 3;
701  $trimOutput = true;
702  } elseif ( ( $prefixLengthOne == '.' ) && ( $inputOffset + 1 == $inputLength ) ) {
703  # Step D, remove "^.$"
704  $inputOffset += 1;
705  } elseif ( ( $prefixLengthTwo == '..' ) && ( $inputOffset + 2 == $inputLength ) ) {
706  # Step D, remove "^..$"
707  $inputOffset += 2;
708  } else {
709  # Step E, move leading path segment to output
710  if ( $prefixLengthOne == '/' ) {
711  $slashPos = strpos( $urlPath, '/', $inputOffset + 1 );
712  } else {
713  $slashPos = strpos( $urlPath, '/', $inputOffset );
714  }
715  if ( $slashPos === false ) {
716  $output .= substr( $urlPath, $inputOffset );
717  $inputOffset = $inputLength;
718  } else {
719  $output .= substr( $urlPath, $inputOffset, $slashPos - $inputOffset );
720  $inputOffset += $slashPos - $inputOffset;
721  }
722  }
723 
724  if ( $trimOutput ) {
725  $slashPos = strrpos( $output, '/' );
726  if ( $slashPos === false ) {
727  $output = '';
728  } else {
729  $output = substr( $output, 0, $slashPos );
730  }
731  }
732  }
733 
734  return $output;
735 }
736 
744 function wfUrlProtocols( $includeProtocolRelative = true ) {
745  global $wgUrlProtocols;
746 
747  // Cache return values separately based on $includeProtocolRelative
748  static $withProtRel = null, $withoutProtRel = null;
749  $cachedValue = $includeProtocolRelative ? $withProtRel : $withoutProtRel;
750  if ( !is_null( $cachedValue ) ) {
751  return $cachedValue;
752  }
753 
754  // Support old-style $wgUrlProtocols strings, for backwards compatibility
755  // with LocalSettings files from 1.5
756  if ( is_array( $wgUrlProtocols ) ) {
757  $protocols = array();
758  foreach ( $wgUrlProtocols as $protocol ) {
759  // Filter out '//' if !$includeProtocolRelative
760  if ( $includeProtocolRelative || $protocol !== '//' ) {
761  $protocols[] = preg_quote( $protocol, '/' );
762  }
763  }
764 
765  $retval = implode( '|', $protocols );
766  } else {
767  // Ignore $includeProtocolRelative in this case
768  // This case exists for pre-1.6 compatibility, and we can safely assume
769  // that '//' won't appear in a pre-1.6 config because protocol-relative
770  // URLs weren't supported until 1.18
771  $retval = $wgUrlProtocols;
772  }
773 
774  // Cache return value
775  if ( $includeProtocolRelative ) {
776  $withProtRel = $retval;
777  } else {
778  $withoutProtRel = $retval;
779  }
780  return $retval;
781 }
782 
789 function wfUrlProtocolsWithoutProtRel() {
790  return wfUrlProtocols( false );
791 }
792 
804 function wfParseUrl( $url ) {
805  global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
806 
807  // Protocol-relative URLs are handled really badly by parse_url(). It's so
808  // bad that the easiest way to handle them is to just prepend 'http:' and
809  // strip the protocol out later.
810  $wasRelative = substr( $url, 0, 2 ) == '//';
811  if ( $wasRelative ) {
812  $url = "http:$url";
813  }
815  $bits = parse_url( $url );
817  // parse_url() returns an array without scheme for some invalid URLs, e.g.
818  // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
819  if ( !$bits || !isset( $bits['scheme'] ) ) {
820  return false;
821  }
822 
823  // parse_url() incorrectly handles schemes case-sensitively. Convert it to lowercase.
824  $bits['scheme'] = strtolower( $bits['scheme'] );
825 
826  // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
827  if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
828  $bits['delimiter'] = '://';
829  } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
830  $bits['delimiter'] = ':';
831  // parse_url detects for news: and mailto: the host part of an url as path
832  // We have to correct this wrong detection
833  if ( isset( $bits['path'] ) ) {
834  $bits['host'] = $bits['path'];
835  $bits['path'] = '';
836  }
837  } else {
838  return false;
839  }
840 
841  /* Provide an empty host for eg. file:/// urls (see bug 28627) */
842  if ( !isset( $bits['host'] ) ) {
843  $bits['host'] = '';
844 
845  // bug 45069
846  if ( isset( $bits['path'] ) ) {
847  /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
848  if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
849  $bits['path'] = '/' . $bits['path'];
850  }
851  } else {
852  $bits['path'] = '';
853  }
854  }
855 
856  // If the URL was protocol-relative, fix scheme and delimiter
857  if ( $wasRelative ) {
858  $bits['scheme'] = '';
859  $bits['delimiter'] = '//';
860  }
861  return $bits;
862 }
863 
874 function wfExpandIRI( $url ) {
875  return preg_replace_callback(
876  '/((?:%[89A-F][0-9A-F])+)/i',
877  'wfExpandIRI_callback',
878  wfExpandUrl( $url )
879  );
880 }
881 
887 function wfExpandIRI_callback( $matches ) {
888  return urldecode( $matches[1] );
889 }
890 
897 function wfMakeUrlIndexes( $url ) {
898  $bits = wfParseUrl( $url );
899 
900  // Reverse the labels in the hostname, convert to lower case
901  // For emails reverse domainpart only
902  if ( $bits['scheme'] == 'mailto' ) {
903  $mailparts = explode( '@', $bits['host'], 2 );
904  if ( count( $mailparts ) === 2 ) {
905  $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) );
906  } else {
907  // No domain specified, don't mangle it
908  $domainpart = '';
909  }
910  $reversedHost = $domainpart . '@' . $mailparts[0];
911  } else {
912  $reversedHost = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) );
913  }
914  // Add an extra dot to the end
915  // Why? Is it in wrong place in mailto links?
916  if ( substr( $reversedHost, -1, 1 ) !== '.' ) {
917  $reversedHost .= '.';
918  }
919  // Reconstruct the pseudo-URL
920  $prot = $bits['scheme'];
921  $index = $prot . $bits['delimiter'] . $reversedHost;
922  // Leave out user and password. Add the port, path, query and fragment
923  if ( isset( $bits['port'] ) ) {
924  $index .= ':' . $bits['port'];
925  }
926  if ( isset( $bits['path'] ) ) {
927  $index .= $bits['path'];
928  } else {
929  $index .= '/';
930  }
931  if ( isset( $bits['query'] ) ) {
932  $index .= '?' . $bits['query'];
933  }
934  if ( isset( $bits['fragment'] ) ) {
935  $index .= '#' . $bits['fragment'];
936  }
937 
938  if ( $prot == '' ) {
939  return array( "http:$index", "https:$index" );
940  } else {
941  return array( $index );
942  }
943 }
944 
951 function wfMatchesDomainList( $url, $domains ) {
952  $bits = wfParseUrl( $url );
953  if ( is_array( $bits ) && isset( $bits['host'] ) ) {
954  $host = '.' . $bits['host'];
955  foreach ( (array)$domains as $domain ) {
956  $domain = '.' . $domain;
957  if ( substr( $host, -strlen( $domain ) ) === $domain ) {
958  return true;
959  }
960  }
961  }
962  return false;
963 }
964 
982 function wfDebug( $text, $dest = 'all' ) {
983  global $wgDebugLogFile, $wgDebugRawPage, $wgDebugLogPrefix;
984 
985  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
986  return;
987  }
988 
989  // Turn $dest into a string if it's a boolean (for b/c)
990  if ( $dest === true ) {
991  $dest = 'all';
992  } elseif ( $dest === false ) {
993  $dest = 'log';
994  }
995 
996  $timer = wfDebugTimer();
997  if ( $timer !== '' ) {
998  $text = preg_replace( '/[^\n]/', $timer . '\0', $text, 1 );
999  }
1000 
1001  if ( $dest === 'all' ) {
1002  MWDebug::debugMsg( $text );
1003  }
1004 
1005  if ( $wgDebugLogFile != '' ) {
1006  # Strip unprintables; they can switch terminal modes when binary data
1007  # gets dumped, which is pretty annoying.
1008  $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
1009  $text = $wgDebugLogPrefix . $text;
1010  wfErrorLog( $text, $wgDebugLogFile );
1011  }
1012 }
1013 
1018 function wfIsDebugRawPage() {
1019  static $cache;
1020  if ( $cache !== null ) {
1021  return $cache;
1022  }
1023  # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
1024  if ( ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' )
1025  || (
1026  isset( $_SERVER['SCRIPT_NAME'] )
1027  && substr( $_SERVER['SCRIPT_NAME'], -8 ) == 'load.php'
1028  )
1029  ) {
1030  $cache = true;
1031  } else {
1032  $cache = false;
1033  }
1034  return $cache;
1035 }
1036 
1042 function wfDebugTimer() {
1043  global $wgDebugTimestamps, $wgRequestTime;
1044 
1045  if ( !$wgDebugTimestamps ) {
1046  return '';
1047  }
1048 
1049  $prefix = sprintf( "%6.4f", microtime( true ) - $wgRequestTime );
1050  $mem = sprintf( "%5.1fM", ( memory_get_usage( true ) / ( 1024 * 1024 ) ) );
1051  return "$prefix $mem ";
1052 }
1053 
1059 function wfDebugMem( $exact = false ) {
1060  $mem = memory_get_usage();
1061  if ( !$exact ) {
1062  $mem = floor( $mem / 1024 ) . ' kilobytes';
1063  } else {
1064  $mem .= ' bytes';
1065  }
1066  wfDebug( "Memory usage: $mem\n" );
1067 }
1068 
1089 function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
1090  global $wgDebugLogGroups;
1091 
1092  $text = trim( $text ) . "\n";
1093 
1094  // Turn $dest into a string if it's a boolean (for b/c)
1095  if ( $dest === true ) {
1096  $dest = 'all';
1097  } elseif ( $dest === false ) {
1098  $dest = 'private';
1099  }
1100 
1101  if ( !isset( $wgDebugLogGroups[$logGroup] ) ) {
1102  if ( $dest !== 'private' ) {
1103  wfDebug( "[$logGroup] $text", $dest );
1104  }
1105  return;
1106  }
1107 
1108  if ( $dest === 'all' ) {
1109  MWDebug::debugMsg( "[$logGroup] $text" );
1110  }
1111 
1112  $logConfig = $wgDebugLogGroups[$logGroup];
1113  if ( $logConfig === false ) {
1114  return;
1115  }
1116  if ( is_array( $logConfig ) ) {
1117  if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
1118  return;
1119  }
1120  $destination = $logConfig['destination'];
1121  } else {
1122  $destination = strval( $logConfig );
1123  }
1124 
1125  $time = wfTimestamp( TS_DB );
1126  $wiki = wfWikiID();
1127  $host = wfHostname();
1128  wfErrorLog( "$time $host $wiki: $text", $destination );
1129 }
1130 
1136 function wfLogDBError( $text ) {
1137  global $wgDBerrorLog, $wgDBerrorLogTZ;
1138  static $logDBErrorTimeZoneObject = null;
1139 
1140  if ( $wgDBerrorLog ) {
1141  $host = wfHostname();
1142  $wiki = wfWikiID();
1143 
1144  if ( $wgDBerrorLogTZ && !$logDBErrorTimeZoneObject ) {
1145  $logDBErrorTimeZoneObject = new DateTimeZone( $wgDBerrorLogTZ );
1146  }
1147 
1148  // Workaround for https://bugs.php.net/bug.php?id=52063
1149  // Can be removed when min PHP > 5.3.2
1150  if ( $logDBErrorTimeZoneObject === null ) {
1151  $d = date_create( "now" );
1152  } else {
1153  $d = date_create( "now", $logDBErrorTimeZoneObject );
1154  }
1155 
1156  $date = $d->format( 'D M j G:i:s T Y' );
1157 
1158  $text = "$date\t$host\t$wiki\t" . trim( $text ) . "\n";
1159  wfErrorLog( $text, $wgDBerrorLog );
1160  }
1161 }
1162 
1176 function wfDeprecated( $function, $version = false, $component = false, $callerOffset = 2 ) {
1177  MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 );
1178 }
1179 
1190 function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
1191  MWDebug::warning( $msg, $callerOffset + 1, $level, 'auto' );
1192 }
1193 
1203 function wfLogWarning( $msg, $callerOffset = 1, $level = E_USER_WARNING ) {
1204  MWDebug::warning( $msg, $callerOffset + 1, $level, 'production' );
1205 }
1206 
1217 function wfErrorLog( $text, $file ) {
1218  if ( substr( $file, 0, 4 ) == 'udp:' ) {
1219  # Needs the sockets extension
1220  if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
1221  // IPv6 bracketed host
1222  $host = $m[2];
1223  $port = intval( $m[3] );
1224  $prefix = isset( $m[4] ) ? $m[4] : false;
1225  $domain = AF_INET6;
1226  } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
1227  $host = $m[2];
1228  if ( !IP::isIPv4( $host ) ) {
1229  $host = gethostbyname( $host );
1230  }
1231  $port = intval( $m[3] );
1232  $prefix = isset( $m[4] ) ? $m[4] : false;
1233  $domain = AF_INET;
1234  } else {
1235  throw new MWException( __METHOD__ . ': Invalid UDP specification' );
1236  }
1237 
1238  // Clean it up for the multiplexer
1239  if ( strval( $prefix ) !== '' ) {
1240  $text = preg_replace( '/^/m', $prefix . ' ', $text );
1241 
1242  // Limit to 64KB
1243  if ( strlen( $text ) > 65506 ) {
1244  $text = substr( $text, 0, 65506 );
1245  }
1246 
1247  if ( substr( $text, -1 ) != "\n" ) {
1248  $text .= "\n";
1249  }
1250  } elseif ( strlen( $text ) > 65507 ) {
1251  $text = substr( $text, 0, 65507 );
1252  }
1253 
1254  $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
1255  if ( !$sock ) {
1256  return;
1257  }
1258 
1259  socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
1260  socket_close( $sock );
1261  } else {
1263  $exists = file_exists( $file );
1264  $size = $exists ? filesize( $file ) : false;
1265  if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
1266  file_put_contents( $file, $text, FILE_APPEND );
1267  }
1269  }
1270 }
1271 
1275 function wfLogProfilingData() {
1276  global $wgRequestTime, $wgDebugLogFile, $wgDebugLogGroups, $wgDebugRawPage;
1277  global $wgProfileLimit, $wgUser, $wgRequest;
1278 
1279  StatCounter::singleton()->flush();
1280 
1281  $profiler = Profiler::instance();
1282 
1283  # Profiling must actually be enabled...
1284  if ( $profiler->isStub() ) {
1285  return;
1286  }
1287 
1288  // Get total page request time and only show pages that longer than
1289  // $wgProfileLimit time (default is 0)
1290  $elapsed = microtime( true ) - $wgRequestTime;
1291  if ( $elapsed <= $wgProfileLimit ) {
1292  return;
1293  }
1294 
1295  $profiler->logData();
1296 
1297  // Check whether this should be logged in the debug file.
1298  if ( isset( $wgDebugLogGroups['profileoutput'] )
1299  && $wgDebugLogGroups['profileoutput'] === false
1300  ) {
1301  // Explicitely disabled
1302  return;
1303  }
1304  if ( !isset( $wgDebugLogGroups['profileoutput'] ) && $wgDebugLogFile == '' ) {
1305  // Logging not enabled; no point going further
1306  return;
1307  }
1308  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
1309  return;
1310  }
1311 
1312  $forward = '';
1313  if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
1314  $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
1315  }
1316  if ( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
1317  $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP'];
1318  }
1319  if ( !empty( $_SERVER['HTTP_FROM'] ) ) {
1320  $forward .= ' from ' . $_SERVER['HTTP_FROM'];
1321  }
1322  if ( $forward ) {
1323  $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
1324  }
1325  // Don't load $wgUser at this late stage just for statistics purposes
1326  // @todo FIXME: We can detect some anons even if it is not loaded. See User::getId()
1327  if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
1328  $forward .= ' anon';
1329  }
1330 
1331  // Command line script uses a FauxRequest object which does not have
1332  // any knowledge about an URL and throw an exception instead.
1333  try {
1334  $requestUrl = $wgRequest->getRequestURL();
1335  } catch ( MWException $e ) {
1336  $requestUrl = 'n/a';
1337  }
1338 
1339  $log = sprintf( "%s\t%04.3f\t%s\n",
1340  gmdate( 'YmdHis' ), $elapsed,
1341  urldecode( $requestUrl . $forward ) );
1342 
1343  wfDebugLog( 'profileoutput', $log . $profiler->getOutput() );
1344 }
1345 
1353 function wfIncrStats( $key, $count = 1 ) {
1354  StatCounter::singleton()->incr( $key, $count );
1355 }
1356 
1362 function wfReadOnly() {
1363  return wfReadOnlyReason() !== false;
1364 }
1365 
1371 function wfReadOnlyReason() {
1372  global $wgReadOnly, $wgReadOnlyFile;
1373 
1374  if ( $wgReadOnly === null ) {
1375  // Set $wgReadOnly for faster access next time
1376  if ( is_file( $wgReadOnlyFile ) && filesize( $wgReadOnlyFile ) > 0 ) {
1377  $wgReadOnly = file_get_contents( $wgReadOnlyFile );
1378  } else {
1379  $wgReadOnly = false;
1380  }
1381  }
1382 
1383  return $wgReadOnly;
1384 }
1385 
1401 function wfGetLangObj( $langcode = false ) {
1402  # Identify which language to get or create a language object for.
1403  # Using is_object here due to Stub objects.
1404  if ( is_object( $langcode ) ) {
1405  # Great, we already have the object (hopefully)!
1406  return $langcode;
1407  }
1408 
1409  global $wgContLang, $wgLanguageCode;
1410  if ( $langcode === true || $langcode === $wgLanguageCode ) {
1411  # $langcode is the language code of the wikis content language object.
1412  # or it is a boolean and value is true
1413  return $wgContLang;
1414  }
1415 
1416  global $wgLang;
1417  if ( $langcode === false || $langcode === $wgLang->getCode() ) {
1418  # $langcode is the language code of user language object.
1419  # or it was a boolean and value is false
1420  return $wgLang;
1421  }
1422 
1423  $validCodes = array_keys( Language::fetchLanguageNames() );
1424  if ( in_array( $langcode, $validCodes ) ) {
1425  # $langcode corresponds to a valid language.
1426  return Language::factory( $langcode );
1427  }
1428 
1429  # $langcode is a string, but not a valid language code; use content language.
1430  wfDebug( "Invalid language code passed to wfGetLangObj, falling back to content language.\n" );
1431  return $wgContLang;
1432 }
1433 
1450 function wfMessage( $key /*...*/ ) {
1451  $params = func_get_args();
1452  array_shift( $params );
1453  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
1454  $params = $params[0];
1455  }
1456  return new Message( $key, $params );
1457 }
1458 
1471 function wfMessageFallback( /*...*/ ) {
1472  $args = func_get_args();
1473  return call_user_func_array( 'Message::newFallbackSequence', $args );
1474 }
1475 
1495 function wfMsg( $key ) {
1496  wfDeprecated( __METHOD__, '1.21' );
1497 
1498  $args = func_get_args();
1499  array_shift( $args );
1500  return wfMsgReal( $key, $args );
1501 }
1502 
1511 function wfMsgNoTrans( $key ) {
1512  wfDeprecated( __METHOD__, '1.21' );
1513 
1514  $args = func_get_args();
1515  array_shift( $args );
1516  return wfMsgReal( $key, $args, true, false, false );
1517 }
1518 
1544 function wfMsgForContent( $key ) {
1545  wfDeprecated( __METHOD__, '1.21' );
1546 
1547  global $wgForceUIMsgAsContentMsg;
1548  $args = func_get_args();
1549  array_shift( $args );
1550  $forcontent = true;
1551  if ( is_array( $wgForceUIMsgAsContentMsg )
1552  && in_array( $key, $wgForceUIMsgAsContentMsg )
1553  ) {
1554  $forcontent = false;
1555  }
1556  return wfMsgReal( $key, $args, true, $forcontent );
1557 }
1558 
1567 function wfMsgForContentNoTrans( $key ) {
1568  wfDeprecated( __METHOD__, '1.21' );
1569 
1570  global $wgForceUIMsgAsContentMsg;
1571  $args = func_get_args();
1572  array_shift( $args );
1573  $forcontent = true;
1574  if ( is_array( $wgForceUIMsgAsContentMsg )
1575  && in_array( $key, $wgForceUIMsgAsContentMsg )
1576  ) {
1577  $forcontent = false;
1578  }
1579  return wfMsgReal( $key, $args, true, $forcontent, false );
1580 }
1581 
1594 function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
1595  wfDeprecated( __METHOD__, '1.21' );
1596 
1597  wfProfileIn( __METHOD__ );
1598  $message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
1599  $message = wfMsgReplaceArgs( $message, $args );
1600  wfProfileOut( __METHOD__ );
1601  return $message;
1602 }
1603 
1616 function wfMsgGetKey( $key, $useDB = true, $langCode = false, $transform = true ) {
1617  wfDeprecated( __METHOD__, '1.21' );
1618 
1619  wfRunHooks( 'NormalizeMessageKey', array( &$key, &$useDB, &$langCode, &$transform ) );
1620 
1622  $message = $cache->get( $key, $useDB, $langCode );
1623  if ( $message === false ) {
1624  $message = '&lt;' . htmlspecialchars( $key ) . '&gt;';
1625  } elseif ( $transform ) {
1626  $message = $cache->transform( $message );
1627  }
1628  return $message;
1629 }
1630 
1639 function wfMsgReplaceArgs( $message, $args ) {
1640  # Fix windows line-endings
1641  # Some messages are split with explode("\n", $msg)
1642  $message = str_replace( "\r", '', $message );
1643 
1644  // Replace arguments
1645  if ( count( $args ) ) {
1646  if ( is_array( $args[0] ) ) {
1647  $args = array_values( $args[0] );
1648  }
1649  $replacementKeys = array();
1650  foreach ( $args as $n => $param ) {
1651  $replacementKeys['$' . ( $n + 1 )] = $param;
1652  }
1653  $message = strtr( $message, $replacementKeys );
1654  }
1655 
1656  return $message;
1657 }
1658 
1672 function wfMsgHtml( $key ) {
1673  wfDeprecated( __METHOD__, '1.21' );
1674 
1675  $args = func_get_args();
1676  array_shift( $args );
1677  return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key ) ), $args );
1678 }
1679 
1693 function wfMsgWikiHtml( $key ) {
1694  wfDeprecated( __METHOD__, '1.21' );
1695 
1696  $args = func_get_args();
1697  array_shift( $args );
1698  return wfMsgReplaceArgs(
1699  MessageCache::singleton()->parse( wfMsgGetKey( $key ), null,
1700  /* can't be set to false */ true, /* interface */ true )->getText(),
1701  $args );
1702 }
1703 
1727 function wfMsgExt( $key, $options ) {
1728  wfDeprecated( __METHOD__, '1.21' );
1729 
1730  $args = func_get_args();
1731  array_shift( $args );
1732  array_shift( $args );
1733  $options = (array)$options;
1734 
1735  foreach ( $options as $arrayKey => $option ) {
1736  if ( !preg_match( '/^[0-9]+|language$/', $arrayKey ) ) {
1737  # An unknown index, neither numeric nor "language"
1738  wfWarn( "wfMsgExt called with incorrect parameter key $arrayKey", 1, E_USER_WARNING );
1739  } elseif ( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option,
1740  array( 'parse', 'parseinline', 'escape', 'escapenoentities',
1741  'replaceafter', 'parsemag', 'content' ) ) ) {
1742  # A numeric index with unknown value
1743  wfWarn( "wfMsgExt called with incorrect parameter $option", 1, E_USER_WARNING );
1744  }
1745  }
1746 
1747  if ( in_array( 'content', $options, true ) ) {
1748  $forContent = true;
1749  $langCode = true;
1750  $langCodeObj = null;
1751  } elseif ( array_key_exists( 'language', $options ) ) {
1752  $forContent = false;
1753  $langCode = wfGetLangObj( $options['language'] );
1754  $langCodeObj = $langCode;
1755  } else {
1756  $forContent = false;
1757  $langCode = false;
1758  $langCodeObj = null;
1759  }
1760 
1761  $string = wfMsgGetKey( $key, /*DB*/true, $langCode, /*Transform*/false );
1762 
1763  if ( !in_array( 'replaceafter', $options, true ) ) {
1764  $string = wfMsgReplaceArgs( $string, $args );
1765  }
1766 
1767  $messageCache = MessageCache::singleton();
1768  $parseInline = in_array( 'parseinline', $options, true );
1769  if ( in_array( 'parse', $options, true ) || $parseInline ) {
1770  $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj );
1771  if ( $string instanceof ParserOutput ) {
1772  $string = $string->getText();
1773  }
1774 
1775  if ( $parseInline ) {
1776  $m = array();
1777  if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
1778  $string = $m[1];
1779  }
1780  }
1781  } elseif ( in_array( 'parsemag', $options, true ) ) {
1782  $string = $messageCache->transform( $string,
1783  !$forContent, $langCodeObj );
1784  }
1785 
1786  if ( in_array( 'escape', $options, true ) ) {
1787  $string = htmlspecialchars ( $string );
1788  } elseif ( in_array( 'escapenoentities', $options, true ) ) {
1789  $string = Sanitizer::escapeHtmlAllowEntities( $string );
1790  }
1791 
1792  if ( in_array( 'replaceafter', $options, true ) ) {
1793  $string = wfMsgReplaceArgs( $string, $args );
1794  }
1795 
1796  return $string;
1797 }
1798 
1809 function wfEmptyMsg( $key ) {
1810  wfDeprecated( __METHOD__, '1.21' );
1811 
1812  return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false;
1813 }
1814 
1823 function wfDebugDieBacktrace( $msg = '' ) {
1824  wfDeprecated( __FUNCTION__, '1.22' );
1825  throw new MWException( $msg );
1826 }
1827 
1835 function wfHostname() {
1836  static $host;
1837  if ( is_null( $host ) ) {
1838 
1839  # Hostname overriding
1840  global $wgOverrideHostname;
1841  if ( $wgOverrideHostname !== false ) {
1842  # Set static and skip any detection
1843  $host = $wgOverrideHostname;
1844  return $host;
1845  }
1846 
1847  if ( function_exists( 'posix_uname' ) ) {
1848  // This function not present on Windows
1849  $uname = posix_uname();
1850  } else {
1851  $uname = false;
1852  }
1853  if ( is_array( $uname ) && isset( $uname['nodename'] ) ) {
1854  $host = $uname['nodename'];
1855  } elseif ( getenv( 'COMPUTERNAME' ) ) {
1856  # Windows computer name
1857  $host = getenv( 'COMPUTERNAME' );
1858  } else {
1859  # This may be a virtual server.
1860  $host = $_SERVER['SERVER_NAME'];
1861  }
1862  }
1863  return $host;
1864 }
1865 
1875 function wfReportTime() {
1876  global $wgRequestTime, $wgShowHostnames;
1877 
1878  $responseTime = round( ( microtime( true ) - $wgRequestTime ) * 1000 );
1879  $reportVars = array( 'wgBackendResponseTime' => $responseTime );
1880  if ( $wgShowHostnames ) {
1881  $reportVars[ 'wgHostname' ] = wfHostname();
1882  }
1883  return Skin::makeVariablesScript( $reportVars );
1884 }
1885 
1901 function wfDebugBacktrace( $limit = 0 ) {
1902  static $disabled = null;
1903 
1904  if ( extension_loaded( 'Zend Optimizer' ) ) {
1905  wfDebug( "Zend Optimizer detected; skipping debug_backtrace for safety.\n" );
1906  return array();
1907  }
1908 
1909  if ( is_null( $disabled ) ) {
1910  $disabled = false;
1911  $functions = explode( ',', ini_get( 'disable_functions' ) );
1912  $functions = array_map( 'trim', $functions );
1913  $functions = array_map( 'strtolower', $functions );
1914  if ( in_array( 'debug_backtrace', $functions ) ) {
1915  wfDebug( "debug_backtrace is in disabled_functions\n" );
1916  $disabled = true;
1917  }
1918  }
1919  if ( $disabled ) {
1920  return array();
1921  }
1922 
1923  if ( $limit && version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
1924  return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit + 1 ), 1 );
1925  } else {
1926  return array_slice( debug_backtrace(), 1 );
1927  }
1928 }
1929 
1935 function wfBacktrace() {
1937 
1938  if ( $wgCommandLineMode ) {
1939  $msg = '';
1940  } else {
1941  $msg = "<ul>\n";
1942  }
1943  $backtrace = wfDebugBacktrace();
1944  foreach ( $backtrace as $call ) {
1945  if ( isset( $call['file'] ) ) {
1946  $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
1947  $file = $f[count( $f ) - 1];
1948  } else {
1949  $file = '-';
1950  }
1951  if ( isset( $call['line'] ) ) {
1952  $line = $call['line'];
1953  } else {
1954  $line = '-';
1955  }
1956  if ( $wgCommandLineMode ) {
1957  $msg .= "$file line $line calls ";
1958  } else {
1959  $msg .= '<li>' . $file . ' line ' . $line . ' calls ';
1960  }
1961  if ( !empty( $call['class'] ) ) {
1962  $msg .= $call['class'] . $call['type'];
1963  }
1964  $msg .= $call['function'] . '()';
1965 
1966  if ( $wgCommandLineMode ) {
1967  $msg .= "\n";
1968  } else {
1969  $msg .= "</li>\n";
1970  }
1971  }
1972  if ( $wgCommandLineMode ) {
1973  $msg .= "\n";
1974  } else {
1975  $msg .= "</ul>\n";
1976  }
1977 
1978  return $msg;
1979 }
1980 
1990 function wfGetCaller( $level = 2 ) {
1991  $backtrace = wfDebugBacktrace( $level + 1 );
1992  if ( isset( $backtrace[$level] ) ) {
1993  return wfFormatStackFrame( $backtrace[$level] );
1994  } else {
1995  return 'unknown';
1996  }
1997 }
1998 
2007 function wfGetAllCallers( $limit = 3 ) {
2008  $trace = array_reverse( wfDebugBacktrace() );
2009  if ( !$limit || $limit > count( $trace ) - 1 ) {
2010  $limit = count( $trace ) - 1;
2011  }
2012  $trace = array_slice( $trace, -$limit - 1, $limit );
2013  return implode( '/', array_map( 'wfFormatStackFrame', $trace ) );
2014 }
2015 
2022 function wfFormatStackFrame( $frame ) {
2023  return isset( $frame['class'] ) ?
2024  $frame['class'] . '::' . $frame['function'] :
2025  $frame['function'];
2026 }
2027 
2028 /* Some generic result counters, pulled out of SearchEngine */
2029 
2037 function wfShowingResults( $offset, $limit ) {
2038  return wfMessage( 'showingresults' )->numParams( $limit, $offset + 1 )->parse();
2039 }
2040 
2052 function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
2053  wfDeprecated( __METHOD__, '1.19' );
2054 
2055  global $wgLang;
2056 
2057  $query = wfCgiToArray( $query );
2058 
2059  if ( is_object( $link ) ) {
2060  $title = $link;
2061  } else {
2063  if ( is_null( $title ) ) {
2064  return false;
2065  }
2066  }
2067 
2068  return $wgLang->viewPrevNext( $title, $offset, $limit, $query, $atend );
2069 }
2070 
2078 function wfClientAcceptsGzip( $force = false ) {
2079  static $result = null;
2080  if ( $result === null || $force ) {
2081  $result = false;
2082  if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
2083  # @todo FIXME: We may want to blacklist some broken browsers
2084  $m = array();
2085  if ( preg_match(
2086  '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
2087  $_SERVER['HTTP_ACCEPT_ENCODING'],
2088  $m
2089  )
2090  ) {
2091  if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) {
2092  $result = false;
2093  return $result;
2094  }
2095  wfDebug( "wfClientAcceptsGzip: client accepts gzip.\n" );
2096  $result = true;
2097  }
2098  }
2099  }
2100  return $result;
2101 }
2102 
2112 function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
2113  global $wgRequest;
2114  return $wgRequest->getLimitOffset( $deflimit, $optionname );
2115 }
2116 
2126 function wfEscapeWikiText( $text ) {
2127  static $repl = null, $repl2 = null;
2128  if ( $repl === null ) {
2129  $repl = array(
2130  '"' => '&#34;', '&' => '&#38;', "'" => '&#39;', '<' => '&#60;',
2131  '=' => '&#61;', '>' => '&#62;', '[' => '&#91;', ']' => '&#93;',
2132  '{' => '&#123;', '|' => '&#124;', '}' => '&#125;', ';' => '&#59;',
2133  "\n#" => "\n&#35;", "\r#" => "\r&#35;",
2134  "\n*" => "\n&#42;", "\r*" => "\r&#42;",
2135  "\n:" => "\n&#58;", "\r:" => "\r&#58;",
2136  "\n " => "\n&#32;", "\r " => "\r&#32;",
2137  "\n\n" => "\n&#10;", "\r\n" => "&#13;\n",
2138  "\n\r" => "\n&#13;", "\r\r" => "\r&#13;",
2139  "\n\t" => "\n&#9;", "\r\t" => "\r&#9;", // "\n\t\n" is treated like "\n\n"
2140  "\n----" => "\n&#45;---", "\r----" => "\r&#45;---",
2141  '__' => '_&#95;', '://' => '&#58;//',
2142  );
2143 
2144  // We have to catch everything "\s" matches in PCRE
2145  foreach ( array( 'ISBN', 'RFC', 'PMID' ) as $magic ) {
2146  $repl["$magic "] = "$magic&#32;";
2147  $repl["$magic\t"] = "$magic&#9;";
2148  $repl["$magic\r"] = "$magic&#13;";
2149  $repl["$magic\n"] = "$magic&#10;";
2150  $repl["$magic\f"] = "$magic&#12;";
2151  }
2152 
2153  // And handle protocols that don't use "://"
2154  global $wgUrlProtocols;
2155  $repl2 = array();
2156  foreach ( $wgUrlProtocols as $prot ) {
2157  if ( substr( $prot, -1 ) === ':' ) {
2158  $repl2[] = preg_quote( substr( $prot, 0, -1 ), '/' );
2159  }
2160  }
2161  $repl2 = $repl2 ? '/\b(' . join( '|', $repl2 ) . '):/i' : '/^(?!)/';
2162  }
2163  $text = substr( strtr( "\n$text", $repl ), 1 );
2164  $text = preg_replace( $repl2, '$1&#58;', $text );
2165  return $text;
2166 }
2167 
2173 function wfTime() {
2174  wfDeprecated( __FUNCTION__, '1.22' );
2175  return microtime( true );
2176 }
2177 
2188 function wfSetVar( &$dest, $source, $force = false ) {
2189  $temp = $dest;
2190  if ( !is_null( $source ) || $force ) {
2191  $dest = $source;
2192  }
2193  return $temp;
2194 }
2195 
2205 function wfSetBit( &$dest, $bit, $state = true ) {
2206  $temp = (bool)( $dest & $bit );
2207  if ( !is_null( $state ) ) {
2208  if ( $state ) {
2209  $dest |= $bit;
2210  } else {
2211  $dest &= ~$bit;
2212  }
2213  }
2214  return $temp;
2215 }
2216 
2223 function wfVarDump( $var ) {
2224  global $wgOut;
2225  $s = str_replace( "\n", "<br />\n", var_export( $var, true ) . "\n" );
2226  if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) {
2227  print $s;
2228  } else {
2229  $wgOut->addHTML( $s );
2230  }
2231 }
2232 
2240 function wfHttpError( $code, $label, $desc ) {
2241  global $wgOut;
2242  $wgOut->disable();
2243  header( "HTTP/1.0 $code $label" );
2244  header( "Status: $code $label" );
2245  $wgOut->sendCacheControl();
2246 
2247  header( 'Content-type: text/html; charset=utf-8' );
2248  print "<!doctype html>" .
2249  '<html><head><title>' .
2250  htmlspecialchars( $label ) .
2251  '</title></head><body><h1>' .
2252  htmlspecialchars( $label ) .
2253  '</h1><p>' .
2254  nl2br( htmlspecialchars( $desc ) ) .
2255  "</p></body></html>\n";
2256 }
2257 
2275 function wfResetOutputBuffers( $resetGzipEncoding = true ) {
2276  if ( $resetGzipEncoding ) {
2277  // Suppress Content-Encoding and Content-Length
2278  // headers from 1.10+s wfOutputHandler
2279  global $wgDisableOutputCompression;
2280  $wgDisableOutputCompression = true;
2281  }
2282  while ( $status = ob_get_status() ) {
2283  if ( $status['type'] == 0 /* PHP_OUTPUT_HANDLER_INTERNAL */ ) {
2284  // Probably from zlib.output_compression or other
2285  // PHP-internal setting which can't be removed.
2286  //
2287  // Give up, and hope the result doesn't break
2288  // output behavior.
2289  break;
2290  }
2291  if ( !ob_end_clean() ) {
2292  // Could not remove output buffer handler; abort now
2293  // to avoid getting in some kind of infinite loop.
2294  break;
2295  }
2296  if ( $resetGzipEncoding ) {
2297  if ( $status['name'] == 'ob_gzhandler' ) {
2298  // Reset the 'Content-Encoding' field set by this handler
2299  // so we can start fresh.
2300  header_remove( 'Content-Encoding' );
2301  break;
2302  }
2303  }
2304  }
2305 }
2306 
2319 function wfClearOutputBuffers() {
2320  wfResetOutputBuffers( false );
2321 }
2322 
2331 function wfAcceptToPrefs( $accept, $def = '*/*' ) {
2332  # No arg means accept anything (per HTTP spec)
2333  if ( !$accept ) {
2334  return array( $def => 1.0 );
2335  }
2336 
2337  $prefs = array();
2338 
2339  $parts = explode( ',', $accept );
2340 
2341  foreach ( $parts as $part ) {
2342  # @todo FIXME: Doesn't deal with params like 'text/html; level=1'
2343  $values = explode( ';', trim( $part ) );
2344  $match = array();
2345  if ( count( $values ) == 1 ) {
2346  $prefs[$values[0]] = 1.0;
2347  } elseif ( preg_match( '/q\s*=\s*(\d*\.\d+)/', $values[1], $match ) ) {
2348  $prefs[$values[0]] = floatval( $match[1] );
2349  }
2350  }
2351 
2352  return $prefs;
2353 }
2354 
2367 function mimeTypeMatch( $type, $avail ) {
2368  if ( array_key_exists( $type, $avail ) ) {
2369  return $type;
2370  } else {
2371  $parts = explode( '/', $type );
2372  if ( array_key_exists( $parts[0] . '/*', $avail ) ) {
2373  return $parts[0] . '/*';
2374  } elseif ( array_key_exists( '*/*', $avail ) ) {
2375  return '*/*';
2376  } else {
2377  return null;
2378  }
2379  }
2380 }
2381 
2395 function wfNegotiateType( $cprefs, $sprefs ) {
2396  $combine = array();
2397 
2398  foreach ( array_keys( $sprefs ) as $type ) {
2399  $parts = explode( '/', $type );
2400  if ( $parts[1] != '*' ) {
2401  $ckey = mimeTypeMatch( $type, $cprefs );
2402  if ( $ckey ) {
2403  $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
2404  }
2405  }
2406  }
2407 
2408  foreach ( array_keys( $cprefs ) as $type ) {
2409  $parts = explode( '/', $type );
2410  if ( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) {
2411  $skey = mimeTypeMatch( $type, $sprefs );
2412  if ( $skey ) {
2413  $combine[$type] = $sprefs[$skey] * $cprefs[$type];
2414  }
2415  }
2416  }
2417 
2418  $bestq = 0;
2419  $besttype = null;
2420 
2421  foreach ( array_keys( $combine ) as $type ) {
2422  if ( $combine[$type] > $bestq ) {
2423  $besttype = $type;
2424  $bestq = $combine[$type];
2425  }
2426  }
2427 
2428  return $besttype;
2429 }
2430 
2436 function wfSuppressWarnings( $end = false ) {
2437  static $suppressCount = 0;
2438  static $originalLevel = false;
2439 
2440  if ( $end ) {
2441  if ( $suppressCount ) {
2442  --$suppressCount;
2443  if ( !$suppressCount ) {
2444  error_reporting( $originalLevel );
2445  }
2446  }
2447  } else {
2448  if ( !$suppressCount ) {
2449  $originalLevel = error_reporting( E_ALL & ~(
2450  E_WARNING |
2451  E_NOTICE |
2452  E_USER_WARNING |
2453  E_USER_NOTICE |
2454  E_DEPRECATED |
2455  E_USER_DEPRECATED |
2456  E_STRICT
2457  ) );
2458  }
2459  ++$suppressCount;
2460  }
2461 }
2462 
2466 function wfRestoreWarnings() {
2467  wfSuppressWarnings( true );
2468 }
2469 
2470 # Autodetect, convert and provide timestamps of various types
2471 
2475 define( 'TS_UNIX', 0 );
2476 
2480 define( 'TS_MW', 1 );
2481 
2485 define( 'TS_DB', 2 );
2486 
2490 define( 'TS_RFC2822', 3 );
2491 
2497 define( 'TS_ISO_8601', 4 );
2498 
2506 define( 'TS_EXIF', 5 );
2507 
2511 define( 'TS_ORACLE', 6 );
2512 
2516 define( 'TS_POSTGRES', 7 );
2517 
2521 define( 'TS_ISO_8601_BASIC', 9 );
2522 
2532 function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
2533  try {
2534  $timestamp = new MWTimestamp( $ts );
2535  return $timestamp->getTimestamp( $outputtype );
2536  } catch ( TimestampException $e ) {
2537  wfDebug( "wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n" );
2538  return false;
2539  }
2540 }
2541 
2550 function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
2551  if ( is_null( $ts ) ) {
2552  return null;
2553  } else {
2554  return wfTimestamp( $outputtype, $ts );
2555  }
2556 }
2557 
2563 function wfTimestampNow() {
2564  # return NOW
2565  return wfTimestamp( TS_MW, time() );
2566 }
2567 
2573 function wfIsWindows() {
2574  static $isWindows = null;
2575  if ( $isWindows === null ) {
2576  $isWindows = substr( php_uname(), 0, 7 ) == 'Windows';
2577  }
2578  return $isWindows;
2579 }
2580 
2586 function wfIsHHVM() {
2587  return defined( 'HHVM_VERSION' );
2588 }
2589 
2596 function swap( &$x, &$y ) {
2597  $z = $x;
2598  $x = $y;
2599  $y = $z;
2600 }
2601 
2613 function wfTempDir() {
2614  global $wgTmpDirectory;
2615 
2616  if ( $wgTmpDirectory !== false ) {
2617  return $wgTmpDirectory;
2618  }
2619 
2620  $tmpDir = array_map( "getenv", array( 'TMPDIR', 'TMP', 'TEMP' ) );
2621 
2622  foreach ( $tmpDir as $tmp ) {
2623  if ( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
2624  return $tmp;
2625  }
2626  }
2627  return sys_get_temp_dir();
2628 }
2629 
2639 function wfMkdirParents( $dir, $mode = null, $caller = null ) {
2640  global $wgDirectoryMode;
2641 
2642  if ( FileBackend::isStoragePath( $dir ) ) { // sanity
2643  throw new MWException( __FUNCTION__ . " given storage path '$dir'." );
2644  }
2645 
2646  if ( !is_null( $caller ) ) {
2647  wfDebug( "$caller: called wfMkdirParents($dir)\n" );
2648  }
2649 
2650  if ( strval( $dir ) === '' || ( file_exists( $dir ) && is_dir( $dir ) ) ) {
2651  return true;
2652  }
2653 
2654  $dir = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $dir );
2655 
2656  if ( is_null( $mode ) ) {
2657  $mode = $wgDirectoryMode;
2658  }
2659 
2660  // Turn off the normal warning, we're doing our own below
2662  $ok = mkdir( $dir, $mode, true ); // PHP5 <3
2664 
2665  if ( !$ok ) {
2666  //directory may have been created on another request since we last checked
2667  if ( is_dir( $dir ) ) {
2668  return true;
2669  }
2670 
2671  // PHP doesn't report the path in its warning message, so add our own to aid in diagnosis.
2672  wfLogWarning( sprintf( "failed to mkdir \"%s\" mode 0%o", $dir, $mode ) );
2673  }
2674  return $ok;
2675 }
2676 
2681 function wfRecursiveRemoveDir( $dir ) {
2682  wfDebug( __FUNCTION__ . "( $dir )\n" );
2683  // taken from http://de3.php.net/manual/en/function.rmdir.php#98622
2684  if ( is_dir( $dir ) ) {
2685  $objects = scandir( $dir );
2686  foreach ( $objects as $object ) {
2687  if ( $object != "." && $object != ".." ) {
2688  if ( filetype( $dir . '/' . $object ) == "dir" ) {
2689  wfRecursiveRemoveDir( $dir . '/' . $object );
2690  } else {
2691  unlink( $dir . '/' . $object );
2692  }
2693  }
2694  }
2695  reset( $objects );
2696  rmdir( $dir );
2697  }
2698 }
2699 
2706 function wfPercent( $nr, $acc = 2, $round = true ) {
2707  $ret = sprintf( "%.${acc}f", $nr );
2708  return $round ? round( $ret, $acc ) . '%' : "$ret%";
2709 }
2710 
2734 function wfIniGetBool( $setting ) {
2735  $val = strtolower( ini_get( $setting ) );
2736  // 'on' and 'true' can't have whitespace around them, but '1' can.
2737  return $val == 'on'
2738  || $val == 'true'
2739  || $val == 'yes'
2740  || preg_match( "/^\s*[+-]?0*[1-9]/", $val ); // approx C atoi() function
2741 }
2742 
2754 function wfEscapeShellArg( /*...*/ ) {
2756 
2757  $args = func_get_args();
2758  $first = true;
2759  $retVal = '';
2760  foreach ( $args as $arg ) {
2761  if ( !$first ) {
2762  $retVal .= ' ';
2763  } else {
2764  $first = false;
2765  }
2766 
2767  if ( wfIsWindows() ) {
2768  // Escaping for an MSVC-style command line parser and CMD.EXE
2769  // @codingStandardsIgnoreStart For long URLs
2770  // Refs:
2771  // * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html
2772  // * http://technet.microsoft.com/en-us/library/cc723564.aspx
2773  // * Bug #13518
2774  // * CR r63214
2775  // Double the backslashes before any double quotes. Escape the double quotes.
2776  // @codingStandardsIgnoreEnd
2777  $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE );
2778  $arg = '';
2779  $iteration = 0;
2780  foreach ( $tokens as $token ) {
2781  if ( $iteration % 2 == 1 ) {
2782  // Delimiter, a double quote preceded by zero or more slashes
2783  $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"';
2784  } elseif ( $iteration % 4 == 2 ) {
2785  // ^ in $token will be outside quotes, need to be escaped
2786  $arg .= str_replace( '^', '^^', $token );
2787  } else { // $iteration % 4 == 0
2788  // ^ in $token will appear inside double quotes, so leave as is
2789  $arg .= $token;
2790  }
2791  $iteration++;
2792  }
2793  // Double the backslashes before the end of the string, because
2794  // we will soon add a quote
2795  $m = array();
2796  if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
2797  $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
2798  }
2799 
2800  // Add surrounding quotes
2801  $retVal .= '"' . $arg . '"';
2802  } else {
2803  $retVal .= escapeshellarg( $arg );
2804  }
2805  }
2806  return $retVal;
2807 }
2808 
2815 function wfShellExecDisabled() {
2816  static $disabled = null;
2817  if ( is_null( $disabled ) ) {
2818  $disabled = false;
2819  if ( wfIniGetBool( 'safe_mode' ) ) {
2820  wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
2821  $disabled = 'safemode';
2822  } else {
2823  $functions = explode( ',', ini_get( 'disable_functions' ) );
2824  $functions = array_map( 'trim', $functions );
2825  $functions = array_map( 'strtolower', $functions );
2826  if ( in_array( 'proc_open', $functions ) ) {
2827  wfDebug( "proc_open is in disabled_functions\n" );
2828  $disabled = 'disabled';
2829  }
2830  }
2831  }
2832  return $disabled;
2833 }
2834 
2853 function wfShellExec( $cmd, &$retval = null, $environ = array(),
2854  $limits = array(), $options = array()
2855 ) {
2856  global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
2857  $wgMaxShellWallClockTime, $wgShellCgroup;
2858 
2859  $disabled = wfShellExecDisabled();
2860  if ( $disabled ) {
2861  $retval = 1;
2862  return $disabled == 'safemode' ?
2863  'Unable to run external programs in safe mode.' :
2864  'Unable to run external programs, proc_open() is disabled.';
2865  }
2866 
2867  $includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
2868 
2870 
2871  $envcmd = '';
2872  foreach ( $environ as $k => $v ) {
2873  if ( wfIsWindows() ) {
2874  /* Surrounding a set in quotes (method used by wfEscapeShellArg) makes the quotes themselves
2875  * appear in the environment variable, so we must use carat escaping as documented in
2876  * http://technet.microsoft.com/en-us/library/cc723564.aspx
2877  * Note however that the quote isn't listed there, but is needed, and the parentheses
2878  * are listed there but doesn't appear to need it.
2879  */
2880  $envcmd .= "set $k=" . preg_replace( '/([&|()<>^"])/', '^\\1', $v ) . '&& ';
2881  } else {
2882  /* Assume this is a POSIX shell, thus required to accept variable assignments before the command
2883  * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_09_01
2884  */
2885  $envcmd .= "$k=" . escapeshellarg( $v ) . ' ';
2886  }
2887  }
2888  $cmd = $envcmd . $cmd;
2889 
2890  $useLogPipe = false;
2891  if ( php_uname( 's' ) == 'Linux' ) {
2892  $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
2893  if ( isset( $limits['walltime'] ) ) {
2894  $wallTime = intval( $limits['walltime'] );
2895  } elseif ( isset( $limits['time'] ) ) {
2896  $wallTime = $time;
2897  } else {
2898  $wallTime = intval( $wgMaxShellWallClockTime );
2899  }
2900  $mem = intval ( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
2901  $filesize = intval ( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
2902 
2903  if ( $time > 0 || $mem > 0 || $filesize > 0 || $wallTime > 0 ) {
2904  $cmd = '/bin/bash ' . escapeshellarg( "$IP/includes/limit.sh" ) . ' ' .
2905  escapeshellarg( $cmd ) . ' ' .
2906  escapeshellarg(
2907  "MW_INCLUDE_STDERR=" . ( $includeStderr ? '1' : '' ) . ';' .
2908  "MW_CPU_LIMIT=$time; " .
2909  'MW_CGROUP=' . escapeshellarg( $wgShellCgroup ) . '; ' .
2910  "MW_MEM_LIMIT=$mem; " .
2911  "MW_FILE_SIZE_LIMIT=$filesize; " .
2912  "MW_WALL_CLOCK_LIMIT=$wallTime; " .
2913  "MW_USE_LOG_PIPE=yes"
2914  );
2915  $useLogPipe = true;
2916  } elseif ( $includeStderr ) {
2917  $cmd .= ' 2>&1';
2918  }
2919  } elseif ( $includeStderr ) {
2920  $cmd .= ' 2>&1';
2921  }
2922  wfDebug( "wfShellExec: $cmd\n" );
2923 
2924  $desc = array(
2925  0 => array( 'file', 'php://stdin', 'r' ),
2926  1 => array( 'pipe', 'w' ),
2927  2 => array( 'file', 'php://stderr', 'w' ) );
2928  if ( $useLogPipe ) {
2929  $desc[3] = array( 'pipe', 'w' );
2930  }
2931  $pipes = null;
2932  $proc = proc_open( $cmd, $desc, $pipes );
2933  if ( !$proc ) {
2934  wfDebugLog( 'exec', "proc_open() failed: $cmd" );
2935  $retval = -1;
2936  return '';
2937  }
2938  $outBuffer = $logBuffer = '';
2939  $emptyArray = array();
2940  $status = false;
2941  $logMsg = false;
2942 
2943  // According to the documentation, it is possible for stream_select()
2944  // to fail due to EINTR. I haven't managed to induce this in testing
2945  // despite sending various signals. If it did happen, the error
2946  // message would take the form:
2947  //
2948  // stream_select(): unable to select [4]: Interrupted system call (max_fd=5)
2949  //
2950  // where [4] is the value of the macro EINTR and "Interrupted system
2951  // call" is string which according to the Linux manual is "possibly"
2952  // localised according to LC_MESSAGES.
2953  $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
2954  $eintrMessage = "stream_select(): unable to select [$eintr]";
2955 
2956  // Build a table mapping resource IDs to pipe FDs to work around a
2957  // PHP 5.3 issue in which stream_select() does not preserve array keys
2958  // <https://bugs.php.net/bug.php?id=53427>.
2959  $fds = array();
2960  foreach ( $pipes as $fd => $pipe ) {
2961  $fds[(int)$pipe] = $fd;
2962  }
2963 
2964  $running = true;
2965  $timeout = null;
2966  $numReadyPipes = 0;
2967 
2968  while ( $running === true || $numReadyPipes !== 0 ) {
2969  if ( $running ) {
2970  $status = proc_get_status( $proc );
2971  // If the process has terminated, switch to nonblocking selects
2972  // for getting any data still waiting to be read.
2973  if ( !$status['running'] ) {
2974  $running = false;
2975  $timeout = 0;
2976  }
2977  }
2978 
2979  $readyPipes = $pipes;
2980 
2981  // Clear last error
2982  @trigger_error( '' );
2983  $numReadyPipes = @stream_select( $readyPipes, $emptyArray, $emptyArray, $timeout );
2984  if ( $numReadyPipes === false ) {
2985  $error = error_get_last();
2986  if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
2987  continue;
2988  } else {
2989  trigger_error( $error['message'], E_USER_WARNING );
2990  $logMsg = $error['message'];
2991  break;
2992  }
2993  }
2994  foreach ( $readyPipes as $pipe ) {
2995  $block = fread( $pipe, 65536 );
2996  $fd = $fds[(int)$pipe];
2997  if ( $block === '' ) {
2998  // End of file
2999  fclose( $pipes[$fd] );
3000  unset( $pipes[$fd] );
3001  if ( !$pipes ) {
3002  break 2;
3003  }
3004  } elseif ( $block === false ) {
3005  // Read error
3006  $logMsg = "Error reading from pipe";
3007  break 2;
3008  } elseif ( $fd == 1 ) {
3009  // From stdout
3010  $outBuffer .= $block;
3011  } elseif ( $fd == 3 ) {
3012  // From log FD
3013  $logBuffer .= $block;
3014  if ( strpos( $block, "\n" ) !== false ) {
3015  $lines = explode( "\n", $logBuffer );
3016  $logBuffer = array_pop( $lines );
3017  foreach ( $lines as $line ) {
3018  wfDebugLog( 'exec', $line );
3019  }
3020  }
3021  }
3022  }
3023  }
3024 
3025  foreach ( $pipes as $pipe ) {
3026  fclose( $pipe );
3027  }
3028 
3029  // Use the status previously collected if possible, since proc_get_status()
3030  // just calls waitpid() which will not return anything useful the second time.
3031  if ( $running ) {
3032  $status = proc_get_status( $proc );
3033  }
3034 
3035  if ( $logMsg !== false ) {
3036  // Read/select error
3037  $retval = -1;
3038  proc_close( $proc );
3039  } elseif ( $status['signaled'] ) {
3040  $logMsg = "Exited with signal {$status['termsig']}";
3041  $retval = 128 + $status['termsig'];
3042  proc_close( $proc );
3043  } else {
3044  if ( $status['running'] ) {
3045  $retval = proc_close( $proc );
3046  } else {
3047  $retval = $status['exitcode'];
3048  proc_close( $proc );
3049  }
3050  if ( $retval == 127 ) {
3051  $logMsg = "Possibly missing executable file";
3052  } elseif ( $retval >= 129 && $retval <= 192 ) {
3053  $logMsg = "Probably exited with signal " . ( $retval - 128 );
3054  }
3055  }
3056 
3057  if ( $logMsg !== false ) {
3058  wfDebugLog( 'exec', "$logMsg: $cmd" );
3059  }
3060 
3061  return $outBuffer;
3062 }
3063 
3078 function wfShellExecWithStderr( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
3079  return wfShellExec( $cmd, $retval, $environ, $limits, array( 'duplicateStderr' => true ) );
3080 }
3081 
3086 function wfInitShellLocale() {
3087  static $done = false;
3088  if ( $done ) {
3089  return;
3090  }
3091  $done = true;
3092  global $wgShellLocale;
3093  if ( !wfIniGetBool( 'safe_mode' ) ) {
3094  putenv( "LC_CTYPE=$wgShellLocale" );
3095  setlocale( LC_CTYPE, $wgShellLocale );
3096  }
3097 }
3098 
3104 function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) {
3105  return wfShellWikiCmd( $script, $parameters, $options );
3106 }
3107 
3120 function wfShellWikiCmd( $script, array $parameters = array(), array $options = array() ) {
3121  global $wgPhpCli;
3122  // Give site config file a chance to run the script in a wrapper.
3123  // The caller may likely want to call wfBasename() on $script.
3124  wfRunHooks( 'wfShellWikiCmd', array( &$script, &$parameters, &$options ) );
3125  $cmd = isset( $options['php'] ) ? array( $options['php'] ) : array( $wgPhpCli );
3126  if ( isset( $options['wrapper'] ) ) {
3127  $cmd[] = $options['wrapper'];
3128  }
3129  $cmd[] = $script;
3130  // Escape each parameter for shell
3131  return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
3132 }
3133 
3144 function wfMerge( $old, $mine, $yours, &$result ) {
3145  global $wgDiff3;
3146 
3147  # This check may also protect against code injection in
3148  # case of broken installations.
3150  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
3152 
3153  if ( !$haveDiff3 ) {
3154  wfDebug( "diff3 not found\n" );
3155  return false;
3156  }
3157 
3158  # Make temporary files
3159  $td = wfTempDir();
3160  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3161  $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
3162  $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
3163 
3164  # NOTE: diff3 issues a warning to stderr if any of the files does not end with
3165  # a newline character. To avoid this, we normalize the trailing whitespace before
3166  # creating the diff.
3167 
3168  fwrite( $oldtextFile, rtrim( $old ) . "\n" );
3169  fclose( $oldtextFile );
3170  fwrite( $mytextFile, rtrim( $mine ) . "\n" );
3171  fclose( $mytextFile );
3172  fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
3173  fclose( $yourtextFile );
3174 
3175  # Check for a conflict
3176  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
3177  wfEscapeShellArg( $mytextName ) . ' ' .
3178  wfEscapeShellArg( $oldtextName ) . ' ' .
3179  wfEscapeShellArg( $yourtextName );
3180  $handle = popen( $cmd, 'r' );
3181 
3182  if ( fgets( $handle, 1024 ) ) {
3183  $conflict = true;
3184  } else {
3185  $conflict = false;
3186  }
3187  pclose( $handle );
3188 
3189  # Merge differences
3190  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
3191  wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
3192  $handle = popen( $cmd, 'r' );
3193  $result = '';
3194  do {
3195  $data = fread( $handle, 8192 );
3196  if ( strlen( $data ) == 0 ) {
3197  break;
3198  }
3199  $result .= $data;
3200  } while ( true );
3201  pclose( $handle );
3202  unlink( $mytextName );
3203  unlink( $oldtextName );
3204  unlink( $yourtextName );
3205 
3206  if ( $result === '' && $old !== '' && !$conflict ) {
3207  wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
3208  $conflict = true;
3209  }
3210  return !$conflict;
3211 }
3212 
3222 function wfDiff( $before, $after, $params = '-u' ) {
3223  if ( $before == $after ) {
3224  return '';
3225  }
3226 
3227  global $wgDiff;
3229  $haveDiff = $wgDiff && file_exists( $wgDiff );
3231 
3232  # This check may also protect against code injection in
3233  # case of broken installations.
3234  if ( !$haveDiff ) {
3235  wfDebug( "diff executable not found\n" );
3236  $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) );
3237  $format = new UnifiedDiffFormatter();
3238  return $format->format( $diffs );
3239  }
3240 
3241  # Make temporary files
3242  $td = wfTempDir();
3243  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3244  $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' );
3245 
3246  fwrite( $oldtextFile, $before );
3247  fclose( $oldtextFile );
3248  fwrite( $newtextFile, $after );
3249  fclose( $newtextFile );
3250 
3251  // Get the diff of the two files
3252  $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName );
3253 
3254  $h = popen( $cmd, 'r' );
3255 
3256  $diff = '';
3257 
3258  do {
3259  $data = fread( $h, 8192 );
3260  if ( strlen( $data ) == 0 ) {
3261  break;
3262  }
3263  $diff .= $data;
3264  } while ( true );
3265 
3266  // Clean up
3267  pclose( $h );
3268  unlink( $oldtextName );
3269  unlink( $newtextName );
3270 
3271  // Kill the --- and +++ lines. They're not useful.
3272  $diff_lines = explode( "\n", $diff );
3273  if ( strpos( $diff_lines[0], '---' ) === 0 ) {
3274  unset( $diff_lines[0] );
3275  }
3276  if ( strpos( $diff_lines[1], '+++' ) === 0 ) {
3277  unset( $diff_lines[1] );
3278  }
3279 
3280  $diff = implode( "\n", $diff_lines );
3281 
3282  return $diff;
3283 }
3284 
3301 function wfUsePHP( $req_ver ) {
3302  $php_ver = PHP_VERSION;
3303 
3304  if ( version_compare( $php_ver, (string)$req_ver, '<' ) ) {
3305  throw new MWException( "PHP $req_ver required--this is only $php_ver" );
3306  }
3307 }
3308 
3331 function wfUseMW( $req_ver ) {
3332  global $wgVersion;
3333 
3334  if ( version_compare( $wgVersion, (string)$req_ver, '<' ) ) {
3335  throw new MWException( "MediaWiki $req_ver required--this is only $wgVersion" );
3336  }
3337 }
3338 
3351 function wfBaseName( $path, $suffix = '' ) {
3352  if ( $suffix == '' ) {
3353  $encSuffix = '';
3354  } else {
3355  $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
3356  }
3357 
3358  $matches = array();
3359  if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
3360  return $matches[1];
3361  } else {
3362  return '';
3363  }
3364 }
3365 
3375 function wfRelativePath( $path, $from ) {
3376  // Normalize mixed input on Windows...
3377  $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
3378  $from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
3379 
3380  // Trim trailing slashes -- fix for drive root
3381  $path = rtrim( $path, DIRECTORY_SEPARATOR );
3382  $from = rtrim( $from, DIRECTORY_SEPARATOR );
3383 
3384  $pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
3385  $against = explode( DIRECTORY_SEPARATOR, $from );
3386 
3387  if ( $pieces[0] !== $against[0] ) {
3388  // Non-matching Windows drive letters?
3389  // Return a full path.
3390  return $path;
3391  }
3392 
3393  // Trim off common prefix
3394  while ( count( $pieces ) && count( $against )
3395  && $pieces[0] == $against[0] ) {
3396  array_shift( $pieces );
3397  array_shift( $against );
3398  }
3399 
3400  // relative dots to bump us to the parent
3401  while ( count( $against ) ) {
3402  array_unshift( $pieces, '..' );
3403  array_shift( $against );
3404  }
3405 
3406  array_push( $pieces, wfBaseName( $path ) );
3407 
3408  return implode( DIRECTORY_SEPARATOR, $pieces );
3409 }
3410 
3426 function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
3427  $lowercase = true, $engine = 'auto'
3428 ) {
3429  $input = (string)$input;
3430  if (
3431  $sourceBase < 2 ||
3432  $sourceBase > 36 ||
3433  $destBase < 2 ||
3434  $destBase > 36 ||
3435  $sourceBase != (int)$sourceBase ||
3436  $destBase != (int)$destBase ||
3437  $pad != (int)$pad ||
3438  !preg_match(
3439  "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i",
3440  $input
3441  )
3442  ) {
3443  return false;
3444  }
3445 
3446  static $baseChars = array(
3447  10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f',
3448  16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l',
3449  22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r',
3450  28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x',
3451  34 => 'y', 35 => 'z',
3452 
3453  '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5,
3454  '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11,
3455  'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17,
3456  'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23,
3457  'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29,
3458  'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35
3459  );
3460 
3461  if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
3462  $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
3463  } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
3464  $decimal = '0';
3465  foreach ( str_split( strtolower( $input ) ) as $char ) {
3466  $decimal = bcmul( $decimal, $sourceBase );
3467  $decimal = bcadd( $decimal, $baseChars[$char] );
3468  }
3469 
3470  for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
3471  $result .= $baseChars[bcmod( $decimal, $destBase )];
3472  }
3473 
3474  $result = strrev( $result );
3475  } else {
3476  $inDigits = array();
3477  foreach ( str_split( strtolower( $input ) ) as $char ) {
3478  $inDigits[] = $baseChars[$char];
3479  }
3480 
3481  // Iterate over the input, modulo-ing out an output digit
3482  // at a time until input is gone.
3483  $result = '';
3484  while ( $inDigits ) {
3485  $work = 0;
3486  $workDigits = array();
3487 
3488  // Long division...
3489  foreach ( $inDigits as $digit ) {
3490  $work *= $sourceBase;
3491  $work += $digit;
3492 
3493  if ( $workDigits || $work >= $destBase ) {
3494  $workDigits[] = (int)( $work / $destBase );
3495  }
3496  $work %= $destBase;
3497  }
3498 
3499  // All that division leaves us with a remainder,
3500  // which is conveniently our next output digit.
3501  $result .= $baseChars[$work];
3502 
3503  // And we continue!
3504  $inDigits = $workDigits;
3505  }
3506 
3507  $result = strrev( $result );
3508  }
3509 
3510  if ( !$lowercase ) {
3511  $result = strtoupper( $result );
3512  }
3513 
3514  return str_pad( $result, $pad, '0', STR_PAD_LEFT );
3515 }
3516 
3522 function wfCheckEntropy() {
3523  return (
3524  ( wfIsWindows() && version_compare( PHP_VERSION, '5.3.3', '>=' ) )
3525  || ini_get( 'session.entropy_file' )
3526  )
3527  && intval( ini_get( 'session.entropy_length' ) ) >= 32;
3528 }
3529 
3534 function wfFixSessionID() {
3535  // If the cookie or session id is already set we already have a session and should abort
3536  if ( isset( $_COOKIE[session_name()] ) || session_id() ) {
3537  return;
3538  }
3539 
3540  // PHP's built-in session entropy is enabled if:
3541  // - entropy_file is set or you're on Windows with php 5.3.3+
3542  // - AND entropy_length is > 0
3543  // We treat it as disabled if it doesn't have an entropy length of at least 32
3544  $entropyEnabled = wfCheckEntropy();
3545 
3546  // If built-in entropy is not enabled or not sufficient override PHP's
3547  // built in session id generation code
3548  if ( !$entropyEnabled ) {
3549  wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, " .
3550  "overriding session id generation using our cryptrand source.\n" );
3551  session_id( MWCryptRand::generateHex( 32 ) );
3552  }
3553 }
3554 
3560 function wfResetSessionID() {
3561  global $wgCookieSecure;
3562  $oldSessionId = session_id();
3563  $cookieParams = session_get_cookie_params();
3564  if ( wfCheckEntropy() && $wgCookieSecure == $cookieParams['secure'] ) {
3565  session_regenerate_id( false );
3566  } else {
3567  $tmp = $_SESSION;
3568  session_destroy();
3570  $_SESSION = $tmp;
3571  }
3572  $newSessionId = session_id();
3573  wfRunHooks( 'ResetSessionID', array( $oldSessionId, $newSessionId ) );
3574 }
3575 
3581 function wfSetupSession( $sessionId = false ) {
3582  global $wgSessionsInMemcached, $wgSessionsInObjectCache, $wgCookiePath, $wgCookieDomain,
3583  $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler;
3584  if ( $wgSessionsInObjectCache || $wgSessionsInMemcached ) {
3586  } elseif ( $wgSessionHandler && $wgSessionHandler != ini_get( 'session.save_handler' ) ) {
3587  # Only set this if $wgSessionHandler isn't null and session.save_handler
3588  # hasn't already been set to the desired value (that causes errors)
3589  ini_set( 'session.save_handler', $wgSessionHandler );
3590  }
3591  session_set_cookie_params(
3592  0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly );
3593  session_cache_limiter( 'private, must-revalidate' );
3594  if ( $sessionId ) {
3595  session_id( $sessionId );
3596  } else {
3597  wfFixSessionID();
3598  }
3600  session_start();
3602 }
3603 
3610 function wfGetPrecompiledData( $name ) {
3611  global $IP;
3612 
3613  $file = "$IP/serialized/$name";
3614  if ( file_exists( $file ) ) {
3615  $blob = file_get_contents( $file );
3616  if ( $blob ) {
3617  return unserialize( $blob );
3618  }
3619  }
3620  return false;
3621 }
3622 
3629 function wfMemcKey( /*...*/ ) {
3630  global $wgCachePrefix;
3631  $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
3632  $args = func_get_args();
3633  $key = $prefix . ':' . implode( ':', $args );
3634  $key = str_replace( ' ', '_', $key );
3635  return $key;
3636 }
3637 
3646 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
3647  $args = array_slice( func_get_args(), 2 );
3648  if ( $prefix ) {
3649  $key = "$db-$prefix:" . implode( ':', $args );
3650  } else {
3651  $key = $db . ':' . implode( ':', $args );
3652  }
3653  return str_replace( ' ', '_', $key );
3654 }
3655 
3662 function wfWikiID() {
3663  global $wgDBprefix, $wgDBname;
3664  if ( $wgDBprefix ) {
3665  return "$wgDBname-$wgDBprefix";
3666  } else {
3667  return $wgDBname;
3668  }
3669 }
3670 
3678 function wfSplitWikiID( $wiki ) {
3679  $bits = explode( '-', $wiki, 2 );
3680  if ( count( $bits ) < 2 ) {
3681  $bits[] = '';
3682  }
3683  return $bits;
3684 }
3685 
3708 function &wfGetDB( $db, $groups = array(), $wiki = false ) {
3709  return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
3710 }
3711 
3718 function wfGetLB( $wiki = false ) {
3719  return wfGetLBFactory()->getMainLB( $wiki );
3720 }
3721 
3727 function &wfGetLBFactory() {
3728  return LBFactory::singleton();
3729 }
3730 
3751 function wfFindFile( $title, $options = array() ) {
3752  return RepoGroup::singleton()->findFile( $title, $options );
3753 }
3754 
3762 function wfLocalFile( $title ) {
3763  return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
3764 }
3765 
3772 function wfQueriesMustScale() {
3773  global $wgMiserMode;
3774  return $wgMiserMode
3775  || ( SiteStats::pages() > 100000
3776  && SiteStats::edits() > 1000000
3777  && SiteStats::users() > 10000 );
3778 }
3779 
3788 function wfScript( $script = 'index' ) {
3789  global $wgScriptPath, $wgScriptExtension, $wgScript, $wgLoadScript;
3790  if ( $script === 'index' ) {
3791  return $wgScript;
3792  } elseif ( $script === 'load' ) {
3793  return $wgLoadScript;
3794  } else {
3795  return "{$wgScriptPath}/{$script}{$wgScriptExtension}";
3796  }
3797 }
3798 
3804 function wfGetScriptUrl() {
3805  if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
3806  #
3807  # as it was called, minus the query string.
3808  #
3809  # Some sites use Apache rewrite rules to handle subdomains,
3810  # and have PHP set up in a weird way that causes PHP_SELF
3811  # to contain the rewritten URL instead of the one that the
3812  # outside world sees.
3813  #
3814  # If in this mode, use SCRIPT_URL instead, which mod_rewrite
3815  # provides containing the "before" URL.
3816  return $_SERVER['SCRIPT_NAME'];
3817  } else {
3818  return $_SERVER['URL'];
3819  }
3820 }
3821 
3829 function wfBoolToStr( $value ) {
3830  return $value ? 'true' : 'false';
3831 }
3832 
3838 function wfGetNull() {
3839  return wfIsWindows() ? 'NUL' : '/dev/null';
3840 }
3841 
3853 function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
3854  if ( $cluster !== false ) {
3855  $lb = wfGetLBFactory()->getExternalLB( $cluster );
3856  } else {
3857  $lb = wfGetLB( $wiki );
3858  }
3859 
3860  // bug 27975 - Don't try to wait for slaves if there are none
3861  // Prevents permission error when getting master position
3862  if ( $lb->getServerCount() > 1 ) {
3863  $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
3864  $pos = $dbw->getMasterPos();
3865  // The DBMS may not support getMasterPos() or the whole
3866  // load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
3867  if ( $pos !== false ) {
3868  $lb->waitForAll( $pos );
3869  }
3870  }
3871 }
3872 
3880 function wfCountDown( $seconds ) {
3881  for ( $i = $seconds; $i >= 0; $i-- ) {
3882  if ( $i != $seconds ) {
3883  echo str_repeat( "\x08", strlen( $i + 1 ) );
3884  }
3885  echo $i;
3886  flush();
3887  if ( $i ) {
3888  sleep( 1 );
3889  }
3890  }
3891  echo "\n";
3892 }
3893 
3902 function wfStripIllegalFilenameChars( $name ) {
3903  global $wgIllegalFileChars;
3904  $illegalFileChars = $wgIllegalFileChars ? "|[" . $wgIllegalFileChars . "]" : '';
3905  $name = wfBaseName( $name );
3906  $name = preg_replace(
3907  "/[^" . Title::legalChars() . "]" . $illegalFileChars . "/",
3908  '-',
3909  $name
3910  );
3911  return $name;
3912 }
3913 
3919 function wfMemoryLimit() {
3920  global $wgMemoryLimit;
3921  $memlimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
3922  if ( $memlimit != -1 ) {
3923  $conflimit = wfShorthandToInteger( $wgMemoryLimit );
3924  if ( $conflimit == -1 ) {
3925  wfDebug( "Removing PHP's memory limit\n" );
3927  ini_set( 'memory_limit', $conflimit );
3929  return $conflimit;
3930  } elseif ( $conflimit > $memlimit ) {
3931  wfDebug( "Raising PHP's memory limit to $conflimit bytes\n" );
3933  ini_set( 'memory_limit', $conflimit );
3935  return $conflimit;
3936  }
3937  }
3938  return $memlimit;
3939 }
3940 
3948 function wfShorthandToInteger( $string = '', $default = -1 ) {
3949  $string = trim( $string );
3950  if ( $string === '' ) {
3951  return $default;
3952  }
3953  $last = $string[strlen( $string ) - 1];
3954  $val = intval( $string );
3955  switch ( $last ) {
3956  case 'g':
3957  case 'G':
3958  $val *= 1024;
3959  // break intentionally missing
3960  case 'm':
3961  case 'M':
3962  $val *= 1024;
3963  // break intentionally missing
3964  case 'k':
3965  case 'K':
3966  $val *= 1024;
3967  }
3968 
3969  return $val;
3970 }
3971 
3979 function wfBCP47( $code ) {
3980  $codeSegment = explode( '-', $code );
3981  $codeBCP = array();
3982  foreach ( $codeSegment as $segNo => $seg ) {
3983  // when previous segment is x, it is a private segment and should be lc
3984  if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
3985  $codeBCP[$segNo] = strtolower( $seg );
3986  // ISO 3166 country code
3987  } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
3988  $codeBCP[$segNo] = strtoupper( $seg );
3989  // ISO 15924 script code
3990  } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
3991  $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
3992  // Use lowercase for other cases
3993  } else {
3994  $codeBCP[$segNo] = strtolower( $seg );
3995  }
3996  }
3997  $langCode = implode( '-', $codeBCP );
3998  return $langCode;
3999 }
4000 
4007 function wfGetCache( $inputType ) {
4008  return ObjectCache::getInstance( $inputType );
4009 }
4010 
4016 function wfGetMainCache() {
4019 }
4020 
4026 function wfGetMessageCacheStorage() {
4027  global $wgMessageCacheType;
4028  return ObjectCache::getInstance( $wgMessageCacheType );
4029 }
4030 
4036 function wfGetParserCacheStorage() {
4037  global $wgParserCacheType;
4038  return ObjectCache::getInstance( $wgParserCacheType );
4039 }
4040 
4046 function wfGetLangConverterCacheStorage() {
4047  global $wgLanguageConverterCacheType;
4048  return ObjectCache::getInstance( $wgLanguageConverterCacheType );
4049 }
4050 
4060 function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null ) {
4061  return Hooks::run( $event, $args, $deprecatedVersion );
4062 }
4063 
4078 function wfUnpack( $format, $data, $length = false ) {
4079  if ( $length !== false ) {
4080  $realLen = strlen( $data );
4081  if ( $realLen < $length ) {
4082  throw new MWException( "Tried to use wfUnpack on a "
4083  . "string of length $realLen, but needed one "
4084  . "of at least length $length."
4085  );
4086  }
4087  }
4088 
4090  $result = unpack( $format, $data );
4092 
4093  if ( $result === false ) {
4094  // If it cannot extract the packed data.
4095  throw new MWException( "unpack could not unpack binary data" );
4096  }
4097  return $result;
4098 }
4099 
4114 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
4115  static $badImageCache = null; // based on bad_image_list msg
4116  wfProfileIn( __METHOD__ );
4117 
4118  # Handle redirects
4119  $redirectTitle = RepoGroup::singleton()->checkRedirect( Title::makeTitle( NS_FILE, $name ) );
4120  if ( $redirectTitle ) {
4121  $name = $redirectTitle->getDBkey();
4122  }
4123 
4124  # Run the extension hook
4125  $bad = false;
4126  if ( !wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {
4127  wfProfileOut( __METHOD__ );
4128  return $bad;
4129  }
4130 
4131  $cacheable = ( $blacklist === null );
4132  if ( $cacheable && $badImageCache !== null ) {
4133  $badImages = $badImageCache;
4134  } else { // cache miss
4135  if ( $blacklist === null ) {
4136  $blacklist = wfMessage( 'bad_image_list' )->inContentLanguage()->plain(); // site list
4137  }
4138  # Build the list now
4139  $badImages = array();
4140  $lines = explode( "\n", $blacklist );
4141  foreach ( $lines as $line ) {
4142  # List items only
4143  if ( substr( $line, 0, 1 ) !== '*' ) {
4144  continue;
4145  }
4146 
4147  # Find all links
4148  $m = array();
4149  if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
4150  continue;
4151  }
4152 
4153  $exceptions = array();
4154  $imageDBkey = false;
4155  foreach ( $m[1] as $i => $titleText ) {
4156  $title = Title::newFromText( $titleText );
4157  if ( !is_null( $title ) ) {
4158  if ( $i == 0 ) {
4159  $imageDBkey = $title->getDBkey();
4160  } else {
4161  $exceptions[$title->getPrefixedDBkey()] = true;
4162  }
4163  }
4164  }
4165 
4166  if ( $imageDBkey !== false ) {
4167  $badImages[$imageDBkey] = $exceptions;
4168  }
4169  }
4170  if ( $cacheable ) {
4171  $badImageCache = $badImages;
4172  }
4173  }
4174 
4175  $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
4176  $bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
4177  wfProfileOut( __METHOD__ );
4178  return $bad;
4179 }
4180 
4188 function wfCanIPUseHTTPS( $ip ) {
4189  $canDo = true;
4190  wfRunHooks( 'CanIPUseHTTPS', array( $ip, &$canDo ) );
4191  return !!$canDo;
4192 }
4193 
4201 function wfGetIP() {
4202  wfDeprecated( __METHOD__, '1.19' );
4203  global $wgRequest;
4204  return $wgRequest->getIP();
4205 }
4206 
4215 function wfIsTrustedProxy( $ip ) {
4216  $trusted = wfIsConfiguredProxy( $ip );
4217  wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
4218  return $trusted;
4219 }
4220 
4228 function wfIsConfiguredProxy( $ip ) {
4229  global $wgSquidServers, $wgSquidServersNoPurge;
4230 
4231  // quick check of known proxy servers
4232  $trusted = in_array( $ip, $wgSquidServers )
4233  || in_array( $ip, $wgSquidServersNoPurge );
4234 
4235  if ( !$trusted ) {
4236  // slightly slower check to see if the ip is listed directly or in a CIDR
4237  // block in $wgSquidServersNoPurge
4238  foreach ( $wgSquidServersNoPurge as $block ) {
4239  if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
4240  $trusted = true;
4241  break;
4242  }
4243  }
4244  }
4245  return $trusted;
4246 }
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:3532
wfGetIP
wfGetIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Definition: GlobalFunctions.php:4199
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:3329
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:3977
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:4186
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:3102
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:3220
wfMerge
wfMerge( $old, $mine, $yours, &$result)
wfMerge attempts to merge differences between three texts.
Definition: GlobalFunctions.php:3142
wfSetupSession
wfSetupSession( $sessionId=false)
Initialise php session.
Definition: GlobalFunctions.php:3579
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:3716
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:3706
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:4076
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:3802
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:3349
wfQueriesMustScale
wfQueriesMustScale()
Should low-performance queries be disabled?
Definition: GlobalFunctions.php:3770
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:3076
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:3299
wfGetCache
wfGetCache( $inputType)
Get a cache object.
Definition: GlobalFunctions.php:4005
wfIsConfiguredProxy
wfIsConfiguredProxy( $ip)
Checks if an IP matches a proxy we've configured.
Definition: GlobalFunctions.php:4226
wfSplitWikiID
wfSplitWikiID( $wiki)
Split a wiki ID into DB name and table prefix.
Definition: GlobalFunctions.php:3676
$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:2154
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:3827
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:4014
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:3900
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3627
$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:3786
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:68
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
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:4058
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:3917
wfWaitForSlaves
wfWaitForSlaves( $maxLag=false, $wiki=false, $cluster=false)
Modern version of wfWaitForSlaves().
Definition: GlobalFunctions.php:3851
wfForeignMemcKey
wfForeignMemcKey( $db, $prefix)
Get a cache key for a foreign DB.
Definition: GlobalFunctions.php:3644
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:3118
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:4112
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:3660
$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:3084
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:4034
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:3836
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:4213
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:4024
$args
if( $line===false) $args
Definition: cdb.php:62
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:3946
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:4044
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:3725
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:3608
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:3424
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:3520
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:3749
$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:3373
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:2578
$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:88
wfLocalFile
wfLocalFile( $title)
Get an object referring to a locally registered file.
Definition: GlobalFunctions.php:3760
wfShowingResults
wfShowingResults( $offset, $limit)
Definition: GlobalFunctions.php:2035
wfResetSessionID
wfResetSessionID()
Reset the session_id.
Definition: GlobalFunctions.php:3558
$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:3878
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