MediaWiki  1.23.6
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 }
108 
115 function wfArrayDiff2( $a, $b ) {
116  return array_udiff( $a, $b, 'wfArrayDiff2_cmp' );
117 }
118 
124 function wfArrayDiff2_cmp( $a, $b ) {
125  if ( is_string( $a ) && is_string( $b ) ) {
126  return strcmp( $a, $b );
127  } elseif ( count( $a ) !== count( $b ) ) {
128  return count( $a ) < count( $b ) ? -1 : 1;
129  } else {
130  reset( $a );
131  reset( $b );
132  while ( ( list( , $valueA ) = each( $a ) ) && ( list( , $valueB ) = each( $b ) ) ) {
133  $cmp = strcmp( $valueA, $valueB );
134  if ( $cmp !== 0 ) {
135  return $cmp;
136  }
137  }
138  return 0;
139  }
140 }
141 
152 function wfArrayLookup( $a, $b ) {
153  wfDeprecated( __FUNCTION__, '1.22' );
154  return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) );
155 }
156 
166 function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
167  if ( is_null( $changed ) ) {
168  throw new MWException( 'GlobalFunctions::wfAppendToArrayIfNotDefault got null' );
169  }
170  if ( $default[$key] !== $value ) {
171  $changed[$key] = $value;
172  }
173 }
174 
185 function wfArrayMerge( $array1 /*...*/ ) {
186  wfDeprecated( __FUNCTION__, '1.22' );
187  $args = func_get_args();
188  $args = array_reverse( $args, true );
189  $out = array();
190  foreach ( $args as $arg ) {
191  $out += $arg;
192  }
193  return $out;
194 }
195 
215 function wfMergeErrorArrays( /*...*/ ) {
216  $args = func_get_args();
217  $out = array();
218  foreach ( $args as $errors ) {
219  foreach ( $errors as $params ) {
220  # @todo FIXME: Sometimes get nested arrays for $params,
221  # which leads to E_NOTICEs
222  $spec = implode( "\t", $params );
223  $out[$spec] = $params;
224  }
225  }
226  return array_values( $out );
227 }
228 
237 function wfArrayInsertAfter( array $array, array $insert, $after ) {
238  // Find the offset of the element to insert after.
239  $keys = array_keys( $array );
240  $offsetByKey = array_flip( $keys );
241 
242  $offset = $offsetByKey[$after];
243 
244  // Insert at the specified offset
245  $before = array_slice( $array, 0, $offset + 1, true );
246  $after = array_slice( $array, $offset + 1, count( $array ) - $offset, true );
247 
248  $output = $before + $insert + $after;
249 
250  return $output;
251 }
252 
260 function wfObjectToArray( $objOrArray, $recursive = true ) {
261  $array = array();
262  if ( is_object( $objOrArray ) ) {
263  $objOrArray = get_object_vars( $objOrArray );
264  }
265  foreach ( $objOrArray as $key => $value ) {
266  if ( $recursive && ( is_object( $value ) || is_array( $value ) ) ) {
268  }
269 
270  $array[$key] = $value;
271  }
272 
273  return $array;
274 }
275 
283 function wfRandom() {
284  # The maximum random value is "only" 2^31-1, so get two random
285  # values to reduce the chance of dupes
286  $max = mt_getrandmax() + 1;
287  $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12, '.', '' );
288 
289  return $rand;
290 }
291 
302 function wfRandomString( $length = 32 ) {
303  $str = '';
304  for ( $n = 0; $n < $length; $n += 7 ) {
305  $str .= sprintf( '%07x', mt_rand() & 0xfffffff );
306  }
307  return substr( $str, 0, $length );
308 }
309 
332 function wfUrlencode( $s ) {
333  static $needle;
334 
335  if ( is_null( $s ) ) {
336  $needle = null;
337  return '';
338  }
339 
340  if ( is_null( $needle ) ) {
341  $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
342  if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
343  ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
344  ) {
345  $needle[] = '%3A';
346  }
347  }
348 
349  $s = urlencode( $s );
350  $s = str_ireplace(
351  $needle,
352  array( ';', '@', '$', '!', '*', '(', ')', ',', '/', ':' ),
353  $s
354  );
355 
356  return $s;
357 }
358 
369 function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
370  if ( !is_null( $array2 ) ) {
371  $array1 = $array1 + $array2;
372  }
373 
374  $cgi = '';
375  foreach ( $array1 as $key => $value ) {
376  if ( !is_null( $value ) && $value !== false ) {
377  if ( $cgi != '' ) {
378  $cgi .= '&';
379  }
380  if ( $prefix !== '' ) {
381  $key = $prefix . "[$key]";
382  }
383  if ( is_array( $value ) ) {
384  $firstTime = true;
385  foreach ( $value as $k => $v ) {
386  $cgi .= $firstTime ? '' : '&';
387  if ( is_array( $v ) ) {
388  $cgi .= wfArrayToCgi( $v, null, $key . "[$k]" );
389  } else {
390  $cgi .= urlencode( $key . "[$k]" ) . '=' . urlencode( $v );
391  }
392  $firstTime = false;
393  }
394  } else {
395  if ( is_object( $value ) ) {
396  $value = $value->__toString();
397  }
398  $cgi .= urlencode( $key ) . '=' . urlencode( $value );
399  }
400  }
401  }
402  return $cgi;
403 }
404 
414 function wfCgiToArray( $query ) {
415  if ( isset( $query[0] ) && $query[0] == '?' ) {
416  $query = substr( $query, 1 );
417  }
418  $bits = explode( '&', $query );
419  $ret = array();
420  foreach ( $bits as $bit ) {
421  if ( $bit === '' ) {
422  continue;
423  }
424  if ( strpos( $bit, '=' ) === false ) {
425  // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does)
426  $key = $bit;
427  $value = '';
428  } else {
429  list( $key, $value ) = explode( '=', $bit );
430  }
431  $key = urldecode( $key );
432  $value = urldecode( $value );
433  if ( strpos( $key, '[' ) !== false ) {
434  $keys = array_reverse( explode( '[', $key ) );
435  $key = array_pop( $keys );
436  $temp = $value;
437  foreach ( $keys as $k ) {
438  $k = substr( $k, 0, -1 );
439  $temp = array( $k => $temp );
440  }
441  if ( isset( $ret[$key] ) ) {
442  $ret[$key] = array_merge( $ret[$key], $temp );
443  } else {
444  $ret[$key] = $temp;
445  }
446  } else {
447  $ret[$key] = $value;
448  }
449  }
450  return $ret;
451 }
452 
461 function wfAppendQuery( $url, $query ) {
462  if ( is_array( $query ) ) {
464  }
465  if ( $query != '' ) {
466  if ( false === strpos( $url, '?' ) ) {
467  $url .= '?';
468  } else {
469  $url .= '&';
470  }
471  $url .= $query;
472  }
473  return $url;
474 }
475 
499 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
500  global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest;
501  if ( $defaultProto === PROTO_CANONICAL ) {
502  $serverUrl = $wgCanonicalServer;
503  } elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
504  // Make $wgInternalServer fall back to $wgServer if not set
505  $serverUrl = $wgInternalServer;
506  } else {
507  $serverUrl = $wgServer;
508  if ( $defaultProto === PROTO_CURRENT ) {
509  $defaultProto = $wgRequest->getProtocol() . '://';
510  }
511  }
512 
513  // Analyze $serverUrl to obtain its protocol
514  $bits = wfParseUrl( $serverUrl );
515  $serverHasProto = $bits && $bits['scheme'] != '';
516 
517  if ( $defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL ) {
518  if ( $serverHasProto ) {
519  $defaultProto = $bits['scheme'] . '://';
520  } else {
521  // $wgCanonicalServer or $wgInternalServer doesn't have a protocol.
522  // This really isn't supposed to happen. Fall back to HTTP in this
523  // ridiculous case.
524  $defaultProto = PROTO_HTTP;
525  }
526  }
527 
528  $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 );
529 
530  if ( substr( $url, 0, 2 ) == '//' ) {
531  $url = $defaultProtoWithoutSlashes . $url;
532  } elseif ( substr( $url, 0, 1 ) == '/' ) {
533  // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
534  // otherwise leave it alone.
535  $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url;
536  }
537 
538  $bits = wfParseUrl( $url );
539  if ( $bits && isset( $bits['path'] ) ) {
540  $bits['path'] = wfRemoveDotSegments( $bits['path'] );
541  return wfAssembleUrl( $bits );
542  } elseif ( $bits ) {
543  # No path to expand
544  return $url;
545  } elseif ( substr( $url, 0, 1 ) != '/' ) {
546  # URL is a relative path
547  return wfRemoveDotSegments( $url );
548  }
549 
550  # Expanded URL is not valid.
551  return false;
552 }
553 
567 function wfAssembleUrl( $urlParts ) {
568  $result = '';
569 
570  if ( isset( $urlParts['delimiter'] ) ) {
571  if ( isset( $urlParts['scheme'] ) ) {
572  $result .= $urlParts['scheme'];
573  }
574 
575  $result .= $urlParts['delimiter'];
576  }
577 
578  if ( isset( $urlParts['host'] ) ) {
579  if ( isset( $urlParts['user'] ) ) {
580  $result .= $urlParts['user'];
581  if ( isset( $urlParts['pass'] ) ) {
582  $result .= ':' . $urlParts['pass'];
583  }
584  $result .= '@';
585  }
586 
587  $result .= $urlParts['host'];
588 
589  if ( isset( $urlParts['port'] ) ) {
590  $result .= ':' . $urlParts['port'];
591  }
592  }
593 
594  if ( isset( $urlParts['path'] ) ) {
595  $result .= $urlParts['path'];
596  }
597 
598  if ( isset( $urlParts['query'] ) ) {
599  $result .= '?' . $urlParts['query'];
600  }
601 
602  if ( isset( $urlParts['fragment'] ) ) {
603  $result .= '#' . $urlParts['fragment'];
604  }
605 
606  return $result;
607 }
608 
619 function wfRemoveDotSegments( $urlPath ) {
620  $output = '';
621  $inputOffset = 0;
622  $inputLength = strlen( $urlPath );
623 
624  while ( $inputOffset < $inputLength ) {
625  $prefixLengthOne = substr( $urlPath, $inputOffset, 1 );
626  $prefixLengthTwo = substr( $urlPath, $inputOffset, 2 );
627  $prefixLengthThree = substr( $urlPath, $inputOffset, 3 );
628  $prefixLengthFour = substr( $urlPath, $inputOffset, 4 );
629  $trimOutput = false;
630 
631  if ( $prefixLengthTwo == './' ) {
632  # Step A, remove leading "./"
633  $inputOffset += 2;
634  } elseif ( $prefixLengthThree == '../' ) {
635  # Step A, remove leading "../"
636  $inputOffset += 3;
637  } elseif ( ( $prefixLengthTwo == '/.' ) && ( $inputOffset + 2 == $inputLength ) ) {
638  # Step B, replace leading "/.$" with "/"
639  $inputOffset += 1;
640  $urlPath[$inputOffset] = '/';
641  } elseif ( $prefixLengthThree == '/./' ) {
642  # Step B, replace leading "/./" with "/"
643  $inputOffset += 2;
644  } elseif ( $prefixLengthThree == '/..' && ( $inputOffset + 3 == $inputLength ) ) {
645  # Step C, replace leading "/..$" with "/" and
646  # remove last path component in output
647  $inputOffset += 2;
648  $urlPath[$inputOffset] = '/';
649  $trimOutput = true;
650  } elseif ( $prefixLengthFour == '/../' ) {
651  # Step C, replace leading "/../" with "/" and
652  # remove last path component in output
653  $inputOffset += 3;
654  $trimOutput = true;
655  } elseif ( ( $prefixLengthOne == '.' ) && ( $inputOffset + 1 == $inputLength ) ) {
656  # Step D, remove "^.$"
657  $inputOffset += 1;
658  } elseif ( ( $prefixLengthTwo == '..' ) && ( $inputOffset + 2 == $inputLength ) ) {
659  # Step D, remove "^..$"
660  $inputOffset += 2;
661  } else {
662  # Step E, move leading path segment to output
663  if ( $prefixLengthOne == '/' ) {
664  $slashPos = strpos( $urlPath, '/', $inputOffset + 1 );
665  } else {
666  $slashPos = strpos( $urlPath, '/', $inputOffset );
667  }
668  if ( $slashPos === false ) {
669  $output .= substr( $urlPath, $inputOffset );
670  $inputOffset = $inputLength;
671  } else {
672  $output .= substr( $urlPath, $inputOffset, $slashPos - $inputOffset );
673  $inputOffset += $slashPos - $inputOffset;
674  }
675  }
676 
677  if ( $trimOutput ) {
678  $slashPos = strrpos( $output, '/' );
679  if ( $slashPos === false ) {
680  $output = '';
681  } else {
682  $output = substr( $output, 0, $slashPos );
683  }
684  }
685  }
686 
687  return $output;
688 }
689 
697 function wfUrlProtocols( $includeProtocolRelative = true ) {
698  global $wgUrlProtocols;
699 
700  // Cache return values separately based on $includeProtocolRelative
701  static $withProtRel = null, $withoutProtRel = null;
702  $cachedValue = $includeProtocolRelative ? $withProtRel : $withoutProtRel;
703  if ( !is_null( $cachedValue ) ) {
704  return $cachedValue;
705  }
706 
707  // Support old-style $wgUrlProtocols strings, for backwards compatibility
708  // with LocalSettings files from 1.5
709  if ( is_array( $wgUrlProtocols ) ) {
710  $protocols = array();
711  foreach ( $wgUrlProtocols as $protocol ) {
712  // Filter out '//' if !$includeProtocolRelative
713  if ( $includeProtocolRelative || $protocol !== '//' ) {
714  $protocols[] = preg_quote( $protocol, '/' );
715  }
716  }
717 
718  $retval = implode( '|', $protocols );
719  } else {
720  // Ignore $includeProtocolRelative in this case
721  // This case exists for pre-1.6 compatibility, and we can safely assume
722  // that '//' won't appear in a pre-1.6 config because protocol-relative
723  // URLs weren't supported until 1.18
724  $retval = $wgUrlProtocols;
725  }
726 
727  // Cache return value
728  if ( $includeProtocolRelative ) {
729  $withProtRel = $retval;
730  } else {
731  $withoutProtRel = $retval;
732  }
733  return $retval;
734 }
735 
742 function wfUrlProtocolsWithoutProtRel() {
743  return wfUrlProtocols( false );
744 }
745 
757 function wfParseUrl( $url ) {
758  global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
759 
760  // Protocol-relative URLs are handled really badly by parse_url(). It's so
761  // bad that the easiest way to handle them is to just prepend 'http:' and
762  // strip the protocol out later.
763  $wasRelative = substr( $url, 0, 2 ) == '//';
764  if ( $wasRelative ) {
765  $url = "http:$url";
766  }
768  $bits = parse_url( $url );
770  // parse_url() returns an array without scheme for some invalid URLs, e.g.
771  // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
772  if ( !$bits || !isset( $bits['scheme'] ) ) {
773  return false;
774  }
775 
776  // parse_url() incorrectly handles schemes case-sensitively. Convert it to lowercase.
777  $bits['scheme'] = strtolower( $bits['scheme'] );
778 
779  // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
780  if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
781  $bits['delimiter'] = '://';
782  } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
783  $bits['delimiter'] = ':';
784  // parse_url detects for news: and mailto: the host part of an url as path
785  // We have to correct this wrong detection
786  if ( isset( $bits['path'] ) ) {
787  $bits['host'] = $bits['path'];
788  $bits['path'] = '';
789  }
790  } else {
791  return false;
792  }
793 
794  /* Provide an empty host for eg. file:/// urls (see bug 28627) */
795  if ( !isset( $bits['host'] ) ) {
796  $bits['host'] = '';
797 
798  // bug 45069
799  if ( isset( $bits['path'] ) ) {
800  /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
801  if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
802  $bits['path'] = '/' . $bits['path'];
803  }
804  } else {
805  $bits['path'] = '';
806  }
807  }
808 
809  // If the URL was protocol-relative, fix scheme and delimiter
810  if ( $wasRelative ) {
811  $bits['scheme'] = '';
812  $bits['delimiter'] = '//';
813  }
814  return $bits;
815 }
816 
827 function wfExpandIRI( $url ) {
828  return preg_replace_callback(
829  '/((?:%[89A-F][0-9A-F])+)/i',
830  'wfExpandIRI_callback',
831  wfExpandUrl( $url )
832  );
833 }
834 
840 function wfExpandIRI_callback( $matches ) {
841  return urldecode( $matches[1] );
842 }
843 
850 function wfMakeUrlIndexes( $url ) {
851  $bits = wfParseUrl( $url );
852 
853  // Reverse the labels in the hostname, convert to lower case
854  // For emails reverse domainpart only
855  if ( $bits['scheme'] == 'mailto' ) {
856  $mailparts = explode( '@', $bits['host'], 2 );
857  if ( count( $mailparts ) === 2 ) {
858  $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) );
859  } else {
860  // No domain specified, don't mangle it
861  $domainpart = '';
862  }
863  $reversedHost = $domainpart . '@' . $mailparts[0];
864  } else {
865  $reversedHost = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) );
866  }
867  // Add an extra dot to the end
868  // Why? Is it in wrong place in mailto links?
869  if ( substr( $reversedHost, -1, 1 ) !== '.' ) {
870  $reversedHost .= '.';
871  }
872  // Reconstruct the pseudo-URL
873  $prot = $bits['scheme'];
874  $index = $prot . $bits['delimiter'] . $reversedHost;
875  // Leave out user and password. Add the port, path, query and fragment
876  if ( isset( $bits['port'] ) ) {
877  $index .= ':' . $bits['port'];
878  }
879  if ( isset( $bits['path'] ) ) {
880  $index .= $bits['path'];
881  } else {
882  $index .= '/';
883  }
884  if ( isset( $bits['query'] ) ) {
885  $index .= '?' . $bits['query'];
886  }
887  if ( isset( $bits['fragment'] ) ) {
888  $index .= '#' . $bits['fragment'];
889  }
890 
891  if ( $prot == '' ) {
892  return array( "http:$index", "https:$index" );
893  } else {
894  return array( $index );
895  }
896 }
897 
904 function wfMatchesDomainList( $url, $domains ) {
905  $bits = wfParseUrl( $url );
906  if ( is_array( $bits ) && isset( $bits['host'] ) ) {
907  $host = '.' . $bits['host'];
908  foreach ( (array)$domains as $domain ) {
909  $domain = '.' . $domain;
910  if ( substr( $host, -strlen( $domain ) ) === $domain ) {
911  return true;
912  }
913  }
914  }
915  return false;
916 }
917 
935 function wfDebug( $text, $dest = 'all' ) {
936  global $wgDebugLogFile, $wgDebugRawPage, $wgDebugLogPrefix;
937 
938  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
939  return;
940  }
941 
942  // Turn $dest into a string if it's a boolean (for b/c)
943  if ( $dest === true ) {
944  $dest = 'all';
945  } elseif ( $dest === false ) {
946  $dest = 'log';
947  }
948 
949  $timer = wfDebugTimer();
950  if ( $timer !== '' ) {
951  $text = preg_replace( '/[^\n]/', $timer . '\0', $text, 1 );
952  }
953 
954  if ( $dest === 'all' ) {
955  MWDebug::debugMsg( $text );
956  }
957 
958  if ( $wgDebugLogFile != '' ) {
959  # Strip unprintables; they can switch terminal modes when binary data
960  # gets dumped, which is pretty annoying.
961  $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
962  $text = $wgDebugLogPrefix . $text;
963  wfErrorLog( $text, $wgDebugLogFile );
964  }
965 }
966 
971 function wfIsDebugRawPage() {
972  static $cache;
973  if ( $cache !== null ) {
974  return $cache;
975  }
976  # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
977  if ( ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' )
978  || (
979  isset( $_SERVER['SCRIPT_NAME'] )
980  && substr( $_SERVER['SCRIPT_NAME'], -8 ) == 'load.php'
981  )
982  ) {
983  $cache = true;
984  } else {
985  $cache = false;
986  }
987  return $cache;
988 }
989 
995 function wfDebugTimer() {
996  global $wgDebugTimestamps, $wgRequestTime;
997 
998  if ( !$wgDebugTimestamps ) {
999  return '';
1000  }
1001 
1002  $prefix = sprintf( "%6.4f", microtime( true ) - $wgRequestTime );
1003  $mem = sprintf( "%5.1fM", ( memory_get_usage( true ) / ( 1024 * 1024 ) ) );
1004  return "$prefix $mem ";
1005 }
1006 
1012 function wfDebugMem( $exact = false ) {
1013  $mem = memory_get_usage();
1014  if ( !$exact ) {
1015  $mem = floor( $mem / 1024 ) . ' kilobytes';
1016  } else {
1017  $mem .= ' bytes';
1018  }
1019  wfDebug( "Memory usage: $mem\n" );
1020 }
1021 
1042 function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
1043  global $wgDebugLogGroups;
1044 
1045  $text = trim( $text ) . "\n";
1046 
1047  // Turn $dest into a string if it's a boolean (for b/c)
1048  if ( $dest === true ) {
1049  $dest = 'all';
1050  } elseif ( $dest === false ) {
1051  $dest = 'private';
1052  }
1053 
1054  if ( !isset( $wgDebugLogGroups[$logGroup] ) ) {
1055  if ( $dest !== 'private' ) {
1056  wfDebug( "[$logGroup] $text", $dest );
1057  }
1058  return;
1059  }
1060 
1061  if ( $dest === 'all' ) {
1062  MWDebug::debugMsg( "[$logGroup] $text" );
1063  }
1064 
1065  $logConfig = $wgDebugLogGroups[$logGroup];
1066  if ( $logConfig === false ) {
1067  return;
1068  }
1069  if ( is_array( $logConfig ) ) {
1070  if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
1071  return;
1072  }
1073  $destination = $logConfig['destination'];
1074  } else {
1075  $destination = strval( $logConfig );
1076  }
1077 
1078  $time = wfTimestamp( TS_DB );
1079  $wiki = wfWikiID();
1080  $host = wfHostname();
1081  wfErrorLog( "$time $host $wiki: $text", $destination );
1082 }
1083 
1089 function wfLogDBError( $text ) {
1090  global $wgDBerrorLog, $wgDBerrorLogTZ;
1091  static $logDBErrorTimeZoneObject = null;
1092 
1093  if ( $wgDBerrorLog ) {
1094  $host = wfHostname();
1095  $wiki = wfWikiID();
1096 
1097  if ( $wgDBerrorLogTZ && !$logDBErrorTimeZoneObject ) {
1098  $logDBErrorTimeZoneObject = new DateTimeZone( $wgDBerrorLogTZ );
1099  }
1100 
1101  // Workaround for https://bugs.php.net/bug.php?id=52063
1102  // Can be removed when min PHP > 5.3.2
1103  if ( $logDBErrorTimeZoneObject === null ) {
1104  $d = date_create( "now" );
1105  } else {
1106  $d = date_create( "now", $logDBErrorTimeZoneObject );
1107  }
1108 
1109  $date = $d->format( 'D M j G:i:s T Y' );
1110 
1111  $text = "$date\t$host\t$wiki\t" . trim( $text ) . "\n";
1112  wfErrorLog( $text, $wgDBerrorLog );
1113  }
1114 }
1115 
1129 function wfDeprecated( $function, $version = false, $component = false, $callerOffset = 2 ) {
1130  MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 );
1131 }
1132 
1143 function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
1144  MWDebug::warning( $msg, $callerOffset + 1, $level, 'auto' );
1145 }
1146 
1156 function wfLogWarning( $msg, $callerOffset = 1, $level = E_USER_WARNING ) {
1157  MWDebug::warning( $msg, $callerOffset + 1, $level, 'production' );
1158 }
1159 
1170 function wfErrorLog( $text, $file ) {
1171  if ( substr( $file, 0, 4 ) == 'udp:' ) {
1172  # Needs the sockets extension
1173  if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
1174  // IPv6 bracketed host
1175  $host = $m[2];
1176  $port = intval( $m[3] );
1177  $prefix = isset( $m[4] ) ? $m[4] : false;
1178  $domain = AF_INET6;
1179  } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
1180  $host = $m[2];
1181  if ( !IP::isIPv4( $host ) ) {
1182  $host = gethostbyname( $host );
1183  }
1184  $port = intval( $m[3] );
1185  $prefix = isset( $m[4] ) ? $m[4] : false;
1186  $domain = AF_INET;
1187  } else {
1188  throw new MWException( __METHOD__ . ': Invalid UDP specification' );
1189  }
1190 
1191  // Clean it up for the multiplexer
1192  if ( strval( $prefix ) !== '' ) {
1193  $text = preg_replace( '/^/m', $prefix . ' ', $text );
1194 
1195  // Limit to 64KB
1196  if ( strlen( $text ) > 65506 ) {
1197  $text = substr( $text, 0, 65506 );
1198  }
1199 
1200  if ( substr( $text, -1 ) != "\n" ) {
1201  $text .= "\n";
1202  }
1203  } elseif ( strlen( $text ) > 65507 ) {
1204  $text = substr( $text, 0, 65507 );
1205  }
1206 
1207  $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
1208  if ( !$sock ) {
1209  return;
1210  }
1211 
1212  socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
1213  socket_close( $sock );
1214  } else {
1216  $exists = file_exists( $file );
1217  $size = $exists ? filesize( $file ) : false;
1218  if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
1219  file_put_contents( $file, $text, FILE_APPEND );
1220  }
1222  }
1223 }
1224 
1228 function wfLogProfilingData() {
1229  global $wgRequestTime, $wgDebugLogFile, $wgDebugLogGroups, $wgDebugRawPage;
1230  global $wgProfileLimit, $wgUser, $wgRequest;
1231 
1232  StatCounter::singleton()->flush();
1233 
1234  $profiler = Profiler::instance();
1235 
1236  # Profiling must actually be enabled...
1237  if ( $profiler->isStub() ) {
1238  return;
1239  }
1240 
1241  // Get total page request time and only show pages that longer than
1242  // $wgProfileLimit time (default is 0)
1243  $elapsed = microtime( true ) - $wgRequestTime;
1244  if ( $elapsed <= $wgProfileLimit ) {
1245  return;
1246  }
1247 
1248  $profiler->logData();
1249 
1250  // Check whether this should be logged in the debug file.
1251  if ( isset( $wgDebugLogGroups['profileoutput'] )
1252  && $wgDebugLogGroups['profileoutput'] === false
1253  ) {
1254  // Explicitely disabled
1255  return;
1256  }
1257  if ( !isset( $wgDebugLogGroups['profileoutput'] ) && $wgDebugLogFile == '' ) {
1258  // Logging not enabled; no point going further
1259  return;
1260  }
1261  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
1262  return;
1263  }
1264 
1265  $forward = '';
1266  if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
1267  $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
1268  }
1269  if ( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
1270  $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP'];
1271  }
1272  if ( !empty( $_SERVER['HTTP_FROM'] ) ) {
1273  $forward .= ' from ' . $_SERVER['HTTP_FROM'];
1274  }
1275  if ( $forward ) {
1276  $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
1277  }
1278  // Don't load $wgUser at this late stage just for statistics purposes
1279  // @todo FIXME: We can detect some anons even if it is not loaded. See User::getId()
1280  if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
1281  $forward .= ' anon';
1282  }
1283 
1284  // Command line script uses a FauxRequest object which does not have
1285  // any knowledge about an URL and throw an exception instead.
1286  try {
1287  $requestUrl = $wgRequest->getRequestURL();
1288  } catch ( MWException $e ) {
1289  $requestUrl = 'n/a';
1290  }
1291 
1292  $log = sprintf( "%s\t%04.3f\t%s\n",
1293  gmdate( 'YmdHis' ), $elapsed,
1294  urldecode( $requestUrl . $forward ) );
1295 
1296  wfDebugLog( 'profileoutput', $log . $profiler->getOutput() );
1297 }
1298 
1306 function wfIncrStats( $key, $count = 1 ) {
1307  StatCounter::singleton()->incr( $key, $count );
1308 }
1309 
1315 function wfReadOnly() {
1316  return wfReadOnlyReason() !== false;
1317 }
1318 
1324 function wfReadOnlyReason() {
1325  global $wgReadOnly, $wgReadOnlyFile;
1326 
1327  if ( $wgReadOnly === null ) {
1328  // Set $wgReadOnly for faster access next time
1329  if ( is_file( $wgReadOnlyFile ) && filesize( $wgReadOnlyFile ) > 0 ) {
1330  $wgReadOnly = file_get_contents( $wgReadOnlyFile );
1331  } else {
1332  $wgReadOnly = false;
1333  }
1334  }
1335 
1336  return $wgReadOnly;
1337 }
1338 
1354 function wfGetLangObj( $langcode = false ) {
1355  # Identify which language to get or create a language object for.
1356  # Using is_object here due to Stub objects.
1357  if ( is_object( $langcode ) ) {
1358  # Great, we already have the object (hopefully)!
1359  return $langcode;
1360  }
1361 
1362  global $wgContLang, $wgLanguageCode;
1363  if ( $langcode === true || $langcode === $wgLanguageCode ) {
1364  # $langcode is the language code of the wikis content language object.
1365  # or it is a boolean and value is true
1366  return $wgContLang;
1367  }
1368 
1369  global $wgLang;
1370  if ( $langcode === false || $langcode === $wgLang->getCode() ) {
1371  # $langcode is the language code of user language object.
1372  # or it was a boolean and value is false
1373  return $wgLang;
1374  }
1375 
1376  $validCodes = array_keys( Language::fetchLanguageNames() );
1377  if ( in_array( $langcode, $validCodes ) ) {
1378  # $langcode corresponds to a valid language.
1379  return Language::factory( $langcode );
1380  }
1381 
1382  # $langcode is a string, but not a valid language code; use content language.
1383  wfDebug( "Invalid language code passed to wfGetLangObj, falling back to content language.\n" );
1384  return $wgContLang;
1385 }
1386 
1403 function wfMessage( $key /*...*/ ) {
1404  $params = func_get_args();
1405  array_shift( $params );
1406  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
1407  $params = $params[0];
1408  }
1409  return new Message( $key, $params );
1410 }
1411 
1424 function wfMessageFallback( /*...*/ ) {
1425  $args = func_get_args();
1426  return call_user_func_array( 'Message::newFallbackSequence', $args );
1427 }
1428 
1448 function wfMsg( $key ) {
1449  wfDeprecated( __METHOD__, '1.21' );
1450 
1451  $args = func_get_args();
1452  array_shift( $args );
1453  return wfMsgReal( $key, $args );
1454 }
1455 
1464 function wfMsgNoTrans( $key ) {
1465  wfDeprecated( __METHOD__, '1.21' );
1466 
1467  $args = func_get_args();
1468  array_shift( $args );
1469  return wfMsgReal( $key, $args, true, false, false );
1470 }
1471 
1497 function wfMsgForContent( $key ) {
1498  wfDeprecated( __METHOD__, '1.21' );
1499 
1500  global $wgForceUIMsgAsContentMsg;
1501  $args = func_get_args();
1502  array_shift( $args );
1503  $forcontent = true;
1504  if ( is_array( $wgForceUIMsgAsContentMsg )
1505  && in_array( $key, $wgForceUIMsgAsContentMsg )
1506  ) {
1507  $forcontent = false;
1508  }
1509  return wfMsgReal( $key, $args, true, $forcontent );
1510 }
1511 
1520 function wfMsgForContentNoTrans( $key ) {
1521  wfDeprecated( __METHOD__, '1.21' );
1522 
1523  global $wgForceUIMsgAsContentMsg;
1524  $args = func_get_args();
1525  array_shift( $args );
1526  $forcontent = true;
1527  if ( is_array( $wgForceUIMsgAsContentMsg )
1528  && in_array( $key, $wgForceUIMsgAsContentMsg )
1529  ) {
1530  $forcontent = false;
1531  }
1532  return wfMsgReal( $key, $args, true, $forcontent, false );
1533 }
1534 
1547 function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
1548  wfDeprecated( __METHOD__, '1.21' );
1549 
1550  wfProfileIn( __METHOD__ );
1551  $message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
1552  $message = wfMsgReplaceArgs( $message, $args );
1553  wfProfileOut( __METHOD__ );
1554  return $message;
1555 }
1556 
1569 function wfMsgGetKey( $key, $useDB = true, $langCode = false, $transform = true ) {
1570  wfDeprecated( __METHOD__, '1.21' );
1571 
1572  wfRunHooks( 'NormalizeMessageKey', array( &$key, &$useDB, &$langCode, &$transform ) );
1573 
1575  $message = $cache->get( $key, $useDB, $langCode );
1576  if ( $message === false ) {
1577  $message = '&lt;' . htmlspecialchars( $key ) . '&gt;';
1578  } elseif ( $transform ) {
1579  $message = $cache->transform( $message );
1580  }
1581  return $message;
1582 }
1583 
1592 function wfMsgReplaceArgs( $message, $args ) {
1593  # Fix windows line-endings
1594  # Some messages are split with explode("\n", $msg)
1595  $message = str_replace( "\r", '', $message );
1596 
1597  // Replace arguments
1598  if ( count( $args ) ) {
1599  if ( is_array( $args[0] ) ) {
1600  $args = array_values( $args[0] );
1601  }
1602  $replacementKeys = array();
1603  foreach ( $args as $n => $param ) {
1604  $replacementKeys['$' . ( $n + 1 )] = $param;
1605  }
1606  $message = strtr( $message, $replacementKeys );
1607  }
1608 
1609  return $message;
1610 }
1611 
1625 function wfMsgHtml( $key ) {
1626  wfDeprecated( __METHOD__, '1.21' );
1627 
1628  $args = func_get_args();
1629  array_shift( $args );
1630  return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key ) ), $args );
1631 }
1632 
1646 function wfMsgWikiHtml( $key ) {
1647  wfDeprecated( __METHOD__, '1.21' );
1648 
1649  $args = func_get_args();
1650  array_shift( $args );
1651  return wfMsgReplaceArgs(
1652  MessageCache::singleton()->parse( wfMsgGetKey( $key ), null,
1653  /* can't be set to false */ true, /* interface */ true )->getText(),
1654  $args );
1655 }
1656 
1680 function wfMsgExt( $key, $options ) {
1681  wfDeprecated( __METHOD__, '1.21' );
1682 
1683  $args = func_get_args();
1684  array_shift( $args );
1685  array_shift( $args );
1686  $options = (array)$options;
1687 
1688  foreach ( $options as $arrayKey => $option ) {
1689  if ( !preg_match( '/^[0-9]+|language$/', $arrayKey ) ) {
1690  # An unknown index, neither numeric nor "language"
1691  wfWarn( "wfMsgExt called with incorrect parameter key $arrayKey", 1, E_USER_WARNING );
1692  } elseif ( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option,
1693  array( 'parse', 'parseinline', 'escape', 'escapenoentities',
1694  'replaceafter', 'parsemag', 'content' ) ) ) {
1695  # A numeric index with unknown value
1696  wfWarn( "wfMsgExt called with incorrect parameter $option", 1, E_USER_WARNING );
1697  }
1698  }
1699 
1700  if ( in_array( 'content', $options, true ) ) {
1701  $forContent = true;
1702  $langCode = true;
1703  $langCodeObj = null;
1704  } elseif ( array_key_exists( 'language', $options ) ) {
1705  $forContent = false;
1706  $langCode = wfGetLangObj( $options['language'] );
1707  $langCodeObj = $langCode;
1708  } else {
1709  $forContent = false;
1710  $langCode = false;
1711  $langCodeObj = null;
1712  }
1713 
1714  $string = wfMsgGetKey( $key, /*DB*/true, $langCode, /*Transform*/false );
1715 
1716  if ( !in_array( 'replaceafter', $options, true ) ) {
1717  $string = wfMsgReplaceArgs( $string, $args );
1718  }
1719 
1720  $messageCache = MessageCache::singleton();
1721  $parseInline = in_array( 'parseinline', $options, true );
1722  if ( in_array( 'parse', $options, true ) || $parseInline ) {
1723  $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj );
1724  if ( $string instanceof ParserOutput ) {
1725  $string = $string->getText();
1726  }
1727 
1728  if ( $parseInline ) {
1729  $m = array();
1730  if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
1731  $string = $m[1];
1732  }
1733  }
1734  } elseif ( in_array( 'parsemag', $options, true ) ) {
1735  $string = $messageCache->transform( $string,
1736  !$forContent, $langCodeObj );
1737  }
1738 
1739  if ( in_array( 'escape', $options, true ) ) {
1740  $string = htmlspecialchars ( $string );
1741  } elseif ( in_array( 'escapenoentities', $options, true ) ) {
1742  $string = Sanitizer::escapeHtmlAllowEntities( $string );
1743  }
1744 
1745  if ( in_array( 'replaceafter', $options, true ) ) {
1746  $string = wfMsgReplaceArgs( $string, $args );
1747  }
1748 
1749  return $string;
1750 }
1751 
1762 function wfEmptyMsg( $key ) {
1763  wfDeprecated( __METHOD__, '1.21' );
1764 
1765  return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false;
1766 }
1767 
1776 function wfDebugDieBacktrace( $msg = '' ) {
1777  wfDeprecated( __FUNCTION__, '1.22' );
1778  throw new MWException( $msg );
1779 }
1780 
1788 function wfHostname() {
1789  static $host;
1790  if ( is_null( $host ) ) {
1791 
1792  # Hostname overriding
1793  global $wgOverrideHostname;
1794  if ( $wgOverrideHostname !== false ) {
1795  # Set static and skip any detection
1796  $host = $wgOverrideHostname;
1797  return $host;
1798  }
1799 
1800  if ( function_exists( 'posix_uname' ) ) {
1801  // This function not present on Windows
1802  $uname = posix_uname();
1803  } else {
1804  $uname = false;
1805  }
1806  if ( is_array( $uname ) && isset( $uname['nodename'] ) ) {
1807  $host = $uname['nodename'];
1808  } elseif ( getenv( 'COMPUTERNAME' ) ) {
1809  # Windows computer name
1810  $host = getenv( 'COMPUTERNAME' );
1811  } else {
1812  # This may be a virtual server.
1813  $host = $_SERVER['SERVER_NAME'];
1814  }
1815  }
1816  return $host;
1817 }
1818 
1828 function wfReportTime() {
1829  global $wgRequestTime, $wgShowHostnames;
1830 
1831  $responseTime = round( ( microtime( true ) - $wgRequestTime ) * 1000 );
1832  $reportVars = array( 'wgBackendResponseTime' => $responseTime );
1833  if ( $wgShowHostnames ) {
1834  $reportVars[ 'wgHostname' ] = wfHostname();
1835  }
1836  return Skin::makeVariablesScript( $reportVars );
1837 }
1838 
1854 function wfDebugBacktrace( $limit = 0 ) {
1855  static $disabled = null;
1856 
1857  if ( extension_loaded( 'Zend Optimizer' ) ) {
1858  wfDebug( "Zend Optimizer detected; skipping debug_backtrace for safety.\n" );
1859  return array();
1860  }
1861 
1862  if ( is_null( $disabled ) ) {
1863  $disabled = false;
1864  $functions = explode( ',', ini_get( 'disable_functions' ) );
1865  $functions = array_map( 'trim', $functions );
1866  $functions = array_map( 'strtolower', $functions );
1867  if ( in_array( 'debug_backtrace', $functions ) ) {
1868  wfDebug( "debug_backtrace is in disabled_functions\n" );
1869  $disabled = true;
1870  }
1871  }
1872  if ( $disabled ) {
1873  return array();
1874  }
1875 
1876  if ( $limit && version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
1877  return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit + 1 ), 1 );
1878  } else {
1879  return array_slice( debug_backtrace(), 1 );
1880  }
1881 }
1882 
1888 function wfBacktrace() {
1890 
1891  if ( $wgCommandLineMode ) {
1892  $msg = '';
1893  } else {
1894  $msg = "<ul>\n";
1895  }
1896  $backtrace = wfDebugBacktrace();
1897  foreach ( $backtrace as $call ) {
1898  if ( isset( $call['file'] ) ) {
1899  $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
1900  $file = $f[count( $f ) - 1];
1901  } else {
1902  $file = '-';
1903  }
1904  if ( isset( $call['line'] ) ) {
1905  $line = $call['line'];
1906  } else {
1907  $line = '-';
1908  }
1909  if ( $wgCommandLineMode ) {
1910  $msg .= "$file line $line calls ";
1911  } else {
1912  $msg .= '<li>' . $file . ' line ' . $line . ' calls ';
1913  }
1914  if ( !empty( $call['class'] ) ) {
1915  $msg .= $call['class'] . $call['type'];
1916  }
1917  $msg .= $call['function'] . '()';
1918 
1919  if ( $wgCommandLineMode ) {
1920  $msg .= "\n";
1921  } else {
1922  $msg .= "</li>\n";
1923  }
1924  }
1925  if ( $wgCommandLineMode ) {
1926  $msg .= "\n";
1927  } else {
1928  $msg .= "</ul>\n";
1929  }
1930 
1931  return $msg;
1932 }
1933 
1943 function wfGetCaller( $level = 2 ) {
1944  $backtrace = wfDebugBacktrace( $level + 1 );
1945  if ( isset( $backtrace[$level] ) ) {
1946  return wfFormatStackFrame( $backtrace[$level] );
1947  } else {
1948  return 'unknown';
1949  }
1950 }
1951 
1960 function wfGetAllCallers( $limit = 3 ) {
1961  $trace = array_reverse( wfDebugBacktrace() );
1962  if ( !$limit || $limit > count( $trace ) - 1 ) {
1963  $limit = count( $trace ) - 1;
1964  }
1965  $trace = array_slice( $trace, -$limit - 1, $limit );
1966  return implode( '/', array_map( 'wfFormatStackFrame', $trace ) );
1967 }
1968 
1975 function wfFormatStackFrame( $frame ) {
1976  return isset( $frame['class'] ) ?
1977  $frame['class'] . '::' . $frame['function'] :
1978  $frame['function'];
1979 }
1980 
1981 /* Some generic result counters, pulled out of SearchEngine */
1982 
1990 function wfShowingResults( $offset, $limit ) {
1991  return wfMessage( 'showingresults' )->numParams( $limit, $offset + 1 )->parse();
1992 }
1993 
2005 function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
2006  wfDeprecated( __METHOD__, '1.19' );
2007 
2008  global $wgLang;
2009 
2010  $query = wfCgiToArray( $query );
2011 
2012  if ( is_object( $link ) ) {
2013  $title = $link;
2014  } else {
2016  if ( is_null( $title ) ) {
2017  return false;
2018  }
2019  }
2020 
2021  return $wgLang->viewPrevNext( $title, $offset, $limit, $query, $atend );
2022 }
2023 
2031 function wfClientAcceptsGzip( $force = false ) {
2032  static $result = null;
2033  if ( $result === null || $force ) {
2034  $result = false;
2035  if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
2036  # @todo FIXME: We may want to blacklist some broken browsers
2037  $m = array();
2038  if ( preg_match(
2039  '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
2040  $_SERVER['HTTP_ACCEPT_ENCODING'],
2041  $m
2042  )
2043  ) {
2044  if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) {
2045  $result = false;
2046  return $result;
2047  }
2048  wfDebug( "wfClientAcceptsGzip: client accepts gzip.\n" );
2049  $result = true;
2050  }
2051  }
2052  }
2053  return $result;
2054 }
2055 
2065 function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
2066  global $wgRequest;
2067  return $wgRequest->getLimitOffset( $deflimit, $optionname );
2068 }
2069 
2079 function wfEscapeWikiText( $text ) {
2080  static $repl = null, $repl2 = null;
2081  if ( $repl === null ) {
2082  $repl = array(
2083  '"' => '&#34;', '&' => '&#38;', "'" => '&#39;', '<' => '&#60;',
2084  '=' => '&#61;', '>' => '&#62;', '[' => '&#91;', ']' => '&#93;',
2085  '{' => '&#123;', '|' => '&#124;', '}' => '&#125;', ';' => '&#59;',
2086  "\n#" => "\n&#35;", "\r#" => "\r&#35;",
2087  "\n*" => "\n&#42;", "\r*" => "\r&#42;",
2088  "\n:" => "\n&#58;", "\r:" => "\r&#58;",
2089  "\n " => "\n&#32;", "\r " => "\r&#32;",
2090  "\n\n" => "\n&#10;", "\r\n" => "&#13;\n",
2091  "\n\r" => "\n&#13;", "\r\r" => "\r&#13;",
2092  "\n\t" => "\n&#9;", "\r\t" => "\r&#9;", // "\n\t\n" is treated like "\n\n"
2093  "\n----" => "\n&#45;---", "\r----" => "\r&#45;---",
2094  '__' => '_&#95;', '://' => '&#58;//',
2095  );
2096 
2097  // We have to catch everything "\s" matches in PCRE
2098  foreach ( array( 'ISBN', 'RFC', 'PMID' ) as $magic ) {
2099  $repl["$magic "] = "$magic&#32;";
2100  $repl["$magic\t"] = "$magic&#9;";
2101  $repl["$magic\r"] = "$magic&#13;";
2102  $repl["$magic\n"] = "$magic&#10;";
2103  $repl["$magic\f"] = "$magic&#12;";
2104  }
2105 
2106  // And handle protocols that don't use "://"
2107  global $wgUrlProtocols;
2108  $repl2 = array();
2109  foreach ( $wgUrlProtocols as $prot ) {
2110  if ( substr( $prot, -1 ) === ':' ) {
2111  $repl2[] = preg_quote( substr( $prot, 0, -1 ), '/' );
2112  }
2113  }
2114  $repl2 = $repl2 ? '/\b(' . join( '|', $repl2 ) . '):/i' : '/^(?!)/';
2115  }
2116  $text = substr( strtr( "\n$text", $repl ), 1 );
2117  $text = preg_replace( $repl2, '$1&#58;', $text );
2118  return $text;
2119 }
2120 
2126 function wfTime() {
2127  wfDeprecated( __FUNCTION__, '1.22' );
2128  return microtime( true );
2129 }
2130 
2141 function wfSetVar( &$dest, $source, $force = false ) {
2142  $temp = $dest;
2143  if ( !is_null( $source ) || $force ) {
2144  $dest = $source;
2145  }
2146  return $temp;
2147 }
2148 
2158 function wfSetBit( &$dest, $bit, $state = true ) {
2159  $temp = (bool)( $dest & $bit );
2160  if ( !is_null( $state ) ) {
2161  if ( $state ) {
2162  $dest |= $bit;
2163  } else {
2164  $dest &= ~$bit;
2165  }
2166  }
2167  return $temp;
2168 }
2169 
2176 function wfVarDump( $var ) {
2177  global $wgOut;
2178  $s = str_replace( "\n", "<br />\n", var_export( $var, true ) . "\n" );
2179  if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) {
2180  print $s;
2181  } else {
2182  $wgOut->addHTML( $s );
2183  }
2184 }
2185 
2193 function wfHttpError( $code, $label, $desc ) {
2194  global $wgOut;
2195  $wgOut->disable();
2196  header( "HTTP/1.0 $code $label" );
2197  header( "Status: $code $label" );
2198  $wgOut->sendCacheControl();
2199 
2200  header( 'Content-type: text/html; charset=utf-8' );
2201  print "<!doctype html>" .
2202  '<html><head><title>' .
2203  htmlspecialchars( $label ) .
2204  '</title></head><body><h1>' .
2205  htmlspecialchars( $label ) .
2206  '</h1><p>' .
2207  nl2br( htmlspecialchars( $desc ) ) .
2208  "</p></body></html>\n";
2209 }
2210 
2228 function wfResetOutputBuffers( $resetGzipEncoding = true ) {
2229  if ( $resetGzipEncoding ) {
2230  // Suppress Content-Encoding and Content-Length
2231  // headers from 1.10+s wfOutputHandler
2232  global $wgDisableOutputCompression;
2233  $wgDisableOutputCompression = true;
2234  }
2235  while ( $status = ob_get_status() ) {
2236  if ( $status['type'] == 0 /* PHP_OUTPUT_HANDLER_INTERNAL */ ) {
2237  // Probably from zlib.output_compression or other
2238  // PHP-internal setting which can't be removed.
2239  //
2240  // Give up, and hope the result doesn't break
2241  // output behavior.
2242  break;
2243  }
2244  if ( !ob_end_clean() ) {
2245  // Could not remove output buffer handler; abort now
2246  // to avoid getting in some kind of infinite loop.
2247  break;
2248  }
2249  if ( $resetGzipEncoding ) {
2250  if ( $status['name'] == 'ob_gzhandler' ) {
2251  // Reset the 'Content-Encoding' field set by this handler
2252  // so we can start fresh.
2253  header_remove( 'Content-Encoding' );
2254  break;
2255  }
2256  }
2257  }
2258 }
2259 
2272 function wfClearOutputBuffers() {
2273  wfResetOutputBuffers( false );
2274 }
2275 
2284 function wfAcceptToPrefs( $accept, $def = '*/*' ) {
2285  # No arg means accept anything (per HTTP spec)
2286  if ( !$accept ) {
2287  return array( $def => 1.0 );
2288  }
2289 
2290  $prefs = array();
2291 
2292  $parts = explode( ',', $accept );
2293 
2294  foreach ( $parts as $part ) {
2295  # @todo FIXME: Doesn't deal with params like 'text/html; level=1'
2296  $values = explode( ';', trim( $part ) );
2297  $match = array();
2298  if ( count( $values ) == 1 ) {
2299  $prefs[$values[0]] = 1.0;
2300  } elseif ( preg_match( '/q\s*=\s*(\d*\.\d+)/', $values[1], $match ) ) {
2301  $prefs[$values[0]] = floatval( $match[1] );
2302  }
2303  }
2304 
2305  return $prefs;
2306 }
2307 
2320 function mimeTypeMatch( $type, $avail ) {
2321  if ( array_key_exists( $type, $avail ) ) {
2322  return $type;
2323  } else {
2324  $parts = explode( '/', $type );
2325  if ( array_key_exists( $parts[0] . '/*', $avail ) ) {
2326  return $parts[0] . '/*';
2327  } elseif ( array_key_exists( '*/*', $avail ) ) {
2328  return '*/*';
2329  } else {
2330  return null;
2331  }
2332  }
2333 }
2334 
2348 function wfNegotiateType( $cprefs, $sprefs ) {
2349  $combine = array();
2350 
2351  foreach ( array_keys( $sprefs ) as $type ) {
2352  $parts = explode( '/', $type );
2353  if ( $parts[1] != '*' ) {
2354  $ckey = mimeTypeMatch( $type, $cprefs );
2355  if ( $ckey ) {
2356  $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
2357  }
2358  }
2359  }
2360 
2361  foreach ( array_keys( $cprefs ) as $type ) {
2362  $parts = explode( '/', $type );
2363  if ( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) {
2364  $skey = mimeTypeMatch( $type, $sprefs );
2365  if ( $skey ) {
2366  $combine[$type] = $sprefs[$skey] * $cprefs[$type];
2367  }
2368  }
2369  }
2370 
2371  $bestq = 0;
2372  $besttype = null;
2373 
2374  foreach ( array_keys( $combine ) as $type ) {
2375  if ( $combine[$type] > $bestq ) {
2376  $besttype = $type;
2377  $bestq = $combine[$type];
2378  }
2379  }
2380 
2381  return $besttype;
2382 }
2383 
2389 function wfSuppressWarnings( $end = false ) {
2390  static $suppressCount = 0;
2391  static $originalLevel = false;
2392 
2393  if ( $end ) {
2394  if ( $suppressCount ) {
2395  --$suppressCount;
2396  if ( !$suppressCount ) {
2397  error_reporting( $originalLevel );
2398  }
2399  }
2400  } else {
2401  if ( !$suppressCount ) {
2402  $originalLevel = error_reporting( E_ALL & ~(
2403  E_WARNING |
2404  E_NOTICE |
2405  E_USER_WARNING |
2406  E_USER_NOTICE |
2407  E_DEPRECATED |
2408  E_USER_DEPRECATED |
2409  E_STRICT
2410  ) );
2411  }
2412  ++$suppressCount;
2413  }
2414 }
2415 
2419 function wfRestoreWarnings() {
2420  wfSuppressWarnings( true );
2421 }
2422 
2423 # Autodetect, convert and provide timestamps of various types
2424 
2428 define( 'TS_UNIX', 0 );
2429 
2433 define( 'TS_MW', 1 );
2434 
2438 define( 'TS_DB', 2 );
2439 
2443 define( 'TS_RFC2822', 3 );
2444 
2450 define( 'TS_ISO_8601', 4 );
2451 
2459 define( 'TS_EXIF', 5 );
2460 
2464 define( 'TS_ORACLE', 6 );
2465 
2469 define( 'TS_POSTGRES', 7 );
2470 
2474 define( 'TS_ISO_8601_BASIC', 9 );
2475 
2485 function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
2486  try {
2487  $timestamp = new MWTimestamp( $ts );
2488  return $timestamp->getTimestamp( $outputtype );
2489  } catch ( TimestampException $e ) {
2490  wfDebug( "wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n" );
2491  return false;
2492  }
2493 }
2494 
2503 function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
2504  if ( is_null( $ts ) ) {
2505  return null;
2506  } else {
2507  return wfTimestamp( $outputtype, $ts );
2508  }
2509 }
2510 
2516 function wfTimestampNow() {
2517  # return NOW
2518  return wfTimestamp( TS_MW, time() );
2519 }
2520 
2526 function wfIsWindows() {
2527  static $isWindows = null;
2528  if ( $isWindows === null ) {
2529  $isWindows = substr( php_uname(), 0, 7 ) == 'Windows';
2530  }
2531  return $isWindows;
2532 }
2533 
2539 function wfIsHHVM() {
2540  return defined( 'HHVM_VERSION' );
2541 }
2542 
2549 function swap( &$x, &$y ) {
2550  $z = $x;
2551  $x = $y;
2552  $y = $z;
2553 }
2554 
2566 function wfTempDir() {
2567  global $wgTmpDirectory;
2568 
2569  if ( $wgTmpDirectory !== false ) {
2570  return $wgTmpDirectory;
2571  }
2572 
2573  $tmpDir = array_map( "getenv", array( 'TMPDIR', 'TMP', 'TEMP' ) );
2574 
2575  foreach ( $tmpDir as $tmp ) {
2576  if ( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
2577  return $tmp;
2578  }
2579  }
2580  return sys_get_temp_dir();
2581 }
2582 
2592 function wfMkdirParents( $dir, $mode = null, $caller = null ) {
2593  global $wgDirectoryMode;
2594 
2595  if ( FileBackend::isStoragePath( $dir ) ) { // sanity
2596  throw new MWException( __FUNCTION__ . " given storage path '$dir'." );
2597  }
2598 
2599  if ( !is_null( $caller ) ) {
2600  wfDebug( "$caller: called wfMkdirParents($dir)\n" );
2601  }
2602 
2603  if ( strval( $dir ) === '' || ( file_exists( $dir ) && is_dir( $dir ) ) ) {
2604  return true;
2605  }
2606 
2607  $dir = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $dir );
2608 
2609  if ( is_null( $mode ) ) {
2610  $mode = $wgDirectoryMode;
2611  }
2612 
2613  // Turn off the normal warning, we're doing our own below
2615  $ok = mkdir( $dir, $mode, true ); // PHP5 <3
2617 
2618  if ( !$ok ) {
2619  //directory may have been created on another request since we last checked
2620  if ( is_dir( $dir ) ) {
2621  return true;
2622  }
2623 
2624  // PHP doesn't report the path in its warning message, so add our own to aid in diagnosis.
2625  wfLogWarning( sprintf( "failed to mkdir \"%s\" mode 0%o", $dir, $mode ) );
2626  }
2627  return $ok;
2628 }
2629 
2634 function wfRecursiveRemoveDir( $dir ) {
2635  wfDebug( __FUNCTION__ . "( $dir )\n" );
2636  // taken from http://de3.php.net/manual/en/function.rmdir.php#98622
2637  if ( is_dir( $dir ) ) {
2638  $objects = scandir( $dir );
2639  foreach ( $objects as $object ) {
2640  if ( $object != "." && $object != ".." ) {
2641  if ( filetype( $dir . '/' . $object ) == "dir" ) {
2642  wfRecursiveRemoveDir( $dir . '/' . $object );
2643  } else {
2644  unlink( $dir . '/' . $object );
2645  }
2646  }
2647  }
2648  reset( $objects );
2649  rmdir( $dir );
2650  }
2651 }
2652 
2659 function wfPercent( $nr, $acc = 2, $round = true ) {
2660  $ret = sprintf( "%.${acc}f", $nr );
2661  return $round ? round( $ret, $acc ) . '%' : "$ret%";
2662 }
2663 
2687 function wfIniGetBool( $setting ) {
2688  $val = strtolower( ini_get( $setting ) );
2689  // 'on' and 'true' can't have whitespace around them, but '1' can.
2690  return $val == 'on'
2691  || $val == 'true'
2692  || $val == 'yes'
2693  || preg_match( "/^\s*[+-]?0*[1-9]/", $val ); // approx C atoi() function
2694 }
2695 
2707 function wfEscapeShellArg( /*...*/ ) {
2709 
2710  $args = func_get_args();
2711  $first = true;
2712  $retVal = '';
2713  foreach ( $args as $arg ) {
2714  if ( !$first ) {
2715  $retVal .= ' ';
2716  } else {
2717  $first = false;
2718  }
2719 
2720  if ( wfIsWindows() ) {
2721  // Escaping for an MSVC-style command line parser and CMD.EXE
2722  // @codingStandardsIgnoreStart For long URLs
2723  // Refs:
2724  // * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html
2725  // * http://technet.microsoft.com/en-us/library/cc723564.aspx
2726  // * Bug #13518
2727  // * CR r63214
2728  // Double the backslashes before any double quotes. Escape the double quotes.
2729  // @codingStandardsIgnoreEnd
2730  $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE );
2731  $arg = '';
2732  $iteration = 0;
2733  foreach ( $tokens as $token ) {
2734  if ( $iteration % 2 == 1 ) {
2735  // Delimiter, a double quote preceded by zero or more slashes
2736  $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"';
2737  } elseif ( $iteration % 4 == 2 ) {
2738  // ^ in $token will be outside quotes, need to be escaped
2739  $arg .= str_replace( '^', '^^', $token );
2740  } else { // $iteration % 4 == 0
2741  // ^ in $token will appear inside double quotes, so leave as is
2742  $arg .= $token;
2743  }
2744  $iteration++;
2745  }
2746  // Double the backslashes before the end of the string, because
2747  // we will soon add a quote
2748  $m = array();
2749  if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
2750  $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
2751  }
2752 
2753  // Add surrounding quotes
2754  $retVal .= '"' . $arg . '"';
2755  } else {
2756  $retVal .= escapeshellarg( $arg );
2757  }
2758  }
2759  return $retVal;
2760 }
2761 
2768 function wfShellExecDisabled() {
2769  static $disabled = null;
2770  if ( is_null( $disabled ) ) {
2771  $disabled = false;
2772  if ( wfIniGetBool( 'safe_mode' ) ) {
2773  wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
2774  $disabled = 'safemode';
2775  } else {
2776  $functions = explode( ',', ini_get( 'disable_functions' ) );
2777  $functions = array_map( 'trim', $functions );
2778  $functions = array_map( 'strtolower', $functions );
2779  if ( in_array( 'proc_open', $functions ) ) {
2780  wfDebug( "proc_open is in disabled_functions\n" );
2781  $disabled = 'disabled';
2782  }
2783  }
2784  }
2785  return $disabled;
2786 }
2787 
2806 function wfShellExec( $cmd, &$retval = null, $environ = array(),
2807  $limits = array(), $options = array()
2808 ) {
2809  global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
2810  $wgMaxShellWallClockTime, $wgShellCgroup;
2811 
2812  $disabled = wfShellExecDisabled();
2813  if ( $disabled ) {
2814  $retval = 1;
2815  return $disabled == 'safemode' ?
2816  'Unable to run external programs in safe mode.' :
2817  'Unable to run external programs, proc_open() is disabled.';
2818  }
2819 
2820  $includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
2821 
2823 
2824  $envcmd = '';
2825  foreach ( $environ as $k => $v ) {
2826  if ( wfIsWindows() ) {
2827  /* Surrounding a set in quotes (method used by wfEscapeShellArg) makes the quotes themselves
2828  * appear in the environment variable, so we must use carat escaping as documented in
2829  * http://technet.microsoft.com/en-us/library/cc723564.aspx
2830  * Note however that the quote isn't listed there, but is needed, and the parentheses
2831  * are listed there but doesn't appear to need it.
2832  */
2833  $envcmd .= "set $k=" . preg_replace( '/([&|()<>^"])/', '^\\1', $v ) . '&& ';
2834  } else {
2835  /* Assume this is a POSIX shell, thus required to accept variable assignments before the command
2836  * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_09_01
2837  */
2838  $envcmd .= "$k=" . escapeshellarg( $v ) . ' ';
2839  }
2840  }
2841  $cmd = $envcmd . $cmd;
2842 
2843  $useLogPipe = false;
2844  if ( php_uname( 's' ) == 'Linux' ) {
2845  $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
2846  if ( isset( $limits['walltime'] ) ) {
2847  $wallTime = intval( $limits['walltime'] );
2848  } elseif ( isset( $limits['time'] ) ) {
2849  $wallTime = $time;
2850  } else {
2851  $wallTime = intval( $wgMaxShellWallClockTime );
2852  }
2853  $mem = intval ( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
2854  $filesize = intval ( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
2855 
2856  if ( $time > 0 || $mem > 0 || $filesize > 0 || $wallTime > 0 ) {
2857  $cmd = '/bin/bash ' . escapeshellarg( "$IP/includes/limit.sh" ) . ' ' .
2858  escapeshellarg( $cmd ) . ' ' .
2859  escapeshellarg(
2860  "MW_INCLUDE_STDERR=" . ( $includeStderr ? '1' : '' ) . ';' .
2861  "MW_CPU_LIMIT=$time; " .
2862  'MW_CGROUP=' . escapeshellarg( $wgShellCgroup ) . '; ' .
2863  "MW_MEM_LIMIT=$mem; " .
2864  "MW_FILE_SIZE_LIMIT=$filesize; " .
2865  "MW_WALL_CLOCK_LIMIT=$wallTime; " .
2866  "MW_USE_LOG_PIPE=yes"
2867  );
2868  $useLogPipe = true;
2869  } elseif ( $includeStderr ) {
2870  $cmd .= ' 2>&1';
2871  }
2872  } elseif ( $includeStderr ) {
2873  $cmd .= ' 2>&1';
2874  }
2875  wfDebug( "wfShellExec: $cmd\n" );
2876 
2877  $desc = array(
2878  0 => array( 'file', 'php://stdin', 'r' ),
2879  1 => array( 'pipe', 'w' ),
2880  2 => array( 'file', 'php://stderr', 'w' ) );
2881  if ( $useLogPipe ) {
2882  $desc[3] = array( 'pipe', 'w' );
2883  }
2884  $pipes = null;
2885  $proc = proc_open( $cmd, $desc, $pipes );
2886  if ( !$proc ) {
2887  wfDebugLog( 'exec', "proc_open() failed: $cmd" );
2888  $retval = -1;
2889  return '';
2890  }
2891  $outBuffer = $logBuffer = '';
2892  $emptyArray = array();
2893  $status = false;
2894  $logMsg = false;
2895 
2896  // According to the documentation, it is possible for stream_select()
2897  // to fail due to EINTR. I haven't managed to induce this in testing
2898  // despite sending various signals. If it did happen, the error
2899  // message would take the form:
2900  //
2901  // stream_select(): unable to select [4]: Interrupted system call (max_fd=5)
2902  //
2903  // where [4] is the value of the macro EINTR and "Interrupted system
2904  // call" is string which according to the Linux manual is "possibly"
2905  // localised according to LC_MESSAGES.
2906  $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
2907  $eintrMessage = "stream_select(): unable to select [$eintr]";
2908 
2909  // Build a table mapping resource IDs to pipe FDs to work around a
2910  // PHP 5.3 issue in which stream_select() does not preserve array keys
2911  // <https://bugs.php.net/bug.php?id=53427>.
2912  $fds = array();
2913  foreach ( $pipes as $fd => $pipe ) {
2914  $fds[(int)$pipe] = $fd;
2915  }
2916 
2917  $running = true;
2918  $timeout = null;
2919  $numReadyPipes = 0;
2920 
2921  while ( $running === true || $numReadyPipes !== 0 ) {
2922  if ( $running ) {
2923  $status = proc_get_status( $proc );
2924  // If the process has terminated, switch to nonblocking selects
2925  // for getting any data still waiting to be read.
2926  if ( !$status['running'] ) {
2927  $running = false;
2928  $timeout = 0;
2929  }
2930  }
2931 
2932  $readyPipes = $pipes;
2933 
2934  // Clear last error
2935  @trigger_error( '' );
2936  $numReadyPipes = @stream_select( $readyPipes, $emptyArray, $emptyArray, $timeout );
2937  if ( $numReadyPipes === false ) {
2938  $error = error_get_last();
2939  if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
2940  continue;
2941  } else {
2942  trigger_error( $error['message'], E_USER_WARNING );
2943  $logMsg = $error['message'];
2944  break;
2945  }
2946  }
2947  foreach ( $readyPipes as $pipe ) {
2948  $block = fread( $pipe, 65536 );
2949  $fd = $fds[(int)$pipe];
2950  if ( $block === '' ) {
2951  // End of file
2952  fclose( $pipes[$fd] );
2953  unset( $pipes[$fd] );
2954  if ( !$pipes ) {
2955  break 2;
2956  }
2957  } elseif ( $block === false ) {
2958  // Read error
2959  $logMsg = "Error reading from pipe";
2960  break 2;
2961  } elseif ( $fd == 1 ) {
2962  // From stdout
2963  $outBuffer .= $block;
2964  } elseif ( $fd == 3 ) {
2965  // From log FD
2966  $logBuffer .= $block;
2967  if ( strpos( $block, "\n" ) !== false ) {
2968  $lines = explode( "\n", $logBuffer );
2969  $logBuffer = array_pop( $lines );
2970  foreach ( $lines as $line ) {
2971  wfDebugLog( 'exec', $line );
2972  }
2973  }
2974  }
2975  }
2976  }
2977 
2978  foreach ( $pipes as $pipe ) {
2979  fclose( $pipe );
2980  }
2981 
2982  // Use the status previously collected if possible, since proc_get_status()
2983  // just calls waitpid() which will not return anything useful the second time.
2984  if ( $running ) {
2985  $status = proc_get_status( $proc );
2986  }
2987 
2988  if ( $logMsg !== false ) {
2989  // Read/select error
2990  $retval = -1;
2991  proc_close( $proc );
2992  } elseif ( $status['signaled'] ) {
2993  $logMsg = "Exited with signal {$status['termsig']}";
2994  $retval = 128 + $status['termsig'];
2995  proc_close( $proc );
2996  } else {
2997  if ( $status['running'] ) {
2998  $retval = proc_close( $proc );
2999  } else {
3000  $retval = $status['exitcode'];
3001  proc_close( $proc );
3002  }
3003  if ( $retval == 127 ) {
3004  $logMsg = "Possibly missing executable file";
3005  } elseif ( $retval >= 129 && $retval <= 192 ) {
3006  $logMsg = "Probably exited with signal " . ( $retval - 128 );
3007  }
3008  }
3009 
3010  if ( $logMsg !== false ) {
3011  wfDebugLog( 'exec', "$logMsg: $cmd" );
3012  }
3013 
3014  return $outBuffer;
3015 }
3016 
3031 function wfShellExecWithStderr( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
3032  return wfShellExec( $cmd, $retval, $environ, $limits, array( 'duplicateStderr' => true ) );
3033 }
3034 
3039 function wfInitShellLocale() {
3040  static $done = false;
3041  if ( $done ) {
3042  return;
3043  }
3044  $done = true;
3045  global $wgShellLocale;
3046  if ( !wfIniGetBool( 'safe_mode' ) ) {
3047  putenv( "LC_CTYPE=$wgShellLocale" );
3048  setlocale( LC_CTYPE, $wgShellLocale );
3049  }
3050 }
3051 
3057 function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) {
3058  return wfShellWikiCmd( $script, $parameters, $options );
3059 }
3060 
3073 function wfShellWikiCmd( $script, array $parameters = array(), array $options = array() ) {
3074  global $wgPhpCli;
3075  // Give site config file a chance to run the script in a wrapper.
3076  // The caller may likely want to call wfBasename() on $script.
3077  wfRunHooks( 'wfShellWikiCmd', array( &$script, &$parameters, &$options ) );
3078  $cmd = isset( $options['php'] ) ? array( $options['php'] ) : array( $wgPhpCli );
3079  if ( isset( $options['wrapper'] ) ) {
3080  $cmd[] = $options['wrapper'];
3081  }
3082  $cmd[] = $script;
3083  // Escape each parameter for shell
3084  return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
3085 }
3086 
3097 function wfMerge( $old, $mine, $yours, &$result ) {
3098  global $wgDiff3;
3099 
3100  # This check may also protect against code injection in
3101  # case of broken installations.
3103  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
3105 
3106  if ( !$haveDiff3 ) {
3107  wfDebug( "diff3 not found\n" );
3108  return false;
3109  }
3110 
3111  # Make temporary files
3112  $td = wfTempDir();
3113  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3114  $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
3115  $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
3116 
3117  # NOTE: diff3 issues a warning to stderr if any of the files does not end with
3118  # a newline character. To avoid this, we normalize the trailing whitespace before
3119  # creating the diff.
3120 
3121  fwrite( $oldtextFile, rtrim( $old ) . "\n" );
3122  fclose( $oldtextFile );
3123  fwrite( $mytextFile, rtrim( $mine ) . "\n" );
3124  fclose( $mytextFile );
3125  fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
3126  fclose( $yourtextFile );
3127 
3128  # Check for a conflict
3129  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
3130  wfEscapeShellArg( $mytextName ) . ' ' .
3131  wfEscapeShellArg( $oldtextName ) . ' ' .
3132  wfEscapeShellArg( $yourtextName );
3133  $handle = popen( $cmd, 'r' );
3134 
3135  if ( fgets( $handle, 1024 ) ) {
3136  $conflict = true;
3137  } else {
3138  $conflict = false;
3139  }
3140  pclose( $handle );
3141 
3142  # Merge differences
3143  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
3144  wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
3145  $handle = popen( $cmd, 'r' );
3146  $result = '';
3147  do {
3148  $data = fread( $handle, 8192 );
3149  if ( strlen( $data ) == 0 ) {
3150  break;
3151  }
3152  $result .= $data;
3153  } while ( true );
3154  pclose( $handle );
3155  unlink( $mytextName );
3156  unlink( $oldtextName );
3157  unlink( $yourtextName );
3158 
3159  if ( $result === '' && $old !== '' && !$conflict ) {
3160  wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
3161  $conflict = true;
3162  }
3163  return !$conflict;
3164 }
3165 
3175 function wfDiff( $before, $after, $params = '-u' ) {
3176  if ( $before == $after ) {
3177  return '';
3178  }
3179 
3180  global $wgDiff;
3182  $haveDiff = $wgDiff && file_exists( $wgDiff );
3184 
3185  # This check may also protect against code injection in
3186  # case of broken installations.
3187  if ( !$haveDiff ) {
3188  wfDebug( "diff executable not found\n" );
3189  $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) );
3190  $format = new UnifiedDiffFormatter();
3191  return $format->format( $diffs );
3192  }
3193 
3194  # Make temporary files
3195  $td = wfTempDir();
3196  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3197  $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' );
3198 
3199  fwrite( $oldtextFile, $before );
3200  fclose( $oldtextFile );
3201  fwrite( $newtextFile, $after );
3202  fclose( $newtextFile );
3203 
3204  // Get the diff of the two files
3205  $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName );
3206 
3207  $h = popen( $cmd, 'r' );
3208 
3209  $diff = '';
3210 
3211  do {
3212  $data = fread( $h, 8192 );
3213  if ( strlen( $data ) == 0 ) {
3214  break;
3215  }
3216  $diff .= $data;
3217  } while ( true );
3218 
3219  // Clean up
3220  pclose( $h );
3221  unlink( $oldtextName );
3222  unlink( $newtextName );
3223 
3224  // Kill the --- and +++ lines. They're not useful.
3225  $diff_lines = explode( "\n", $diff );
3226  if ( strpos( $diff_lines[0], '---' ) === 0 ) {
3227  unset( $diff_lines[0] );
3228  }
3229  if ( strpos( $diff_lines[1], '+++' ) === 0 ) {
3230  unset( $diff_lines[1] );
3231  }
3232 
3233  $diff = implode( "\n", $diff_lines );
3234 
3235  return $diff;
3236 }
3237 
3254 function wfUsePHP( $req_ver ) {
3255  $php_ver = PHP_VERSION;
3256 
3257  if ( version_compare( $php_ver, (string)$req_ver, '<' ) ) {
3258  throw new MWException( "PHP $req_ver required--this is only $php_ver" );
3259  }
3260 }
3261 
3284 function wfUseMW( $req_ver ) {
3285  global $wgVersion;
3286 
3287  if ( version_compare( $wgVersion, (string)$req_ver, '<' ) ) {
3288  throw new MWException( "MediaWiki $req_ver required--this is only $wgVersion" );
3289  }
3290 }
3291 
3304 function wfBaseName( $path, $suffix = '' ) {
3305  if ( $suffix == '' ) {
3306  $encSuffix = '';
3307  } else {
3308  $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
3309  }
3310 
3311  $matches = array();
3312  if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
3313  return $matches[1];
3314  } else {
3315  return '';
3316  }
3317 }
3318 
3328 function wfRelativePath( $path, $from ) {
3329  // Normalize mixed input on Windows...
3330  $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
3331  $from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
3332 
3333  // Trim trailing slashes -- fix for drive root
3334  $path = rtrim( $path, DIRECTORY_SEPARATOR );
3335  $from = rtrim( $from, DIRECTORY_SEPARATOR );
3336 
3337  $pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
3338  $against = explode( DIRECTORY_SEPARATOR, $from );
3339 
3340  if ( $pieces[0] !== $against[0] ) {
3341  // Non-matching Windows drive letters?
3342  // Return a full path.
3343  return $path;
3344  }
3345 
3346  // Trim off common prefix
3347  while ( count( $pieces ) && count( $against )
3348  && $pieces[0] == $against[0] ) {
3349  array_shift( $pieces );
3350  array_shift( $against );
3351  }
3352 
3353  // relative dots to bump us to the parent
3354  while ( count( $against ) ) {
3355  array_unshift( $pieces, '..' );
3356  array_shift( $against );
3357  }
3358 
3359  array_push( $pieces, wfBaseName( $path ) );
3360 
3361  return implode( DIRECTORY_SEPARATOR, $pieces );
3362 }
3363 
3379 function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
3380  $lowercase = true, $engine = 'auto'
3381 ) {
3382  $input = (string)$input;
3383  if (
3384  $sourceBase < 2 ||
3385  $sourceBase > 36 ||
3386  $destBase < 2 ||
3387  $destBase > 36 ||
3388  $sourceBase != (int)$sourceBase ||
3389  $destBase != (int)$destBase ||
3390  $pad != (int)$pad ||
3391  !preg_match(
3392  "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i",
3393  $input
3394  )
3395  ) {
3396  return false;
3397  }
3398 
3399  static $baseChars = array(
3400  10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f',
3401  16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l',
3402  22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r',
3403  28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x',
3404  34 => 'y', 35 => 'z',
3405 
3406  '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5,
3407  '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11,
3408  'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17,
3409  'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23,
3410  'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29,
3411  'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35
3412  );
3413 
3414  if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
3415  $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
3416  } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
3417  $decimal = '0';
3418  foreach ( str_split( strtolower( $input ) ) as $char ) {
3419  $decimal = bcmul( $decimal, $sourceBase );
3420  $decimal = bcadd( $decimal, $baseChars[$char] );
3421  }
3422 
3423  for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
3424  $result .= $baseChars[bcmod( $decimal, $destBase )];
3425  }
3426 
3427  $result = strrev( $result );
3428  } else {
3429  $inDigits = array();
3430  foreach ( str_split( strtolower( $input ) ) as $char ) {
3431  $inDigits[] = $baseChars[$char];
3432  }
3433 
3434  // Iterate over the input, modulo-ing out an output digit
3435  // at a time until input is gone.
3436  $result = '';
3437  while ( $inDigits ) {
3438  $work = 0;
3439  $workDigits = array();
3440 
3441  // Long division...
3442  foreach ( $inDigits as $digit ) {
3443  $work *= $sourceBase;
3444  $work += $digit;
3445 
3446  if ( $workDigits || $work >= $destBase ) {
3447  $workDigits[] = (int)( $work / $destBase );
3448  }
3449  $work %= $destBase;
3450  }
3451 
3452  // All that division leaves us with a remainder,
3453  // which is conveniently our next output digit.
3454  $result .= $baseChars[$work];
3455 
3456  // And we continue!
3457  $inDigits = $workDigits;
3458  }
3459 
3460  $result = strrev( $result );
3461  }
3462 
3463  if ( !$lowercase ) {
3464  $result = strtoupper( $result );
3465  }
3466 
3467  return str_pad( $result, $pad, '0', STR_PAD_LEFT );
3468 }
3469 
3475 function wfCheckEntropy() {
3476  return (
3477  ( wfIsWindows() && version_compare( PHP_VERSION, '5.3.3', '>=' ) )
3478  || ini_get( 'session.entropy_file' )
3479  )
3480  && intval( ini_get( 'session.entropy_length' ) ) >= 32;
3481 }
3482 
3487 function wfFixSessionID() {
3488  // If the cookie or session id is already set we already have a session and should abort
3489  if ( isset( $_COOKIE[session_name()] ) || session_id() ) {
3490  return;
3491  }
3492 
3493  // PHP's built-in session entropy is enabled if:
3494  // - entropy_file is set or you're on Windows with php 5.3.3+
3495  // - AND entropy_length is > 0
3496  // We treat it as disabled if it doesn't have an entropy length of at least 32
3497  $entropyEnabled = wfCheckEntropy();
3498 
3499  // If built-in entropy is not enabled or not sufficient override PHP's
3500  // built in session id generation code
3501  if ( !$entropyEnabled ) {
3502  wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, " .
3503  "overriding session id generation using our cryptrand source.\n" );
3504  session_id( MWCryptRand::generateHex( 32 ) );
3505  }
3506 }
3507 
3513 function wfResetSessionID() {
3514  global $wgCookieSecure;
3515  $oldSessionId = session_id();
3516  $cookieParams = session_get_cookie_params();
3517  if ( wfCheckEntropy() && $wgCookieSecure == $cookieParams['secure'] ) {
3518  session_regenerate_id( false );
3519  } else {
3520  $tmp = $_SESSION;
3521  session_destroy();
3523  $_SESSION = $tmp;
3524  }
3525  $newSessionId = session_id();
3526  wfRunHooks( 'ResetSessionID', array( $oldSessionId, $newSessionId ) );
3527 }
3528 
3534 function wfSetupSession( $sessionId = false ) {
3535  global $wgSessionsInMemcached, $wgSessionsInObjectCache, $wgCookiePath, $wgCookieDomain,
3536  $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler;
3537  if ( $wgSessionsInObjectCache || $wgSessionsInMemcached ) {
3539  } elseif ( $wgSessionHandler && $wgSessionHandler != ini_get( 'session.save_handler' ) ) {
3540  # Only set this if $wgSessionHandler isn't null and session.save_handler
3541  # hasn't already been set to the desired value (that causes errors)
3542  ini_set( 'session.save_handler', $wgSessionHandler );
3543  }
3544  session_set_cookie_params(
3545  0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly );
3546  session_cache_limiter( 'private, must-revalidate' );
3547  if ( $sessionId ) {
3548  session_id( $sessionId );
3549  } else {
3550  wfFixSessionID();
3551  }
3553  session_start();
3555 }
3556 
3563 function wfGetPrecompiledData( $name ) {
3564  global $IP;
3565 
3566  $file = "$IP/serialized/$name";
3567  if ( file_exists( $file ) ) {
3568  $blob = file_get_contents( $file );
3569  if ( $blob ) {
3570  return unserialize( $blob );
3571  }
3572  }
3573  return false;
3574 }
3575 
3582 function wfMemcKey( /*...*/ ) {
3583  global $wgCachePrefix;
3584  $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
3585  $args = func_get_args();
3586  $key = $prefix . ':' . implode( ':', $args );
3587  $key = str_replace( ' ', '_', $key );
3588  return $key;
3589 }
3590 
3599 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
3600  $args = array_slice( func_get_args(), 2 );
3601  if ( $prefix ) {
3602  $key = "$db-$prefix:" . implode( ':', $args );
3603  } else {
3604  $key = $db . ':' . implode( ':', $args );
3605  }
3606  return str_replace( ' ', '_', $key );
3607 }
3608 
3615 function wfWikiID() {
3616  global $wgDBprefix, $wgDBname;
3617  if ( $wgDBprefix ) {
3618  return "$wgDBname-$wgDBprefix";
3619  } else {
3620  return $wgDBname;
3621  }
3622 }
3623 
3631 function wfSplitWikiID( $wiki ) {
3632  $bits = explode( '-', $wiki, 2 );
3633  if ( count( $bits ) < 2 ) {
3634  $bits[] = '';
3635  }
3636  return $bits;
3637 }
3638 
3661 function &wfGetDB( $db, $groups = array(), $wiki = false ) {
3662  return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
3663 }
3664 
3671 function wfGetLB( $wiki = false ) {
3672  return wfGetLBFactory()->getMainLB( $wiki );
3673 }
3674 
3680 function &wfGetLBFactory() {
3681  return LBFactory::singleton();
3682 }
3683 
3704 function wfFindFile( $title, $options = array() ) {
3705  return RepoGroup::singleton()->findFile( $title, $options );
3706 }
3707 
3715 function wfLocalFile( $title ) {
3716  return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
3717 }
3718 
3725 function wfQueriesMustScale() {
3726  global $wgMiserMode;
3727  return $wgMiserMode
3728  || ( SiteStats::pages() > 100000
3729  && SiteStats::edits() > 1000000
3730  && SiteStats::users() > 10000 );
3731 }
3732 
3741 function wfScript( $script = 'index' ) {
3742  global $wgScriptPath, $wgScriptExtension, $wgScript, $wgLoadScript;
3743  if ( $script === 'index' ) {
3744  return $wgScript;
3745  } elseif ( $script === 'load' ) {
3746  return $wgLoadScript;
3747  } else {
3748  return "{$wgScriptPath}/{$script}{$wgScriptExtension}";
3749  }
3750 }
3751 
3757 function wfGetScriptUrl() {
3758  if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
3759  #
3760  # as it was called, minus the query string.
3761  #
3762  # Some sites use Apache rewrite rules to handle subdomains,
3763  # and have PHP set up in a weird way that causes PHP_SELF
3764  # to contain the rewritten URL instead of the one that the
3765  # outside world sees.
3766  #
3767  # If in this mode, use SCRIPT_URL instead, which mod_rewrite
3768  # provides containing the "before" URL.
3769  return $_SERVER['SCRIPT_NAME'];
3770  } else {
3771  return $_SERVER['URL'];
3772  }
3773 }
3774 
3782 function wfBoolToStr( $value ) {
3783  return $value ? 'true' : 'false';
3784 }
3785 
3791 function wfGetNull() {
3792  return wfIsWindows() ? 'NUL' : '/dev/null';
3793 }
3794 
3806 function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
3807  if ( $cluster !== false ) {
3808  $lb = wfGetLBFactory()->getExternalLB( $cluster );
3809  } else {
3810  $lb = wfGetLB( $wiki );
3811  }
3812 
3813  // bug 27975 - Don't try to wait for slaves if there are none
3814  // Prevents permission error when getting master position
3815  if ( $lb->getServerCount() > 1 ) {
3816  $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
3817  $pos = $dbw->getMasterPos();
3818  // The DBMS may not support getMasterPos() or the whole
3819  // load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
3820  if ( $pos !== false ) {
3821  $lb->waitForAll( $pos );
3822  }
3823  }
3824 }
3825 
3833 function wfCountDown( $seconds ) {
3834  for ( $i = $seconds; $i >= 0; $i-- ) {
3835  if ( $i != $seconds ) {
3836  echo str_repeat( "\x08", strlen( $i + 1 ) );
3837  }
3838  echo $i;
3839  flush();
3840  if ( $i ) {
3841  sleep( 1 );
3842  }
3843  }
3844  echo "\n";
3845 }
3846 
3855 function wfStripIllegalFilenameChars( $name ) {
3856  global $wgIllegalFileChars;
3857  $illegalFileChars = $wgIllegalFileChars ? "|[" . $wgIllegalFileChars . "]" : '';
3858  $name = wfBaseName( $name );
3859  $name = preg_replace(
3860  "/[^" . Title::legalChars() . "]" . $illegalFileChars . "/",
3861  '-',
3862  $name
3863  );
3864  return $name;
3865 }
3866 
3872 function wfMemoryLimit() {
3873  global $wgMemoryLimit;
3874  $memlimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
3875  if ( $memlimit != -1 ) {
3876  $conflimit = wfShorthandToInteger( $wgMemoryLimit );
3877  if ( $conflimit == -1 ) {
3878  wfDebug( "Removing PHP's memory limit\n" );
3880  ini_set( 'memory_limit', $conflimit );
3882  return $conflimit;
3883  } elseif ( $conflimit > $memlimit ) {
3884  wfDebug( "Raising PHP's memory limit to $conflimit bytes\n" );
3886  ini_set( 'memory_limit', $conflimit );
3888  return $conflimit;
3889  }
3890  }
3891  return $memlimit;
3892 }
3893 
3900 function wfShorthandToInteger( $string = '' ) {
3901  $string = trim( $string );
3902  if ( $string === '' ) {
3903  return -1;
3904  }
3905  $last = $string[strlen( $string ) - 1];
3906  $val = intval( $string );
3907  switch ( $last ) {
3908  case 'g':
3909  case 'G':
3910  $val *= 1024;
3911  // break intentionally missing
3912  case 'm':
3913  case 'M':
3914  $val *= 1024;
3915  // break intentionally missing
3916  case 'k':
3917  case 'K':
3918  $val *= 1024;
3919  }
3920 
3921  return $val;
3922 }
3923 
3931 function wfBCP47( $code ) {
3932  $codeSegment = explode( '-', $code );
3933  $codeBCP = array();
3934  foreach ( $codeSegment as $segNo => $seg ) {
3935  // when previous segment is x, it is a private segment and should be lc
3936  if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
3937  $codeBCP[$segNo] = strtolower( $seg );
3938  // ISO 3166 country code
3939  } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
3940  $codeBCP[$segNo] = strtoupper( $seg );
3941  // ISO 15924 script code
3942  } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
3943  $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
3944  // Use lowercase for other cases
3945  } else {
3946  $codeBCP[$segNo] = strtolower( $seg );
3947  }
3948  }
3949  $langCode = implode( '-', $codeBCP );
3950  return $langCode;
3951 }
3952 
3959 function wfGetCache( $inputType ) {
3960  return ObjectCache::getInstance( $inputType );
3961 }
3962 
3968 function wfGetMainCache() {
3971 }
3972 
3978 function wfGetMessageCacheStorage() {
3979  global $wgMessageCacheType;
3980  return ObjectCache::getInstance( $wgMessageCacheType );
3981 }
3982 
3988 function wfGetParserCacheStorage() {
3989  global $wgParserCacheType;
3990  return ObjectCache::getInstance( $wgParserCacheType );
3991 }
3992 
3998 function wfGetLangConverterCacheStorage() {
3999  global $wgLanguageConverterCacheType;
4000  return ObjectCache::getInstance( $wgLanguageConverterCacheType );
4001 }
4002 
4012 function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null ) {
4013  return Hooks::run( $event, $args, $deprecatedVersion );
4014 }
4015 
4030 function wfUnpack( $format, $data, $length = false ) {
4031  if ( $length !== false ) {
4032  $realLen = strlen( $data );
4033  if ( $realLen < $length ) {
4034  throw new MWException( "Tried to use wfUnpack on a "
4035  . "string of length $realLen, but needed one "
4036  . "of at least length $length."
4037  );
4038  }
4039  }
4040 
4042  $result = unpack( $format, $data );
4044 
4045  if ( $result === false ) {
4046  // If it cannot extract the packed data.
4047  throw new MWException( "unpack could not unpack binary data" );
4048  }
4049  return $result;
4050 }
4051 
4066 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
4067  static $badImageCache = null; // based on bad_image_list msg
4068  wfProfileIn( __METHOD__ );
4069 
4070  # Handle redirects
4071  $redirectTitle = RepoGroup::singleton()->checkRedirect( Title::makeTitle( NS_FILE, $name ) );
4072  if ( $redirectTitle ) {
4073  $name = $redirectTitle->getDBkey();
4074  }
4075 
4076  # Run the extension hook
4077  $bad = false;
4078  if ( !wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {
4079  wfProfileOut( __METHOD__ );
4080  return $bad;
4081  }
4082 
4083  $cacheable = ( $blacklist === null );
4084  if ( $cacheable && $badImageCache !== null ) {
4085  $badImages = $badImageCache;
4086  } else { // cache miss
4087  if ( $blacklist === null ) {
4088  $blacklist = wfMessage( 'bad_image_list' )->inContentLanguage()->plain(); // site list
4089  }
4090  # Build the list now
4091  $badImages = array();
4092  $lines = explode( "\n", $blacklist );
4093  foreach ( $lines as $line ) {
4094  # List items only
4095  if ( substr( $line, 0, 1 ) !== '*' ) {
4096  continue;
4097  }
4098 
4099  # Find all links
4100  $m = array();
4101  if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
4102  continue;
4103  }
4104 
4105  $exceptions = array();
4106  $imageDBkey = false;
4107  foreach ( $m[1] as $i => $titleText ) {
4108  $title = Title::newFromText( $titleText );
4109  if ( !is_null( $title ) ) {
4110  if ( $i == 0 ) {
4111  $imageDBkey = $title->getDBkey();
4112  } else {
4113  $exceptions[$title->getPrefixedDBkey()] = true;
4114  }
4115  }
4116  }
4117 
4118  if ( $imageDBkey !== false ) {
4119  $badImages[$imageDBkey] = $exceptions;
4120  }
4121  }
4122  if ( $cacheable ) {
4123  $badImageCache = $badImages;
4124  }
4125  }
4126 
4127  $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
4128  $bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
4129  wfProfileOut( __METHOD__ );
4130  return $bad;
4131 }
4132 
4140 function wfCanIPUseHTTPS( $ip ) {
4141  $canDo = true;
4142  wfRunHooks( 'CanIPUseHTTPS', array( $ip, &$canDo ) );
4143  return !!$canDo;
4144 }
4145 
4153 function wfGetIP() {
4154  wfDeprecated( __METHOD__, '1.19' );
4155  global $wgRequest;
4156  return $wgRequest->getIP();
4157 }
4158 
4167 function wfIsTrustedProxy( $ip ) {
4168  $trusted = wfIsConfiguredProxy( $ip );
4169  wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
4170  return $trusted;
4171 }
4172 
4180 function wfIsConfiguredProxy( $ip ) {
4181  global $wgSquidServers, $wgSquidServersNoPurge;
4182 
4183  // quick check of known proxy servers
4184  $trusted = in_array( $ip, $wgSquidServers )
4185  || in_array( $ip, $wgSquidServersNoPurge );
4186 
4187  if ( !$trusted ) {
4188  // slightly slower check to see if the ip is listed directly or in a CIDR
4189  // block in $wgSquidServersNoPurge
4190  foreach ( $wgSquidServersNoPurge as $block ) {
4191  if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
4192  $trusted = true;
4193  break;
4194  }
4195  }
4196  }
4197  return $trusted;
4198 }
wfMsgNoTrans
wfMsgNoTrans( $key)
Same as above except doesn't transform the message.
Definition: GlobalFunctions.php:1462
wfMessage
wfMessage( $key)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1401
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:3485
wfGetIP
wfGetIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Definition: GlobalFunctions.php:4151
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:3282
wfArrayInsertAfter
wfArrayInsertAfter(array $array, array $insert, $after)
Insert array into another array after the specified KEY
Definition: GlobalFunctions.php:235
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:552
$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
$time
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1358
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:2657
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:2804
wfResetOutputBuffers
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
Definition: GlobalFunctions.php:2226
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:3929
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:4138
wfMergeErrorArrays
wfMergeErrorArrays()
Merge arrays in the style of getUserPermissionsErrors, with duplicate removal e.g.
Definition: GlobalFunctions.php:213
ParserOutput
Definition: ParserOutput.php:24
wfMsgForContent
wfMsgForContent( $key)
Get a message from anywhere, for the current global language set with $wgLanguageCode.
Definition: GlobalFunctions.php:1495
wfErrorLog
wfErrorLog( $text, $file)
Log to a file without getting "file size exceeded" signals.
Definition: GlobalFunctions.php:1168
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:3055
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:3173
wfMerge
wfMerge( $old, $mine, $yours, &$result)
wfMerge attempts to merge differences between three texts.
Definition: GlobalFunctions.php:3095
wfSetupSession
wfSetupSession( $sessionId=false)
Initialise php session.
Definition: GlobalFunctions.php:3532
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:2590
LBFactory\singleton
static & singleton()
Get an LBFactory instance.
Definition: LBFactory.php:46
wfDebugBacktrace
wfDebugBacktrace( $limit=0)
Safety wrapper for debug_backtrace().
Definition: GlobalFunctions.php:1852
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:2139
wfGetLB
wfGetLB( $wiki=false)
Get a load balancer object.
Definition: GlobalFunctions.php:3669
wfCheckLimits
wfCheckLimits( $deflimit=50, $optionname='rclimit')
Obtain the offset and limit values from the request string; used in special pages.
Definition: GlobalFunctions.php:2063
wfFormatStackFrame
wfFormatStackFrame( $frame)
Return a string representation of frame.
Definition: GlobalFunctions.php:1973
$last
$last
Definition: profileinfo.php:365
wfGetDB
& wfGetDB( $db, $groups=array(), $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3659
wfRemoveDotSegments
wfRemoveDotSegments( $urlPath)
Remove all dot-segments in the provided URL path.
Definition: GlobalFunctions.php:617
wfSetBit
wfSetBit(&$dest, $bit, $state=true)
As for wfSetVar except setting a bit.
Definition: GlobalFunctions.php:2156
$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:1760
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:2346
wfMakeUrlIndexes
wfMakeUrlIndexes( $url)
Make URL indexes, appropriate for the el_index field of externallinks.
Definition: GlobalFunctions.php:848
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:2124
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2483
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:1040
wfUnpack
wfUnpack( $format, $data, $length=false)
Wrapper around php's unpack.
Definition: GlobalFunctions.php:4028
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:258
$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:2387
$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:330
wfArrayDiff2_cmp
wfArrayDiff2_cmp( $a, $b)
Definition: GlobalFunctions.php:122
wfGetScriptUrl
wfGetScriptUrl()
Get the script URL.
Definition: GlobalFunctions.php:3755
Fallback\mb_strpos
static mb_strpos( $haystack, $needle, $offset=0, $encoding='')
Fallback implementation of mb_strpos, hardcoded to UTF-8.
Definition: Fallback.php:160
wfArrayDiff2
if(!defined( 'MEDIAWIKI')) wfArrayDiff2( $a, $b)
Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
Definition: GlobalFunctions.php:113
wfBaseName
wfBaseName( $path, $suffix='')
Return the final portion of a pathname.
Definition: GlobalFunctions.php:3302
wfQueriesMustScale
wfQueriesMustScale()
Should low-performance queries be disabled?
Definition: GlobalFunctions.php:3723
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:1786
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1313
wfMsgReplaceArgs
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
Definition: GlobalFunctions.php:1590
wfShellExecWithStderr
wfShellExecWithStderr( $cmd, &$retval=null, $environ=array(), $limits=array())
Execute a shell command, returning both stdout and stderr.
Definition: GlobalFunctions.php:3029
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:3252
wfGetCache
wfGetCache( $inputType)
Get a cache object.
Definition: GlobalFunctions.php:3957
wfIsConfiguredProxy
wfIsConfiguredProxy( $ip)
Checks if an IP matches a proxy we've configured.
Definition: GlobalFunctions.php:4178
wfSplitWikiID
wfSplitWikiID( $wiki)
Split a wiki ID into DB name and table prefix.
Definition: GlobalFunctions.php:3629
$s
$s
Definition: mergeMessageFileList.php:156
TS_DB
const TS_DB
MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
Definition: GlobalFunctions.php:2436
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:183
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:1154
$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:2149
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:825
wfMessageFallback
wfMessageFallback()
This function accepts multiple message keys and returns a message instance for the first message whic...
Definition: GlobalFunctions.php:1422
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:150
wfMsgReal
wfMsgReal( $key, $args, $useDB=true, $forContent=false, $transform=true)
Really get a message.
Definition: GlobalFunctions.php:1545
wfBoolToStr
wfBoolToStr( $value)
Convenience function converts boolean values into "true" or "false" (string) values.
Definition: GlobalFunctions.php:3780
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:459
wfBacktrace
wfBacktrace()
Get a debug backtrace as a string.
Definition: GlobalFunctions.php:1886
wfParseUrl
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
Definition: GlobalFunctions.php:755
$lb
if( $wgAPIRequestLog) $lb
Definition: api.php:126
wfGetMainCache
wfGetMainCache()
Get the main cache object.
Definition: GlobalFunctions.php:3966
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:3853
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3580
$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:2318
wfMsgHtml
wfMsgHtml( $key)
Return an HTML-escaped version of a message.
Definition: GlobalFunctions.php:1623
$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:1127
wfRestoreWarnings
wfRestoreWarnings()
Restore error level to previous value.
Definition: GlobalFunctions.php:2417
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:3739
wfIncrStats
wfIncrStats( $key, $count=1)
Increment a statistics counter.
Definition: GlobalFunctions.php:1304
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:401
wfShellExecDisabled
wfShellExecDisabled()
Check if wfShellExec() is effectively disabled via php.ini config.
Definition: GlobalFunctions.php:2766
wfUrlProtocolsWithoutProtRel
wfUrlProtocolsWithoutProtRel()
Like wfUrlProtocols(), but excludes '//' from the protocol list.
Definition: GlobalFunctions.php:740
$wgRequestTime
$wgRequestTime
Definition: WebStart.php:68
wfDebugDieBacktrace
wfDebugDieBacktrace( $msg='')
Throw a debugging exception.
Definition: GlobalFunctions.php:1774
wfTimestampOrNull
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
Definition: GlobalFunctions.php:2501
swap
swap(&$x, &$y)
Swap two variables.
Definition: GlobalFunctions.php:2547
wfProfileOut
wfProfileOut( $functionname='missing')
Stop profiling of a function.
Definition: Profiler.php:46
$wgOut
$wgOut
Definition: Setup.php:562
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:1644
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:4010
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1352
wfShorthandToInteger
wfShorthandToInteger( $string='')
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:3898
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:412
$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:707
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:2514
wfMemoryLimit
wfMemoryLimit()
Set PHP's memory limit to the larger of php.ini or $wgMemoryLimit;.
Definition: GlobalFunctions.php:3870
wfWaitForSlaves
wfWaitForSlaves( $maxLag=false, $wiki=false, $cluster=false)
Modern version of wfWaitForSlaves().
Definition: GlobalFunctions.php:3804
wfForeignMemcKey
wfForeignMemcKey( $db, $prefix)
Get a cache key for a foreign DB.
Definition: GlobalFunctions.php:3597
wfAcceptToPrefs
wfAcceptToPrefs( $accept, $def=' */*')
Converts an Accept-* header into an array mapping string values to quality factors.
Definition: GlobalFunctions.php:2282
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:838
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:969
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:993
$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:3071
wfUrlProtocols
wfUrlProtocols( $includeProtocolRelative=true)
Returns a regular expression of url protocols.
Definition: GlobalFunctions.php:695
$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:4064
TS_MW
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
Definition: GlobalFunctions.php:2431
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:933
wfWikiID
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
Definition: GlobalFunctions.php:3613
$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:2270
$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:2029
wfLogDBError
wfLogDBError( $text)
Log for database errors.
Definition: GlobalFunctions.php:1087
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:2524
wfEscapeShellArg
wfEscapeShellArg()
Windows-compatible version of escapeshellarg() Windows doesn't recognise single-quotes in the shell,...
Definition: GlobalFunctions.php:2705
wfDebugMem
wfDebugMem( $exact=false)
Send a line giving PHP memory usage.
Definition: GlobalFunctions.php:1010
wfInitShellLocale
wfInitShellLocale()
Workaround for http://bugs.php.net/bug.php?id=45132 escapeshellarg() destroys non-ASCII characters if...
Definition: GlobalFunctions.php:3037
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:2077
$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:164
wfVarDump
wfVarDump( $var)
A wrapper around the PHP function var_export().
Definition: GlobalFunctions.php:2174
wfGetParserCacheStorage
wfGetParserCacheStorage()
Get the cache object used by the parser cache.
Definition: GlobalFunctions.php:3986
wfMsgExt
wfMsgExt( $key, $options)
Returns message in the requested format.
Definition: GlobalFunctions.php:1678
wfGetNull
wfGetNull()
Get a platform-independent path to the null file, e.g.
Definition: GlobalFunctions.php:3789
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:2685
wfIsTrustedProxy
wfIsTrustedProxy( $ip)
Checks if an IP is a trusted proxy provider.
Definition: GlobalFunctions.php:4165
wfMsgGetKey
wfMsgGetKey( $key, $useDB=true, $langCode=false, $transform=true)
Fetch a message string value, but don't replace any keys yet.
Definition: GlobalFunctions.php:1567
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:1826
wfGetAllCallers
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
Definition: GlobalFunctions.php:1958
$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:3976
$args
if( $line===false) $args
Definition: cdb.php:62
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:281
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:2564
wfGetLangConverterCacheStorage
wfGetLangConverterCacheStorage()
Get the cache object used by the language converter.
Definition: GlobalFunctions.php:3996
wfHttpError
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
Definition: GlobalFunctions.php:2191
wfReadOnlyReason
wfReadOnlyReason()
Get the value of $wgReadOnly or the contents of $wgReadOnlyFile.
Definition: GlobalFunctions.php:1322
wfGetLBFactory
& wfGetLBFactory()
Get the load balancer factory object.
Definition: GlobalFunctions.php:3678
wfMatchesDomainList
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
Definition: GlobalFunctions.php:902
$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:3561
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:3377
wfRecursiveRemoveDir
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
Definition: GlobalFunctions.php:2632
wfCheckEntropy
wfCheckEntropy()
Check if there is sufficient entropy in php's built-in session generation.
Definition: GlobalFunctions.php:3473
TS_UNIX
const TS_UNIX
Unix time - the number of seconds since 1970-01-01 00:00:00 UTC.
Definition: GlobalFunctions.php:2426
$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:3702
$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:2003
$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:565
wfRelativePath
wfRelativePath( $path, $from)
Generate a relative path name to the given file.
Definition: GlobalFunctions.php:3326
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:1141
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:2573
$e
if( $useReadline) $e
Definition: eval.php:66
$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:2537
$IP
$IP
Definition: WebStart.php:88
wfLocalFile
wfLocalFile( $title)
Get an object referring to a locally registered file.
Definition: GlobalFunctions.php:3713
wfShowingResults
wfShowingResults( $offset, $limit)
Definition: GlobalFunctions.php:1988
wfResetSessionID
wfResetSessionID()
Reset the session_id.
Definition: GlobalFunctions.php:3511
$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:1941
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:1446
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:1518
wfCountDown
wfCountDown( $seconds)
Count down from $seconds to zero on the terminal, with a one-second pause between showing each number...
Definition: GlobalFunctions.php:3831
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:497
wfLogProfilingData
wfLogProfilingData()
Definition: GlobalFunctions.php:1226
$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:367
wfRandomString
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Definition: GlobalFunctions.php:300
$type
$type
Definition: testCompression.php:46