MediaWiki  1.23.2
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  while ( true ) {
2918  $status = proc_get_status( $proc );
2919  if ( !$status['running'] ) {
2920  break;
2921  }
2922  $status = false;
2923 
2924  $readyPipes = $pipes;
2925 
2926  // Clear last error
2927  @trigger_error( '' );
2928  if ( @stream_select( $readyPipes, $emptyArray, $emptyArray, null ) === false ) {
2929  $error = error_get_last();
2930  if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
2931  continue;
2932  } else {
2933  trigger_error( $error['message'], E_USER_WARNING );
2934  $logMsg = $error['message'];
2935  break;
2936  }
2937  }
2938  foreach ( $readyPipes as $pipe ) {
2939  $block = fread( $pipe, 65536 );
2940  $fd = $fds[(int)$pipe];
2941  if ( $block === '' ) {
2942  // End of file
2943  fclose( $pipes[$fd] );
2944  unset( $pipes[$fd] );
2945  if ( !$pipes ) {
2946  break 2;
2947  }
2948  } elseif ( $block === false ) {
2949  // Read error
2950  $logMsg = "Error reading from pipe";
2951  break 2;
2952  } elseif ( $fd == 1 ) {
2953  // From stdout
2954  $outBuffer .= $block;
2955  } elseif ( $fd == 3 ) {
2956  // From log FD
2957  $logBuffer .= $block;
2958  if ( strpos( $block, "\n" ) !== false ) {
2959  $lines = explode( "\n", $logBuffer );
2960  $logBuffer = array_pop( $lines );
2961  foreach ( $lines as $line ) {
2962  wfDebugLog( 'exec', $line );
2963  }
2964  }
2965  }
2966  }
2967  }
2968 
2969  foreach ( $pipes as $pipe ) {
2970  fclose( $pipe );
2971  }
2972 
2973  // Use the status previously collected if possible, since proc_get_status()
2974  // just calls waitpid() which will not return anything useful the second time.
2975  if ( $status === false ) {
2976  $status = proc_get_status( $proc );
2977  }
2978 
2979  if ( $logMsg !== false ) {
2980  // Read/select error
2981  $retval = -1;
2982  proc_close( $proc );
2983  } elseif ( $status['signaled'] ) {
2984  $logMsg = "Exited with signal {$status['termsig']}";
2985  $retval = 128 + $status['termsig'];
2986  proc_close( $proc );
2987  } else {
2988  if ( $status['running'] ) {
2989  $retval = proc_close( $proc );
2990  } else {
2991  $retval = $status['exitcode'];
2992  proc_close( $proc );
2993  }
2994  if ( $retval == 127 ) {
2995  $logMsg = "Possibly missing executable file";
2996  } elseif ( $retval >= 129 && $retval <= 192 ) {
2997  $logMsg = "Probably exited with signal " . ( $retval - 128 );
2998  }
2999  }
3000 
3001  if ( $logMsg !== false ) {
3002  wfDebugLog( 'exec', "$logMsg: $cmd" );
3003  }
3004 
3005  return $outBuffer;
3006 }
3007 
3022 function wfShellExecWithStderr( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
3023  return wfShellExec( $cmd, $retval, $environ, $limits, array( 'duplicateStderr' => true ) );
3024 }
3025 
3030 function wfInitShellLocale() {
3031  static $done = false;
3032  if ( $done ) {
3033  return;
3034  }
3035  $done = true;
3036  global $wgShellLocale;
3037  if ( !wfIniGetBool( 'safe_mode' ) ) {
3038  putenv( "LC_CTYPE=$wgShellLocale" );
3039  setlocale( LC_CTYPE, $wgShellLocale );
3040  }
3041 }
3042 
3048 function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) {
3049  return wfShellWikiCmd( $script, $parameters, $options );
3050 }
3051 
3064 function wfShellWikiCmd( $script, array $parameters = array(), array $options = array() ) {
3065  global $wgPhpCli;
3066  // Give site config file a chance to run the script in a wrapper.
3067  // The caller may likely want to call wfBasename() on $script.
3068  wfRunHooks( 'wfShellWikiCmd', array( &$script, &$parameters, &$options ) );
3069  $cmd = isset( $options['php'] ) ? array( $options['php'] ) : array( $wgPhpCli );
3070  if ( isset( $options['wrapper'] ) ) {
3071  $cmd[] = $options['wrapper'];
3072  }
3073  $cmd[] = $script;
3074  // Escape each parameter for shell
3075  return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
3076 }
3077 
3088 function wfMerge( $old, $mine, $yours, &$result ) {
3089  global $wgDiff3;
3090 
3091  # This check may also protect against code injection in
3092  # case of broken installations.
3094  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
3096 
3097  if ( !$haveDiff3 ) {
3098  wfDebug( "diff3 not found\n" );
3099  return false;
3100  }
3101 
3102  # Make temporary files
3103  $td = wfTempDir();
3104  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3105  $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
3106  $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
3107 
3108  # NOTE: diff3 issues a warning to stderr if any of the files does not end with
3109  # a newline character. To avoid this, we normalize the trailing whitespace before
3110  # creating the diff.
3111 
3112  fwrite( $oldtextFile, rtrim( $old ) . "\n" );
3113  fclose( $oldtextFile );
3114  fwrite( $mytextFile, rtrim( $mine ) . "\n" );
3115  fclose( $mytextFile );
3116  fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
3117  fclose( $yourtextFile );
3118 
3119  # Check for a conflict
3120  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
3121  wfEscapeShellArg( $mytextName ) . ' ' .
3122  wfEscapeShellArg( $oldtextName ) . ' ' .
3123  wfEscapeShellArg( $yourtextName );
3124  $handle = popen( $cmd, 'r' );
3125 
3126  if ( fgets( $handle, 1024 ) ) {
3127  $conflict = true;
3128  } else {
3129  $conflict = false;
3130  }
3131  pclose( $handle );
3132 
3133  # Merge differences
3134  $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
3135  wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
3136  $handle = popen( $cmd, 'r' );
3137  $result = '';
3138  do {
3139  $data = fread( $handle, 8192 );
3140  if ( strlen( $data ) == 0 ) {
3141  break;
3142  }
3143  $result .= $data;
3144  } while ( true );
3145  pclose( $handle );
3146  unlink( $mytextName );
3147  unlink( $oldtextName );
3148  unlink( $yourtextName );
3149 
3150  if ( $result === '' && $old !== '' && !$conflict ) {
3151  wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
3152  $conflict = true;
3153  }
3154  return !$conflict;
3155 }
3156 
3166 function wfDiff( $before, $after, $params = '-u' ) {
3167  if ( $before == $after ) {
3168  return '';
3169  }
3170 
3171  global $wgDiff;
3173  $haveDiff = $wgDiff && file_exists( $wgDiff );
3175 
3176  # This check may also protect against code injection in
3177  # case of broken installations.
3178  if ( !$haveDiff ) {
3179  wfDebug( "diff executable not found\n" );
3180  $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) );
3181  $format = new UnifiedDiffFormatter();
3182  return $format->format( $diffs );
3183  }
3184 
3185  # Make temporary files
3186  $td = wfTempDir();
3187  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
3188  $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' );
3189 
3190  fwrite( $oldtextFile, $before );
3191  fclose( $oldtextFile );
3192  fwrite( $newtextFile, $after );
3193  fclose( $newtextFile );
3194 
3195  // Get the diff of the two files
3196  $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName );
3197 
3198  $h = popen( $cmd, 'r' );
3199 
3200  $diff = '';
3201 
3202  do {
3203  $data = fread( $h, 8192 );
3204  if ( strlen( $data ) == 0 ) {
3205  break;
3206  }
3207  $diff .= $data;
3208  } while ( true );
3209 
3210  // Clean up
3211  pclose( $h );
3212  unlink( $oldtextName );
3213  unlink( $newtextName );
3214 
3215  // Kill the --- and +++ lines. They're not useful.
3216  $diff_lines = explode( "\n", $diff );
3217  if ( strpos( $diff_lines[0], '---' ) === 0 ) {
3218  unset( $diff_lines[0] );
3219  }
3220  if ( strpos( $diff_lines[1], '+++' ) === 0 ) {
3221  unset( $diff_lines[1] );
3222  }
3223 
3224  $diff = implode( "\n", $diff_lines );
3225 
3226  return $diff;
3227 }
3228 
3245 function wfUsePHP( $req_ver ) {
3246  $php_ver = PHP_VERSION;
3247 
3248  if ( version_compare( $php_ver, (string)$req_ver, '<' ) ) {
3249  throw new MWException( "PHP $req_ver required--this is only $php_ver" );
3250  }
3251 }
3252 
3275 function wfUseMW( $req_ver ) {
3276  global $wgVersion;
3277 
3278  if ( version_compare( $wgVersion, (string)$req_ver, '<' ) ) {
3279  throw new MWException( "MediaWiki $req_ver required--this is only $wgVersion" );
3280  }
3281 }
3282 
3295 function wfBaseName( $path, $suffix = '' ) {
3296  if ( $suffix == '' ) {
3297  $encSuffix = '';
3298  } else {
3299  $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
3300  }
3301 
3302  $matches = array();
3303  if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
3304  return $matches[1];
3305  } else {
3306  return '';
3307  }
3308 }
3309 
3319 function wfRelativePath( $path, $from ) {
3320  // Normalize mixed input on Windows...
3321  $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
3322  $from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
3323 
3324  // Trim trailing slashes -- fix for drive root
3325  $path = rtrim( $path, DIRECTORY_SEPARATOR );
3326  $from = rtrim( $from, DIRECTORY_SEPARATOR );
3327 
3328  $pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
3329  $against = explode( DIRECTORY_SEPARATOR, $from );
3330 
3331  if ( $pieces[0] !== $against[0] ) {
3332  // Non-matching Windows drive letters?
3333  // Return a full path.
3334  return $path;
3335  }
3336 
3337  // Trim off common prefix
3338  while ( count( $pieces ) && count( $against )
3339  && $pieces[0] == $against[0] ) {
3340  array_shift( $pieces );
3341  array_shift( $against );
3342  }
3343 
3344  // relative dots to bump us to the parent
3345  while ( count( $against ) ) {
3346  array_unshift( $pieces, '..' );
3347  array_shift( $against );
3348  }
3349 
3350  array_push( $pieces, wfBaseName( $path ) );
3351 
3352  return implode( DIRECTORY_SEPARATOR, $pieces );
3353 }
3354 
3370 function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
3371  $lowercase = true, $engine = 'auto'
3372 ) {
3373  $input = (string)$input;
3374  if (
3375  $sourceBase < 2 ||
3376  $sourceBase > 36 ||
3377  $destBase < 2 ||
3378  $destBase > 36 ||
3379  $sourceBase != (int)$sourceBase ||
3380  $destBase != (int)$destBase ||
3381  $pad != (int)$pad ||
3382  !preg_match(
3383  "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i",
3384  $input
3385  )
3386  ) {
3387  return false;
3388  }
3389 
3390  static $baseChars = array(
3391  10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f',
3392  16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l',
3393  22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r',
3394  28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x',
3395  34 => 'y', 35 => 'z',
3396 
3397  '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5,
3398  '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11,
3399  'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17,
3400  'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23,
3401  'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29,
3402  'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35
3403  );
3404 
3405  if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
3406  $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
3407  } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
3408  $decimal = '0';
3409  foreach ( str_split( strtolower( $input ) ) as $char ) {
3410  $decimal = bcmul( $decimal, $sourceBase );
3411  $decimal = bcadd( $decimal, $baseChars[$char] );
3412  }
3413 
3414  for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
3415  $result .= $baseChars[bcmod( $decimal, $destBase )];
3416  }
3417 
3418  $result = strrev( $result );
3419  } else {
3420  $inDigits = array();
3421  foreach ( str_split( strtolower( $input ) ) as $char ) {
3422  $inDigits[] = $baseChars[$char];
3423  }
3424 
3425  // Iterate over the input, modulo-ing out an output digit
3426  // at a time until input is gone.
3427  $result = '';
3428  while ( $inDigits ) {
3429  $work = 0;
3430  $workDigits = array();
3431 
3432  // Long division...
3433  foreach ( $inDigits as $digit ) {
3434  $work *= $sourceBase;
3435  $work += $digit;
3436 
3437  if ( $workDigits || $work >= $destBase ) {
3438  $workDigits[] = (int)( $work / $destBase );
3439  }
3440  $work %= $destBase;
3441  }
3442 
3443  // All that division leaves us with a remainder,
3444  // which is conveniently our next output digit.
3445  $result .= $baseChars[$work];
3446 
3447  // And we continue!
3448  $inDigits = $workDigits;
3449  }
3450 
3451  $result = strrev( $result );
3452  }
3453 
3454  if ( !$lowercase ) {
3455  $result = strtoupper( $result );
3456  }
3457 
3458  return str_pad( $result, $pad, '0', STR_PAD_LEFT );
3459 }
3460 
3466 function wfCheckEntropy() {
3467  return (
3468  ( wfIsWindows() && version_compare( PHP_VERSION, '5.3.3', '>=' ) )
3469  || ini_get( 'session.entropy_file' )
3470  )
3471  && intval( ini_get( 'session.entropy_length' ) ) >= 32;
3472 }
3473 
3478 function wfFixSessionID() {
3479  // If the cookie or session id is already set we already have a session and should abort
3480  if ( isset( $_COOKIE[session_name()] ) || session_id() ) {
3481  return;
3482  }
3483 
3484  // PHP's built-in session entropy is enabled if:
3485  // - entropy_file is set or you're on Windows with php 5.3.3+
3486  // - AND entropy_length is > 0
3487  // We treat it as disabled if it doesn't have an entropy length of at least 32
3488  $entropyEnabled = wfCheckEntropy();
3489 
3490  // If built-in entropy is not enabled or not sufficient override PHP's
3491  // built in session id generation code
3492  if ( !$entropyEnabled ) {
3493  wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, " .
3494  "overriding session id generation using our cryptrand source.\n" );
3495  session_id( MWCryptRand::generateHex( 32 ) );
3496  }
3497 }
3498 
3504 function wfResetSessionID() {
3505  global $wgCookieSecure;
3506  $oldSessionId = session_id();
3507  $cookieParams = session_get_cookie_params();
3508  if ( wfCheckEntropy() && $wgCookieSecure == $cookieParams['secure'] ) {
3509  session_regenerate_id( false );
3510  } else {
3511  $tmp = $_SESSION;
3512  session_destroy();
3514  $_SESSION = $tmp;
3515  }
3516  $newSessionId = session_id();
3517  wfRunHooks( 'ResetSessionID', array( $oldSessionId, $newSessionId ) );
3518 }
3519 
3525 function wfSetupSession( $sessionId = false ) {
3526  global $wgSessionsInMemcached, $wgSessionsInObjectCache, $wgCookiePath, $wgCookieDomain,
3527  $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler;
3528  if ( $wgSessionsInObjectCache || $wgSessionsInMemcached ) {
3530  } elseif ( $wgSessionHandler && $wgSessionHandler != ini_get( 'session.save_handler' ) ) {
3531  # Only set this if $wgSessionHandler isn't null and session.save_handler
3532  # hasn't already been set to the desired value (that causes errors)
3533  ini_set( 'session.save_handler', $wgSessionHandler );
3534  }
3535  session_set_cookie_params(
3536  0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly );
3537  session_cache_limiter( 'private, must-revalidate' );
3538  if ( $sessionId ) {
3539  session_id( $sessionId );
3540  } else {
3541  wfFixSessionID();
3542  }
3544  session_start();
3546 }
3547 
3554 function wfGetPrecompiledData( $name ) {
3555  global $IP;
3556 
3557  $file = "$IP/serialized/$name";
3558  if ( file_exists( $file ) ) {
3559  $blob = file_get_contents( $file );
3560  if ( $blob ) {
3561  return unserialize( $blob );
3562  }
3563  }
3564  return false;
3565 }
3566 
3573 function wfMemcKey( /*...*/ ) {
3574  global $wgCachePrefix;
3575  $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
3576  $args = func_get_args();
3577  $key = $prefix . ':' . implode( ':', $args );
3578  $key = str_replace( ' ', '_', $key );
3579  return $key;
3580 }
3581 
3590 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
3591  $args = array_slice( func_get_args(), 2 );
3592  if ( $prefix ) {
3593  $key = "$db-$prefix:" . implode( ':', $args );
3594  } else {
3595  $key = $db . ':' . implode( ':', $args );
3596  }
3597  return str_replace( ' ', '_', $key );
3598 }
3599 
3606 function wfWikiID() {
3607  global $wgDBprefix, $wgDBname;
3608  if ( $wgDBprefix ) {
3609  return "$wgDBname-$wgDBprefix";
3610  } else {
3611  return $wgDBname;
3612  }
3613 }
3614 
3622 function wfSplitWikiID( $wiki ) {
3623  $bits = explode( '-', $wiki, 2 );
3624  if ( count( $bits ) < 2 ) {
3625  $bits[] = '';
3626  }
3627  return $bits;
3628 }
3629 
3652 function &wfGetDB( $db, $groups = array(), $wiki = false ) {
3653  return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
3654 }
3655 
3662 function wfGetLB( $wiki = false ) {
3663  return wfGetLBFactory()->getMainLB( $wiki );
3664 }
3665 
3671 function &wfGetLBFactory() {
3672  return LBFactory::singleton();
3673 }
3674 
3695 function wfFindFile( $title, $options = array() ) {
3696  return RepoGroup::singleton()->findFile( $title, $options );
3697 }
3698 
3706 function wfLocalFile( $title ) {
3707  return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
3708 }
3709 
3716 function wfQueriesMustScale() {
3717  global $wgMiserMode;
3718  return $wgMiserMode
3719  || ( SiteStats::pages() > 100000
3720  && SiteStats::edits() > 1000000
3721  && SiteStats::users() > 10000 );
3722 }
3723 
3732 function wfScript( $script = 'index' ) {
3733  global $wgScriptPath, $wgScriptExtension, $wgScript, $wgLoadScript;
3734  if ( $script === 'index' ) {
3735  return $wgScript;
3736  } elseif ( $script === 'load' ) {
3737  return $wgLoadScript;
3738  } else {
3739  return "{$wgScriptPath}/{$script}{$wgScriptExtension}";
3740  }
3741 }
3742 
3748 function wfGetScriptUrl() {
3749  if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
3750  #
3751  # as it was called, minus the query string.
3752  #
3753  # Some sites use Apache rewrite rules to handle subdomains,
3754  # and have PHP set up in a weird way that causes PHP_SELF
3755  # to contain the rewritten URL instead of the one that the
3756  # outside world sees.
3757  #
3758  # If in this mode, use SCRIPT_URL instead, which mod_rewrite
3759  # provides containing the "before" URL.
3760  return $_SERVER['SCRIPT_NAME'];
3761  } else {
3762  return $_SERVER['URL'];
3763  }
3764 }
3765 
3773 function wfBoolToStr( $value ) {
3774  return $value ? 'true' : 'false';
3775 }
3776 
3782 function wfGetNull() {
3783  return wfIsWindows() ? 'NUL' : '/dev/null';
3784 }
3785 
3797 function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
3798  if ( $cluster !== false ) {
3799  $lb = wfGetLBFactory()->getExternalLB( $cluster );
3800  } else {
3801  $lb = wfGetLB( $wiki );
3802  }
3803 
3804  // bug 27975 - Don't try to wait for slaves if there are none
3805  // Prevents permission error when getting master position
3806  if ( $lb->getServerCount() > 1 ) {
3807  $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
3808  $pos = $dbw->getMasterPos();
3809  // The DBMS may not support getMasterPos() or the whole
3810  // load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
3811  if ( $pos !== false ) {
3812  $lb->waitForAll( $pos );
3813  }
3814  }
3815 }
3816 
3824 function wfCountDown( $seconds ) {
3825  for ( $i = $seconds; $i >= 0; $i-- ) {
3826  if ( $i != $seconds ) {
3827  echo str_repeat( "\x08", strlen( $i + 1 ) );
3828  }
3829  echo $i;
3830  flush();
3831  if ( $i ) {
3832  sleep( 1 );
3833  }
3834  }
3835  echo "\n";
3836 }
3837 
3846 function wfStripIllegalFilenameChars( $name ) {
3847  global $wgIllegalFileChars;
3848  $illegalFileChars = $wgIllegalFileChars ? "|[" . $wgIllegalFileChars . "]" : '';
3849  $name = wfBaseName( $name );
3850  $name = preg_replace(
3851  "/[^" . Title::legalChars() . "]" . $illegalFileChars . "/",
3852  '-',
3853  $name
3854  );
3855  return $name;
3856 }
3857 
3863 function wfMemoryLimit() {
3864  global $wgMemoryLimit;
3865  $memlimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
3866  if ( $memlimit != -1 ) {
3867  $conflimit = wfShorthandToInteger( $wgMemoryLimit );
3868  if ( $conflimit == -1 ) {
3869  wfDebug( "Removing PHP's memory limit\n" );
3871  ini_set( 'memory_limit', $conflimit );
3873  return $conflimit;
3874  } elseif ( $conflimit > $memlimit ) {
3875  wfDebug( "Raising PHP's memory limit to $conflimit bytes\n" );
3877  ini_set( 'memory_limit', $conflimit );
3879  return $conflimit;
3880  }
3881  }
3882  return $memlimit;
3883 }
3884 
3891 function wfShorthandToInteger( $string = '' ) {
3892  $string = trim( $string );
3893  if ( $string === '' ) {
3894  return -1;
3895  }
3896  $last = $string[strlen( $string ) - 1];
3897  $val = intval( $string );
3898  switch ( $last ) {
3899  case 'g':
3900  case 'G':
3901  $val *= 1024;
3902  // break intentionally missing
3903  case 'm':
3904  case 'M':
3905  $val *= 1024;
3906  // break intentionally missing
3907  case 'k':
3908  case 'K':
3909  $val *= 1024;
3910  }
3911 
3912  return $val;
3913 }
3914 
3922 function wfBCP47( $code ) {
3923  $codeSegment = explode( '-', $code );
3924  $codeBCP = array();
3925  foreach ( $codeSegment as $segNo => $seg ) {
3926  // when previous segment is x, it is a private segment and should be lc
3927  if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
3928  $codeBCP[$segNo] = strtolower( $seg );
3929  // ISO 3166 country code
3930  } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
3931  $codeBCP[$segNo] = strtoupper( $seg );
3932  // ISO 15924 script code
3933  } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
3934  $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
3935  // Use lowercase for other cases
3936  } else {
3937  $codeBCP[$segNo] = strtolower( $seg );
3938  }
3939  }
3940  $langCode = implode( '-', $codeBCP );
3941  return $langCode;
3942 }
3943 
3950 function wfGetCache( $inputType ) {
3951  return ObjectCache::getInstance( $inputType );
3952 }
3953 
3959 function wfGetMainCache() {
3962 }
3963 
3969 function wfGetMessageCacheStorage() {
3970  global $wgMessageCacheType;
3971  return ObjectCache::getInstance( $wgMessageCacheType );
3972 }
3973 
3979 function wfGetParserCacheStorage() {
3980  global $wgParserCacheType;
3981  return ObjectCache::getInstance( $wgParserCacheType );
3982 }
3983 
3989 function wfGetLangConverterCacheStorage() {
3990  global $wgLanguageConverterCacheType;
3991  return ObjectCache::getInstance( $wgLanguageConverterCacheType );
3992 }
3993 
4003 function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null ) {
4004  return Hooks::run( $event, $args, $deprecatedVersion );
4005 }
4006 
4021 function wfUnpack( $format, $data, $length = false ) {
4022  if ( $length !== false ) {
4023  $realLen = strlen( $data );
4024  if ( $realLen < $length ) {
4025  throw new MWException( "Tried to use wfUnpack on a "
4026  . "string of length $realLen, but needed one "
4027  . "of at least length $length."
4028  );
4029  }
4030  }
4031 
4033  $result = unpack( $format, $data );
4035 
4036  if ( $result === false ) {
4037  // If it cannot extract the packed data.
4038  throw new MWException( "unpack could not unpack binary data" );
4039  }
4040  return $result;
4041 }
4042 
4057 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
4058  static $badImageCache = null; // based on bad_image_list msg
4059  wfProfileIn( __METHOD__ );
4060 
4061  # Handle redirects
4062  $redirectTitle = RepoGroup::singleton()->checkRedirect( Title::makeTitle( NS_FILE, $name ) );
4063  if ( $redirectTitle ) {
4064  $name = $redirectTitle->getDBkey();
4065  }
4066 
4067  # Run the extension hook
4068  $bad = false;
4069  if ( !wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {
4070  wfProfileOut( __METHOD__ );
4071  return $bad;
4072  }
4073 
4074  $cacheable = ( $blacklist === null );
4075  if ( $cacheable && $badImageCache !== null ) {
4076  $badImages = $badImageCache;
4077  } else { // cache miss
4078  if ( $blacklist === null ) {
4079  $blacklist = wfMessage( 'bad_image_list' )->inContentLanguage()->plain(); // site list
4080  }
4081  # Build the list now
4082  $badImages = array();
4083  $lines = explode( "\n", $blacklist );
4084  foreach ( $lines as $line ) {
4085  # List items only
4086  if ( substr( $line, 0, 1 ) !== '*' ) {
4087  continue;
4088  }
4089 
4090  # Find all links
4091  $m = array();
4092  if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
4093  continue;
4094  }
4095 
4096  $exceptions = array();
4097  $imageDBkey = false;
4098  foreach ( $m[1] as $i => $titleText ) {
4099  $title = Title::newFromText( $titleText );
4100  if ( !is_null( $title ) ) {
4101  if ( $i == 0 ) {
4102  $imageDBkey = $title->getDBkey();
4103  } else {
4104  $exceptions[$title->getPrefixedDBkey()] = true;
4105  }
4106  }
4107  }
4108 
4109  if ( $imageDBkey !== false ) {
4110  $badImages[$imageDBkey] = $exceptions;
4111  }
4112  }
4113  if ( $cacheable ) {
4114  $badImageCache = $badImages;
4115  }
4116  }
4117 
4118  $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
4119  $bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
4120  wfProfileOut( __METHOD__ );
4121  return $bad;
4122 }
4123 
4131 function wfCanIPUseHTTPS( $ip ) {
4132  $canDo = true;
4133  wfRunHooks( 'CanIPUseHTTPS', array( $ip, &$canDo ) );
4134  return !!$canDo;
4135 }
4136 
4144 function wfGetIP() {
4145  wfDeprecated( __METHOD__, '1.19' );
4146  global $wgRequest;
4147  return $wgRequest->getIP();
4148 }
4149 
4158 function wfIsTrustedProxy( $ip ) {
4159  $trusted = wfIsConfiguredProxy( $ip );
4160  wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
4161  return $trusted;
4162 }
4163 
4171 function wfIsConfiguredProxy( $ip ) {
4172  global $wgSquidServers, $wgSquidServersNoPurge;
4173 
4174  // quick check of known proxy servers
4175  $trusted = in_array( $ip, $wgSquidServers )
4176  || in_array( $ip, $wgSquidServersNoPurge );
4177 
4178  if ( !$trusted ) {
4179  // slightly slower check to see if the ip is listed directly or in a CIDR
4180  // block in $wgSquidServersNoPurge
4181  foreach ( $wgSquidServersNoPurge as $block ) {
4182  if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
4183  $trusted = true;
4184  break;
4185  }
4186  }
4187  }
4188  return $trusted;
4189 }
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:3476
wfGetIP
wfGetIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Definition: GlobalFunctions.php:4142
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:3273
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:3920
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:4129
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:3046
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:3164
wfMerge
wfMerge( $old, $mine, $yours, &$result)
wfMerge attempts to merge differences between three texts.
Definition: GlobalFunctions.php:3086
wfSetupSession
wfSetupSession( $sessionId=false)
Initialise php session.
Definition: GlobalFunctions.php:3523
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:3660
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:3650
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:4019
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:3746
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:3293
wfQueriesMustScale
wfQueriesMustScale()
Should low-performance queries be disabled?
Definition: GlobalFunctions.php:3714
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:3020
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:3243
wfGetCache
wfGetCache( $inputType)
Get a cache object.
Definition: GlobalFunctions.php:3948
wfIsConfiguredProxy
wfIsConfiguredProxy( $ip)
Checks if an IP matches a proxy we've configured.
Definition: GlobalFunctions.php:4169
wfSplitWikiID
wfSplitWikiID( $wiki)
Split a wiki ID into DB name and table prefix.
Definition: GlobalFunctions.php:3620
$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:3771
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:3957
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:3844
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3571
$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:3730
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:4001
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:3889
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:3861
wfWaitForSlaves
wfWaitForSlaves( $maxLag=false, $wiki=false, $cluster=false)
Modern version of wfWaitForSlaves().
Definition: GlobalFunctions.php:3795
wfForeignMemcKey
wfForeignMemcKey( $db, $prefix)
Get a cache key for a foreign DB.
Definition: GlobalFunctions.php:3588
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:3062
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:4055
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:3604
$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:3028
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:3977
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:3780
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:4156
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:3967
$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:3987
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:3669
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:3552
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:3368
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:3464
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:3693
$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:3317
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:3704
wfShowingResults
wfShowingResults( $offset, $limit)
Definition: GlobalFunctions.php:1988
wfResetSessionID
wfResetSessionID()
Reset the session_id.
Definition: GlobalFunctions.php:3502
$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:1141
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:3822
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