summaryrefslogtreecommitdiff
path: root/includes/GlobalFunctions.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/GlobalFunctions.php')
-rw-r--r--includes/GlobalFunctions.php445
1 files changed, 290 insertions, 155 deletions
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index d1336d47..33f5831d 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -8,10 +8,12 @@ if ( !defined( 'MEDIAWIKI' ) ) {
* Global functions used everywhere
*/
-require_once dirname(__FILE__) . '/LogPage.php';
require_once dirname(__FILE__) . '/normal/UtfNormalUtil.php';
require_once dirname(__FILE__) . '/XmlFunctions.php';
+// Hide compatibility functions from Doxygen
+/// @cond
+
/**
* Compatibility functions
*
@@ -87,6 +89,9 @@ if ( !function_exists( 'array_diff_key' ) ) {
}
}
+/// @endcond
+
+
/**
* Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
*/
@@ -145,16 +150,31 @@ function wfRandom() {
}
/**
- * We want / and : to be included as literal characters in our title URLs.
+ * We want some things to be included as literal characters in our title URLs
+ * for prettiness, which urlencode encodes by default. According to RFC 1738,
+ * all of the following should be safe:
+ *
+ * ;:@&=$-_.+!*'(),
+ *
+ * But + is not safe because it's used to indicate a space; &= are only safe in
+ * paths and not in queries (and we don't distinguish here); ' seems kind of
+ * scary; and urlencode() doesn't touch -_. to begin with. Plus, although /
+ * is reserved, we don't care. So the list we unescape is:
+ *
+ * ;:@$!*(),/
+ *
* %2F in the page titles seems to fatally break for some reason.
*
* @param $s String:
* @return string
*/
-function wfUrlencode ( $s ) {
+function wfUrlencode( $s ) {
$s = urlencode( $s );
- $s = preg_replace( '/%3[Aa]/', ':', $s );
- $s = preg_replace( '/%2[Ff]/', '/', $s );
+ $s = str_ireplace(
+ array( '%3B','%3A','%40','%24','%21','%2A','%28','%29','%2C','%2F' ),
+ array( ';', ':', '@', '$', '!', '*', '(', ')', ',', '/' ),
+ $s
+ );
return $s;
}
@@ -174,6 +194,7 @@ function wfUrlencode ( $s ) {
*/
function wfDebug( $text, $logonly = false ) {
global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage;
+ global $wgDebugLogPrefix;
static $recursion = 0;
static $cache = array(); // Cache of unoutputted messages
@@ -206,11 +227,26 @@ function wfDebug( $text, $logonly = false ) {
# Strip unprintables; they can switch terminal modes when binary data
# gets dumped, which is pretty annoying.
$text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
+ $text = $wgDebugLogPrefix . $text;
wfErrorLog( $text, $wgDebugLogFile );
}
}
/**
+ * Send a line giving PHP memory usage.
+ * @param $exact Bool : print exact values instead of kilobytes (default: false)
+ */
+function wfDebugMem( $exact = false ) {
+ $mem = memory_get_usage();
+ if( !$exact ) {
+ $mem = floor( $mem / 1024 ) . ' kilobytes';
+ } else {
+ $mem .= ' bytes';
+ }
+ wfDebug( "Memory usage: $mem\n" );
+}
+
+/**
* Send a line to a supplementary debug log file, if configured, or main debug log if not.
* $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log.
*
@@ -220,12 +256,17 @@ function wfDebug( $text, $logonly = false ) {
* log file is specified, (default true)
*/
function wfDebugLog( $logGroup, $text, $public = true ) {
- global $wgDebugLogGroups;
- if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n";
+ global $wgDebugLogGroups, $wgShowHostnames;
+ $text = trim($text)."\n";
if( isset( $wgDebugLogGroups[$logGroup] ) ) {
$time = wfTimestamp( TS_DB );
$wiki = wfWikiID();
- wfErrorLog( "$time $wiki: $text", $wgDebugLogGroups[$logGroup] );
+ if ( $wgShowHostnames ) {
+ $host = wfHostname();
+ } else {
+ $host = '';
+ }
+ wfErrorLog( "$time $host $wiki: $text", $wgDebugLogGroups[$logGroup] );
} else if ( $public === true ) {
wfDebug( $text, true );
}
@@ -245,16 +286,50 @@ function wfLogDBError( $text ) {
}
/**
- * Log to a file without getting "file size exceeded" signals
+ * Log to a file without getting "file size exceeded" signals.
+ *
+ * Can also log to TCP or UDP with the syntax udp://host:port/prefix. This will
+ * send lines to the specified port, prefixed by the specified prefix and a space.
*/
function wfErrorLog( $text, $file ) {
- wfSuppressWarnings();
- $exists = file_exists( $file );
- $size = $exists ? filesize( $file ) : false;
- if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
- error_log( $text, 3, $file );
+ if ( substr( $file, 0, 4 ) == 'udp:' ) {
+ if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ // IPv6 bracketed host
+ $protocol = $m[1];
+ $host = $m[2];
+ $port = $m[3];
+ $prefix = isset( $m[4] ) ? $m[4] : false;
+ } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ $protocol = $m[1];
+ $host = $m[2];
+ $port = $m[3];
+ $prefix = isset( $m[4] ) ? $m[4] : false;
+ } else {
+ throw new MWException( __METHOD__.": Invalid UDP specification" );
+ }
+ // Clean it up for the multiplexer
+ if ( strval( $prefix ) !== '' ) {
+ $text = preg_replace( '/^/m', $prefix . ' ', $text );
+ if ( substr( $text, -1 ) != "\n" ) {
+ $text .= "\n";
+ }
+ }
+
+ $sock = fsockopen( "$protocol://$host", $port );
+ if ( !$sock ) {
+ return;
+ }
+ fwrite( $sock, $text );
+ fclose( $sock );
+ } else {
+ wfSuppressWarnings();
+ $exists = file_exists( $file );
+ $size = $exists ? filesize( $file ) : false;
+ if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
+ error_log( $text, 3, $file );
+ }
+ wfRestoreWarnings();
}
- wfRestoreWarnings();
}
/**
@@ -320,6 +395,47 @@ function wfReadOnlyReason() {
}
/**
+ * Return a Language object from $langcode
+ * @param $langcode Mixed: either:
+ * - a Language object
+ * - code of the language to get the message for, if it is
+ * a valid code create a language for that language, if
+ * it is a string but not a valid code then make a basic
+ * language object
+ * - a boolean: if it's false then use the current users
+ * language (as a fallback for the old parameter
+ * functionality), or if it is true then use the wikis
+ * @return Language object
+ */
+function wfGetLangObj( $langcode = false ){
+ # Identify which language to get or create a language object for.
+ if( $langcode instanceof Language )
+ # Great, we already have the object!
+ return $langcode;
+
+ global $wgContLang;
+ if( $langcode === $wgContLang->getCode() || $langcode === true )
+ # $langcode is the language code of the wikis content language object.
+ # or it is a boolean and value is true
+ return $wgContLang;
+
+ global $wgLang;
+ if( $langcode === $wgLang->getCode() || $langcode === false )
+ # $langcode is the language code of user language object.
+ # or it was a boolean and value is false
+ return $wgLang;
+
+ $validCodes = array_keys( Language::getLanguageNames() );
+ if( in_array( $langcode, $validCodes ) )
+ # $langcode corresponds to a valid language.
+ return Language::factory( $langcode );
+
+ # $langcode is a string, but not a valid language code; use content language.
+ wfDebug( 'Invalid language code passed to wfGetLangObj, falling back to content language.' );
+ return $wgContLang;
+}
+
+/**
* Get a message from anywhere, for the current user language.
*
* Use wfMsgForContent() instead if the message should NOT
@@ -458,7 +574,7 @@ function wfMsgWeirdKey ( $key ) {
* @private
*/
function wfMsgGetKey( $key, $useDB, $langCode = false, $transform = true ) {
- global $wgParser, $wgContLang, $wgMessageCache, $wgLang;
+ global $wgContLang, $wgMessageCache;
wfRunHooks('NormalizeMessageKey', array(&$key, &$useDB, &$langCode, &$transform));
@@ -469,21 +585,7 @@ function wfMsgGetKey( $key, $useDB, $langCode = false, $transform = true ) {
$message = $wgMessageCache->transform( $message );
}
} else {
- if( $langCode === true ) {
- $lang = &$wgContLang;
- } elseif( $langCode === false ) {
- $lang = &$wgLang;
- } else {
- $validCodes = array_keys( Language::getLanguageNames() );
- if( in_array( $langCode, $validCodes ) ) {
- # $langcode corresponds to a valid language.
- $lang = Language::factory( $langCode );
- } else {
- # $langcode is a string, but not a valid language code; use content language.
- $lang =& $wgContLang;
- wfDebug( 'Invalid language code passed to wfMsgGetKey, falling back to content language.' );
- }
- }
+ $lang = wfGetLangObj( $langCode );
# MessageCache::get() does this already, Language::getMessage() doesn't
# ISSUE: Should we try to handle "message/lang" here too?
@@ -565,40 +667,47 @@ function wfMsgWikiHtml( $key ) {
/**
* Returns message in the requested format
* @param string $key Key of the message
- * @param array $options Processing rules:
- * <i>parse</i>: parses wikitext to html
- * <i>parseinline</i>: parses wikitext to html and removes the surrounding p's added by parser or tidy
- * <i>escape</i>: filters message through htmlspecialchars
- * <i>escapenoentities</i>: same, but allows entity references like &nbsp; through
- * <i>replaceafter</i>: parameters are substituted after parsing or escaping
- * <i>parsemag</i>: transform the message using magic phrases
- * <i>content</i>: fetch message for content language instead of interface
- * <i>language</i>: language code to fetch message for (overriden by <i>content</i>), its behaviour
- * with parser, parseinline and parsemag is undefined.
+ * @param array $options Processing rules. Can take the following options:
+ * <i>parse</i>: parses wikitext to html
+ * <i>parseinline</i>: parses wikitext to html and removes the surrounding
+ * p's added by parser or tidy
+ * <i>escape</i>: filters message through htmlspecialchars
+ * <i>escapenoentities</i>: same, but allows entity references like &nbsp; through
+ * <i>replaceafter</i>: parameters are substituted after parsing or escaping
+ * <i>parsemag</i>: transform the message using magic phrases
+ * <i>content</i>: fetch message for content language instead of interface
+ * Also can accept a single associative argument, of the form 'language' => 'xx':
+ * <i>language</i>: Language object or language code to fetch message for
+ * (overriden by <i>content</i>), its behaviour with parser, parseinline
+ * and parsemag is undefined.
* Behavior for conflicting options (e.g., parse+parseinline) is undefined.
*/
function wfMsgExt( $key, $options ) {
- global $wgOut, $wgParser;
+ global $wgOut;
$args = func_get_args();
array_shift( $args );
array_shift( $args );
-
- if( !is_array($options) ) {
- $options = array($options);
+ $options = (array)$options;
+
+ foreach( $options as $arrayKey => $option ) {
+ if( !preg_match( '/^[0-9]+|language$/', $arrayKey ) ) {
+ # An unknown index, neither numeric nor "language"
+ trigger_error( "wfMsgExt called with incorrect parameter key $arrayKey", E_USER_WARNING );
+ } elseif( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option,
+ array( 'parse', 'parseinline', 'escape', 'escapenoentities',
+ 'replaceafter', 'parsemag', 'content' ) ) ) {
+ # A numeric index with unknown value
+ trigger_error( "wfMsgExt called with incorrect parameter $option", E_USER_WARNING );
+ }
}
- if( in_array('content', $options) ) {
+ if( in_array('content', $options, true ) ) {
$forContent = true;
$langCode = true;
} elseif( array_key_exists('language', $options) ) {
$forContent = false;
- $langCode = $options['language'];
- $validCodes = array_keys( Language::getLanguageNames() );
- if( !in_array($options['language'], $validCodes) ) {
- # Fallback to en, instead of whatever interface language we might have
- $langCode = 'en';
- }
+ $langCode = wfGetLangObj( $options['language'] );
} else {
$forContent = false;
$langCode = false;
@@ -606,34 +715,34 @@ function wfMsgExt( $key, $options ) {
$string = wfMsgGetKey( $key, /*DB*/true, $langCode, /*Transform*/false );
- if( !in_array('replaceafter', $options) ) {
+ if( !in_array('replaceafter', $options, true ) ) {
$string = wfMsgReplaceArgs( $string, $args );
}
- if( in_array('parse', $options) ) {
+ if( in_array('parse', $options, true ) ) {
$string = $wgOut->parse( $string, true, !$forContent );
- } elseif ( in_array('parseinline', $options) ) {
+ } elseif ( in_array('parseinline', $options, true ) ) {
$string = $wgOut->parse( $string, true, !$forContent );
$m = array();
if( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
$string = $m[1];
}
- } elseif ( in_array('parsemag', $options) ) {
+ } elseif ( in_array('parsemag', $options, true ) ) {
global $wgMessageCache;
if ( isset( $wgMessageCache ) ) {
- $string = $wgMessageCache->transform( $string, !$forContent );
+ $string = $wgMessageCache->transform( $string,
+ !$forContent,
+ is_object( $langCode ) ? $langCode : null );
}
}
- if ( in_array('escape', $options) ) {
+ if ( in_array('escape', $options, true ) ) {
$string = htmlspecialchars ( $string );
- } elseif ( in_array( 'escapenoentities', $options ) ) {
- $string = htmlspecialchars( $string );
- $string = str_replace( '&amp;', '&', $string );
- $string = Sanitizer::normalizeCharReferences( $string );
+ } elseif ( in_array( 'escapenoentities', $options, true ) ) {
+ $string = Sanitizer::escapeHtmlAllowEntities( $string );
}
- if( in_array('replaceafter', $options) ) {
+ if( in_array('replaceafter', $options, true ) ) {
$string = wfMsgReplaceArgs( $string, $args );
}
@@ -707,18 +816,25 @@ function wfDebugDieBacktrace( $msg = '' ) {
* @return string
*/
function wfHostname() {
- if ( function_exists( 'posix_uname' ) ) {
- // This function not present on Windows
- $uname = @posix_uname();
- } else {
- $uname = false;
- }
- if( is_array( $uname ) && isset( $uname['nodename'] ) ) {
- return $uname['nodename'];
- } else {
- # This may be a virtual server.
- return $_SERVER['SERVER_NAME'];
+ static $host;
+ if ( is_null( $host ) ) {
+ if ( function_exists( 'posix_uname' ) ) {
+ // This function not present on Windows
+ $uname = @posix_uname();
+ } else {
+ $uname = false;
+ }
+ if( is_array( $uname ) && isset( $uname['nodename'] ) ) {
+ $host = $uname['nodename'];
+ } elseif ( getenv( 'COMPUTERNAME' ) ) {
+ # Windows computer name
+ $host = getenv( 'COMPUTERNAME' );
+ } else {
+ # This may be a virtual server.
+ $host = $_SERVER['SERVER_NAME'];
+ }
}
+ return $host;
}
/**
@@ -929,7 +1045,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
*/
function wfEscapeWikiText( $text ) {
$text = str_replace(
- array( '[', '|', ']', '\'', 'ISBN ', 'RFC ', '://', "\n=", '{{' ),
+ array( '[', '|', ']', '\'', 'ISBN ', 'RFC ', '://', "\n=", '{{' ), # }}
array( '&#91;', '&#124;', '&#93;', '&#39;', 'ISBN&#32;', 'RFC&#32;', '&#58;//', "\n&#61;", '&#123;&#123;' ),
htmlspecialchars($text) );
return $text;
@@ -1029,6 +1145,34 @@ function wfArrayToCGI( $array1, $array2 = NULL )
}
/**
+ * This is the logical opposite of wfArrayToCGI(): it accepts a query string as
+ * its argument and returns the same string in array form. This allows compa-
+ * tibility with legacy functions that accept raw query strings instead of nice
+ * arrays. Of course, keys and values are urldecode()d. Don't try passing in-
+ * valid query strings, or it will explode.
+ *
+ * @param $query string Query string
+ * @return array Array version of input
+ */
+function wfCgiToArray( $query ) {
+ if( isset( $query[0] ) and $query[0] == '?' ) {
+ $query = substr( $query, 1 );
+ }
+ $bits = explode( '&', $query );
+ $ret = array();
+ foreach( $bits as $bit ) {
+ if( $bit === '' ) {
+ continue;
+ }
+ list( $key, $value ) = explode( '=', $bit );
+ $key = urldecode( $key );
+ $value = urldecode( $value );
+ $ret[$key] = $value;
+ }
+ return $ret;
+}
+
+/**
* Append a query string to an existing URL, which may or may not already
* have query string parameters already. If so, they will be combined.
*
@@ -1132,7 +1276,7 @@ function wfMerge( $old, $mine, $yours, &$result ){
# This check may also protect against code injection in
# case of broken installations.
- if(! file_exists( $wgDiff3 ) ){
+ if( !$wgDiff3 || !file_exists( $wgDiff3 ) ) {
wfDebug( "diff3 not found\n" );
return false;
}
@@ -1246,7 +1390,10 @@ function wfDiff( $before, $after, $params = '-u' ) {
}
/**
- * @todo document
+ * A wrapper around the PHP function var_export().
+ * Either print it or add it to the regular output ($wgOut).
+ *
+ * @param $var A PHP variable to dump.
*/
function wfVarDump( $var ) {
global $wgOut;
@@ -1322,6 +1469,7 @@ function wfResetOutputBuffers( $resetGzipEncoding=true ) {
// Reset the 'Content-Encoding' field set by this handler
// so we can start fresh.
header( 'Content-Encoding:' );
+ break;
}
}
}
@@ -1568,11 +1716,11 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
# TS_ORACLE
$uts = strtotime(preg_replace('/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
str_replace("+00:00", "UTC", $ts)));
- } elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/', $ts, $da)) {
+ } elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da)) {
# TS_ISO_8601
- } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)[\+\- ](\d\d)$/',$ts,$da)) {
+ } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d*[\+\- ](\d\d)$/',$ts,$da)) {
# TS_POSTGRES
- } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/',$ts,$da)) {
+ } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/',$ts,$da)) {
# TS_POSTGRES
} else {
# Bogus value; fall back to the epoch...
@@ -1648,7 +1796,7 @@ function swap( &$x, &$y ) {
}
function wfGetCachedNotice( $name ) {
- global $wgOut, $parserMemc;
+ global $wgOut, $wgRenderHashAppend, $parserMemc;
$fname = 'wfGetCachedNotice';
wfProfileIn( $fname );
@@ -1670,7 +1818,9 @@ function wfGetCachedNotice( $name ) {
}
}
- $cachedNotice = $parserMemc->get( wfMemcKey( $name ) );
+ // Use the extra hash appender to let eg SSL variants separately cache.
+ $key = wfMemcKey( $name . $wgRenderHashAppend );
+ $cachedNotice = $parserMemc->get( $key );
if( is_array( $cachedNotice ) ) {
if( md5( $notice ) == $cachedNotice['hash'] ) {
$notice = $cachedNotice['html'];
@@ -1684,7 +1834,7 @@ function wfGetCachedNotice( $name ) {
if( $needParse ) {
if( is_object( $wgOut ) ) {
$parsed = $wgOut->parse( $notice );
- $parserMemc->set( wfMemcKey( $name ), array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
+ $parserMemc->set( $key, array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
$notice = $parsed;
} else {
wfDebug( 'wfGetCachedNotice called for ' . $name . ' with no $wgOut available' );
@@ -1777,69 +1927,20 @@ function wfTempDir() {
/**
* Make directory, and make all parent directories if they don't exist
*
- * @param string $fullDir Full path to directory to create
+ * @param string $dir Full path to directory to create
* @param int $mode Chmod value to use, default is $wgDirectoryMode
* @return bool
*/
-function wfMkdirParents( $fullDir, $mode = null ) {
+function wfMkdirParents( $dir, $mode = null ) {
global $wgDirectoryMode;
- if( strval( $fullDir ) === '' )
- return true;
- if( file_exists( $fullDir ) )
- return true;
- // If not defined or isn't an int, set to default
- if ( is_null( $mode ) ) {
- $mode = $wgDirectoryMode;
- }
-
-
- # Go back through the paths to find the first directory that exists
- $currentDir = $fullDir;
- $createList = array();
- while ( strval( $currentDir ) !== '' && !file_exists( $currentDir ) ) {
- # Strip trailing slashes
- $currentDir = rtrim( $currentDir, '/\\' );
- # Add to create list
- $createList[] = $currentDir;
-
- # Find next delimiter searching from the end
- $p = max( strrpos( $currentDir, '/' ), strrpos( $currentDir, '\\' ) );
- if ( $p === false ) {
- $currentDir = false;
- } else {
- $currentDir = substr( $currentDir, 0, $p );
- }
- }
-
- if ( count( $createList ) == 0 ) {
- # Directory specified already exists
+ if( strval( $dir ) === '' || file_exists( $dir ) )
return true;
- } elseif ( $currentDir === false ) {
- # Went all the way back to root and it apparently doesn't exist
- wfDebugLog( 'mkdir', "Root doesn't exist?\n" );
- return false;
- }
- # Now go forward creating directories
- $createList = array_reverse( $createList );
- # Is the parent directory writable?
- if ( $currentDir === '' ) {
- $currentDir = '/';
- }
- if ( !is_writable( $currentDir ) ) {
- wfDebugLog( 'mkdir', "Not writable: $currentDir\n" );
- return false;
- }
+ if ( is_null( $mode ) )
+ $mode = $wgDirectoryMode;
- foreach ( $createList as $dir ) {
- # use chmod to override the umask, as suggested by the PHP manual
- if ( !mkdir( $dir, $mode ) || !chmod( $dir, $mode ) ) {
- wfDebugLog( 'mkdir', "Unable to create directory $dir\n" );
- return false;
- }
- }
- return true;
+ return mkdir( $dir, $mode, true ); // PHP5 <3
}
/**
@@ -1998,7 +2099,7 @@ function wfIniGetBool( $setting ) {
* @return collected stdout as a string (trailing newlines stripped)
*/
function wfShellExec( $cmd, &$retval=null ) {
- global $IP, $wgMaxShellMemory, $wgMaxShellFileSize;
+ global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime;
if( wfIniGetBool( 'safe_mode' ) ) {
wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
@@ -2008,7 +2109,7 @@ function wfShellExec( $cmd, &$retval=null ) {
wfInitShellLocale();
if ( php_uname( 's' ) == 'Linux' ) {
- $time = intval( ini_get( 'max_execution_time' ) );
+ $time = intval( $wgMaxShellTime );
$mem = intval( $wgMaxShellMemory );
$filesize = intval( $wgMaxShellFileSize );
@@ -2030,6 +2131,10 @@ function wfShellExec( $cmd, &$retval=null ) {
passthru( $cmd, $retval );
$output = ob_get_contents();
ob_end_clean();
+
+ if ( $retval == 127 ) {
+ wfDebugLog( 'exec', "Possibly missing executable file: $cmd\n" );
+ }
return $output;
}
@@ -2167,28 +2272,51 @@ function wfRelativePath( $path, $from ) {
}
/**
- * array_merge() does awful things with "numeric" indexes, including
- * string indexes when happen to look like integers. When we want
- * to merge arrays with arbitrary string indexes, we don't want our
- * arrays to be randomly corrupted just because some of them consist
- * of numbers.
- *
- * Fuck you, PHP. Fuck you in the ear!
+ * Backwards array plus for people who haven't bothered to read the PHP manual
+ * XXX: will not darn your socks for you.
*
* @param array $array1, [$array2, [...]]
* @return array
*/
function wfArrayMerge( $array1/* ... */ ) {
- $out = $array1;
- for( $i = 1; $i < func_num_args(); $i++ ) {
- foreach( func_get_arg( $i ) as $key => $value ) {
- $out[$key] = $value;
- }
+ $args = func_get_args();
+ $args = array_reverse( $args, true );
+ $out = array();
+ foreach ( $args as $arg ) {
+ $out += $arg;
}
return $out;
}
/**
+ * Merge arrays in the style of getUserPermissionsErrors, with duplicate removal
+ * e.g.
+ * wfMergeErrorArrays(
+ * array( array( 'x' ) ),
+ * array( array( 'x', '2' ) ),
+ * array( array( 'x' ) ),
+ * array( array( 'y') )
+ * );
+ * returns:
+ * array(
+ * array( 'x', '2' ),
+ * array( 'x' ),
+ * array( 'y' )
+ * )
+ */
+function wfMergeErrorArrays(/*...*/) {
+ $args = func_get_args();
+ $out = array();
+ foreach ( $args as $errors ) {
+ foreach ( $errors as $params ) {
+ $spec = implode( "\t", $params );
+ $out[$spec] = $params;
+ }
+ }
+ return array_values( $out );
+}
+
+/**
* Make a URL index, appropriate for the el_index field of externallinks.
*/
function wfMakeUrlIndex( $url ) {
@@ -2560,7 +2688,7 @@ function wfSplitWikiID( $wiki ) {
* will always return the same object, unless the underlying connection or load
* balancer is manually destroyed.
*/
-function &wfGetDB( $db = DB_LAST, $groups = array(), $wiki = false ) {
+function &wfGetDB( $db, $groups = array(), $wiki = false ) {
return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
}
@@ -2590,10 +2718,15 @@ function &wfGetLBFactory() {
* current version. An image object will be returned which
* was created at the specified time.
* @param mixed $flags FileRepo::FIND_ flags
+ * @param boolean $bypass Bypass the file cache even if it could be used
* @return File, or false if the file does not exist
*/
-function wfFindFile( $title, $time = false, $flags = 0 ) {
- return RepoGroup::singleton()->findFile( $title, $time, $flags );
+function wfFindFile( $title, $time = false, $flags = 0, $bypass = false ) {
+ if( !$time && !$flags && !$bypass ) {
+ return FileCache::singleton()->findFile( $title );
+ } else {
+ return RepoGroup::singleton()->findFile( $title, $time, $flags );
+ }
}
/**
@@ -2646,6 +2779,8 @@ function wfBoolToStr( $value ) {
* @param string $extensionName Name of extension to load messages from\for.
* @param string $langcode Language to load messages for, or false for default
* behvaiour (en, content language and user language).
+ * @since r24808 (v1.11) Using this method of loading extension messages will not work
+ * on MediaWiki prior to that
*/
function wfLoadExtensionMessages( $extensionName, $langcode = false ) {
global $wgExtensionMessagesFiles, $wgMessageCache, $wgLang, $wgContLang;