dépôts
/
lhc
/
web
/
wiklou.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Remove most named character references from output
[lhc/web/wiklou.git]
/
includes
/
GlobalFunctions.php
diff --git
a/includes/GlobalFunctions.php
b/includes/GlobalFunctions.php
index
53e0b87
..
005fb8e
100644
(file)
--- a/
includes/GlobalFunctions.php
+++ b/
includes/GlobalFunctions.php
@@
-9,7
+9,6
@@
if ( !defined( 'MEDIAWIKI' ) ) {
*/
require_once dirname(__FILE__) . '/normal/UtfNormalUtil.php';
*/
require_once dirname(__FILE__) . '/normal/UtfNormalUtil.php';
-require_once dirname(__FILE__) . '/XmlFunctions.php';
// Hide compatibility functions from Doxygen
/// @cond
// Hide compatibility functions from Doxygen
/// @cond
@@
-173,23
+172,6
@@
if( !function_exists( 'mb_strrpos' ) ) {
}
}
}
}
-if ( !function_exists( 'array_diff_key' ) ) {
- /**
- * Exists in PHP 5.1.0+
- * Not quite compatible, two-argument version only
- * Null values will cause problems due to this use of isset()
- */
- function array_diff_key( $left, $right ) {
- $result = $left;
- foreach ( $left as $key => $unused ) {
- if ( isset( $right[$key] ) ) {
- unset( $result[$key] );
- }
- }
- return $result;
- }
-}
-
// Support for Wietse Venema's taint feature
if ( !function_exists( 'istainted' ) ) {
function istainted( $var ) {
// Support for Wietse Venema's taint feature
if ( !function_exists( 'istainted' ) ) {
function istainted( $var ) {
@@
-230,15
+212,6
@@
function wfArrayDiff2_cmp( $a, $b ) {
}
}
}
}
-/**
- * Wrapper for clone(), for compatibility with PHP4-friendly extensions.
- * PHP 5 won't let you declare a 'clone' function, even conditionally,
- * so it has to be a wrapper with a different name.
- */
-function wfClone( $object ) {
- return clone( $object );
-}
-
/**
* Seed Mersenne Twister
* No-op for compatibility; only necessary in PHP < 4.2.0
/**
* Seed Mersenne Twister
* No-op for compatibility; only necessary in PHP < 4.2.0
@@
-277,16
+250,27
@@
function wfRandom() {
*
* ;:@$!*(),/
*
*
* ;:@$!*(),/
*
+ * However, IIS7 redirects fail when the url contains a colon (Bug 22709),
+ * so no fancy : for IIS7.
+ *
* %2F in the page titles seems to fatally break for some reason.
*
* @param $s String:
* @return string
*/
function wfUrlencode( $s ) {
* %2F in the page titles seems to fatally break for some reason.
*
* @param $s String:
* @return string
*/
function wfUrlencode( $s ) {
+ static $needle;
+ if ( is_null( $needle ) ) {
+ $needle = array( '%3B','%40','%24','%21','%2A','%28','%29','%2C','%2F' );
+ if (! isset($_SERVER['SERVER_SOFTWARE']) || ( strpos($_SERVER['SERVER_SOFTWARE'], "Microsoft-IIS/7") === false)) {
+ $needle[] = '%3A';
+ }
+ }
+
$s = urlencode( $s );
$s = str_ireplace(
$s = urlencode( $s );
$s = str_ireplace(
-
array( '%3B','%3A','%40','%24','%21','%2A','%28','%29','%2C','%2F' )
,
- array(
';', ':', '@', '$', '!', '*', '(', ')', ',', '/
' ),
+
$needle
,
+ array(
';', '@', '$', '!', '*', '(', ')', ',', '/', ':
' ),
$s
);
$s
);
@@
-312,6
+296,7
@@
function wfDebug( $text, $logonly = false ) {
static $recursion = 0;
static $cache = array(); // Cache of unoutputted messages
static $recursion = 0;
static $cache = array(); // Cache of unoutputted messages
+ $text = wfDebugTimer() . $text;
# Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) {
# Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) {
@@
-337,7
+322,7
@@
function wfDebug( $text, $logonly = false ) {
array_map( array( $wgOut, 'debug' ), $cache );
$cache = array();
}
array_map( array( $wgOut, 'debug' ), $cache );
$cache = array();
}
- if (
'' != $wgDebugLogFile
&& !$wgProfileOnly ) {
+ if (
$wgDebugLogFile != ''
&& !$wgProfileOnly ) {
# 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 );
# 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 );
@@
-346,6
+331,21
@@
function wfDebug( $text, $logonly = false ) {
}
}
}
}
+function wfDebugTimer() {
+ global $wgDebugTimestamps;
+ if ( !$wgDebugTimestamps ) return '';
+ static $start = null;
+
+ if ( $start === null ) {
+ $start = microtime( true );
+ $prefix = "\n$start";
+ } else {
+ $prefix = sprintf( "%6.4f", microtime( true ) - $start );
+ }
+
+ return $prefix . ' ';
+}
+
/**
* Send a line giving PHP memory usage.
* @param $exact Bool: print exact values instead of kilobytes (default: false)
/**
* Send a line giving PHP memory usage.
* @param $exact Bool: print exact values instead of kilobytes (default: false)
@@
-458,7
+458,7
@@
function wfLogProfilingData() {
global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
global $wgProfiler, $wgProfileLimit, $wgUser;
# Profiling must actually be enabled...
global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
global $wgProfiler, $wgProfileLimit, $wgUser;
# Profiling must actually be enabled...
- if(
!isset
( $wgProfiler ) ) return;
+ if(
is_null
( $wgProfiler ) ) return;
# Get total page request time
$now = wfTime();
$elapsed = $now - $wgRequestTime;
# Get total page request time
$now = wfTime();
$elapsed = $now - $wgRequestTime;
@@
-480,7
+480,7
@@
function wfLogProfilingData() {
$log = sprintf( "%s\t%04.3f\t%s\n",
gmdate( 'YmdHis' ), $elapsed,
urldecode( $wgRequest->getRequestURL() . $forward ) );
$log = sprintf( "%s\t%04.3f\t%s\n",
gmdate( 'YmdHis' ), $elapsed,
urldecode( $wgRequest->getRequestURL() . $forward ) );
- if (
'' != $wgDebugLogFile
&& ( $wgRequest->getVal('action') != 'raw' || $wgDebugRawPage ) ) {
+ if (
$wgDebugLogFile != ''
&& ( $wgRequest->getVal('action') != 'raw' || $wgDebugRawPage ) ) {
wfErrorLog( $log . $prof, $wgDebugLogFile );
}
}
wfErrorLog( $log . $prof, $wgDebugLogFile );
}
}
@@
-497,7
+497,7
@@
function wfReadOnly() {
if ( !is_null( $wgReadOnly ) ) {
return (bool)$wgReadOnly;
}
if ( !is_null( $wgReadOnly ) ) {
return (bool)$wgReadOnly;
}
- if (
'' == $wgReadOnlyFile
) {
+ if (
$wgReadOnlyFile == ''
) {
return false;
}
// Set $wgReadOnly for faster access next time
return false;
}
// Set $wgReadOnly for faster access next time
@@
-600,8
+600,8
@@
function wfMsgNoTrans( $key ) {
*
* Be wary of this distinction: If you use wfMsg() where you should
* use wfMsgForContent(), a user of the software may have to
*
* Be wary of this distinction: If you use wfMsg() where you should
* use wfMsgForContent(), a user of the software may have to
- * customize
over 70 messages in order to, e.g., fix a link in every
- * possible language.
+ * customize
potentially hundreds of messages in
+ *
order to, e.g., fix a link in every
possible language.
*
* @param $key String: lookup key for the message, usually
* defined in languages/Language.php
*
* @param $key String: lookup key for the message, usually
* defined in languages/Language.php
@@
-660,8
+660,8
@@
function wfMsgNoDBForContent( $key ) {
* @param $key String: key to get.
* @param $args
* @param $useDB Boolean
* @param $key String: key to get.
* @param $args
* @param $useDB Boolean
- * @param $transform Boolean: Whether or not to transform the message.
* @param $forContent Mixed: Language code, or false for user lang, true for content lang.
* @param $forContent Mixed: Language code, or false for user lang, true for content lang.
+ * @param $transform Boolean: Whether or not to transform the message.
* @return String: the requested message.
*/
function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
* @return String: the requested message.
*/
function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
@@
-702,7
+702,9
@@
function wfMsgGetKey( $key, $useDB, $langCode = false, $transform = true ) {
# If $wgMessageCache isn't initialised yet, try to return something sensible.
if( is_object( $wgMessageCache ) ) {
$message = $wgMessageCache->get( $key, $useDB, $langCode );
# If $wgMessageCache isn't initialised yet, try to return something sensible.
if( is_object( $wgMessageCache ) ) {
$message = $wgMessageCache->get( $key, $useDB, $langCode );
- if ( $transform ) {
+ if( $message === false ){
+ $message = '<' . htmlspecialchars( $key ) . '>';
+ } elseif ( $transform ) {
$message = $wgMessageCache->transform( $message );
}
} else {
$message = $wgMessageCache->transform( $message );
}
} else {
@@
-793,7
+795,7
@@
function wfMsgWikiHtml( $key ) {
* <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>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>escapenoentities</i>: same, but allows entity references like &
#160
; 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>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
@@
-1167,8
+1169,7
@@
function wfNumLink( $offset, $limit, $title, $query = '' ) {
* @return bool Whereas client accept gzip compression
*/
function wfClientAcceptsGzip() {
* @return bool Whereas client accept gzip compression
*/
function wfClientAcceptsGzip() {
- global $wgUseGzip;
- if( $wgUseGzip ) {
+ if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
# FIXME: we may want to blacklist some broken browsers
$m = array();
if( preg_match(
# FIXME: we may want to blacklist some broken browsers
$m = array();
if( preg_match(
@@
-1277,7
+1278,7
@@
function wfSetBit( &$dest, $bit, $state = true ) {
* "days=7&limit=100". Options in the first array override options in the second.
* Options set to "" will not be output.
*/
* "days=7&limit=100". Options in the first array override options in the second.
* Options set to "" will not be output.
*/
-function wfArrayToCGI( $array1, $array2 =
NULL
)
+function wfArrayToCGI( $array1, $array2 =
null
)
{
if ( !is_null( $array2 ) ) {
$array1 = $array1 + $array2;
{
if ( !is_null( $array2 ) ) {
$array1 = $array1 + $array2;
@@
-1285,8
+1286,8
@@
function wfArrayToCGI( $array1, $array2 = NULL )
$cgi = '';
foreach ( $array1 as $key => $value ) {
$cgi = '';
foreach ( $array1 as $key => $value ) {
- if (
'' !== $value
) {
- if (
'' != $cgi
) {
+ if (
$value !== ''
) {
+ if (
$cgi != ''
) {
$cgi .= '&';
}
if ( is_array( $value ) ) {
$cgi .= '&';
}
if ( is_array( $value ) ) {
@@
-1362,16
+1363,19
@@
function wfAppendQuery( $url, $query ) {
/**
* Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer
/**
* Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer
- *
is correct. Also doesn't handle any type of relative URL except one
- *
starting with a single "/": this won't work with current-path-relative URLs
- *
like "subdir/foo.html", protocol-relative URLs like
- *
"//en.wikipedia.org/wiki/", etc. TODO: improve this!
+ *
and $wgProto are correct.
+ *
+ *
@todo this won't work with current-path-relative URLs
+ *
like "subdir/foo.html", etc.
*
* @param $url String: either fully-qualified or a local path + query
* @return string Fully-qualified URL
*/
function wfExpandUrl( $url ) {
*
* @param $url String: either fully-qualified or a local path + query
* @return string Fully-qualified URL
*/
function wfExpandUrl( $url ) {
- if( substr( $url, 0, 1 ) == '/' ) {
+ if( substr( $url, 0, 2 ) == '//' ) {
+ global $wgProto;
+ return $wgProto . ':' . $url;
+ } elseif( substr( $url, 0, 1 ) == '/' ) {
global $wgServer;
return $wgServer . $url;
} else {
global $wgServer;
return $wgServer . $url;
} else {
@@
-1423,13
+1427,17
@@
function wfEscapeShellArg( ) {
}
$delim = !$delim;
}
}
$delim = !$delim;
}
+
// Double the backslashes before the end of the string, because
// we will soon add a quote
$m = array();
if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
$arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
}
// Double the backslashes before the end of the string, because
// we will soon add a quote
$m = array();
if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
$arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
}
-
+
+ // The caret is also an special character
+ $arg = str_replace( "^", "^^", $arg );
+
// Add surrounding quotes
$retVal .= '"' . $arg . '"';
} else {
// Add surrounding quotes
$retVal .= '"' . $arg . '"';
} else {
@@
-1717,7
+1725,7
@@
function mimeTypeMatch( $type, $avail ) {
} elseif( array_key_exists( '*/*', $avail ) ) {
return '*/*';
} else {
} elseif( array_key_exists( '*/*', $avail ) ) {
return '*/*';
} else {
- return
NULL
;
+ return
null
;
}
}
}
}
}
}
@@
-1759,7
+1767,7
@@
function wfNegotiateType( $cprefs, $sprefs ) {
}
$bestq = 0;
}
$bestq = 0;
- $besttype =
NULL
;
+ $besttype =
null
;
foreach( array_keys( $combine ) as $type ) {
if( $combine[$type] > $bestq ) {
foreach( array_keys( $combine ) as $type ) {
if( $combine[$type] > $bestq ) {
@@
-1807,7
+1815,7
@@
function wfSuppressWarnings( $end = false ) {
}
} else {
if ( !$suppressCount ) {
}
} else {
if ( !$suppressCount ) {
- $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) );
+ $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE
| E_USER_WARNING | E_USER_NOTICE
) );
}
++$suppressCount;
}
}
++$suppressCount;
}
@@
-2089,9
+2097,10
@@
function &wfGetMimeMagic() {
}
/**
}
/**
- * Tries to get the system directory for temporary files.
- * The TMPDIR, TMP, and TEMP environment variables are checked in sequence,
- * and if none are set /tmp is returned as the generic Unix default.
+ * Tries to get the system directory for temporary files. For PHP >= 5.2.1,
+ * we'll use sys_get_temp_dir(). The TMPDIR, TMP, and TEMP environment
+ * variables are then checked in sequence, and if none are set /tmp is
+ * returned as the generic Unix default.
*
* NOTE: When possible, use the tempfile() function to create temporary
* files to avoid race conditions on file creation, etc.
*
* NOTE: When possible, use the tempfile() function to create temporary
* files to avoid race conditions on file creation, etc.
@@
-2099,6
+2108,9
@@
function &wfGetMimeMagic() {
* @return String
*/
function wfTempDir() {
* @return String
*/
function wfTempDir() {
+ if( function_exists( 'sys_get_temp_dir' ) ) {
+ return sys_get_temp_dir();
+ }
foreach( array( 'TMPDIR', 'TMP', 'TEMP' ) as $var ) {
$tmp = getenv( $var );
if( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
foreach( array( 'TMPDIR', 'TMP', 'TEMP' ) as $var ) {
$tmp = getenv( $var );
if( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
@@
-2209,12
+2221,12
@@
function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
* looked up didn't exist but a XHTML string, this function checks for the
* nonexistance of messages by looking at wfMsg() output
*
* looked up didn't exist but a XHTML string, this function checks for the
* nonexistance of messages by looking at wfMsg() output
*
- * @param $msg String: the message key looked up
- * @param $wfMsgOut String: the output of wfMsg*()
- * @return Boolean
+ * @param $key String: the message key looked up
+ * @return Boolean True if the message *doesn't* exist.
*/
*/
-function wfEmptyMsg( $msg, $wfMsgOut ) {
- return $wfMsgOut === htmlspecialchars( "<$msg>" );
+function wfEmptyMsg( $key ) {
+ global $wgMessageCache;
+ return $wgMessageCache->get( $key, /*useDB*/true, /*content*/false ) === false;
}
/**
}
/**
@@
-2241,9
+2253,7
@@
function wfSpecialList( $page, $details ) {
*/
function wfUrlProtocols() {
global $wgUrlProtocols;
*/
function wfUrlProtocols() {
global $wgUrlProtocols;
-
- // This function is called a lot, cache its return value
- // TODO: Cache this in memcached instead?
+
static $retval = null;
if ( !is_null( $retval ) )
return $retval;
static $retval = null;
if ( !is_null( $retval ) )
return $retval;
@@
-2259,7
+2269,6
@@
function wfUrlProtocols() {
} else {
$retval = $wgUrlProtocols;
}
} else {
$retval = $wgUrlProtocols;
}
-
return $retval;
}
return $retval;
}
@@
-2528,11
+2537,13
@@
function wfArrayMerge( $array1/* ... */ ) {
* array( 'y' )
* )
*/
* array( 'y' )
* )
*/
-function wfMergeErrorArrays(
/*...*/
) {
+function wfMergeErrorArrays(
/*...*/
) {
$args = func_get_args();
$out = array();
foreach ( $args as $errors ) {
foreach ( $errors as $params ) {
$args = func_get_args();
$out = array();
foreach ( $args as $errors ) {
foreach ( $errors as $params ) {
+ # FIXME: sometimes get nested arrays for $params,
+ # which leads to E_NOTICEs
$spec = implode( "\t", $params );
$out[$spec] = $params;
}
$spec = implode( "\t", $params );
$out[$spec] = $params;
}
@@
-2755,15
+2766,6
@@
function wfCreateObject( $name, $p ){
}
}
}
}
-/**
- * Alias for modularized function
- * @deprecated Use Http::get() instead
- */
-function wfGetHTTP( $url ) {
- wfDeprecated(__FUNCTION__);
- return Http::get( $url );
-}
-
/**
* Alias for modularized function
* @deprecated Use Http::isLocalURL() instead
/**
* Alias for modularized function
* @deprecated Use Http::isLocalURL() instead
@@
-2896,9
+2898,7
@@
function wfForeignMemcKey( $db, $prefix /*, ... */ ) {
* This is used as a prefix in memcached keys
*/
function wfWikiID() {
* This is used as a prefix in memcached keys
*/
function wfWikiID() {
- global $wgDBprefix, $wgDBname, $wgWikiId;
- if( $wgWikiId )
- return $wgWikiId;
+ global $wgDBprefix, $wgDBname;
if ( $wgDBprefix ) {
return "$wgDBname-$wgDBprefix";
} else {
if ( $wgDBprefix ) {
return "$wgDBname-$wgDBprefix";
} else {
@@
-2957,6
+2957,7
@@
function &wfGetLBFactory() {
/**
* Find a file.
* Shortcut for RepoGroup::singleton()->findFile()
/**
* Find a file.
* Shortcut for RepoGroup::singleton()->findFile()
+ * @param $title Either a string or Title object
* @param $options Associative array of options:
* time: requested time for an archived image, or false for the
* current version. An image object will be returned which was
* @param $options Associative array of options:
* time: requested time for an archived image, or false for the
* current version. An image object will be returned which was
@@
-2979,6
+2980,8
@@
function wfFindFile( $title, $options = array() ) {
/**
* Get an object referring to a locally registered file.
* Returns a valid placeholder object if the file does not exist.
/**
* Get an object referring to a locally registered file.
* Returns a valid placeholder object if the file does not exist.
+ * @param $title Either a string or Title object
+ * @return File, or null if passed an invalid Title
*/
function wfLocalFile( $title ) {
return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
*/
function wfLocalFile( $title ) {
return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
@@
-3044,7
+3047,7
@@
function wfBoolToStr( $value ) {
/**
* Load an extension messages file
/**
* Load an extension messages file
- * @deprecated
+ * @deprecated
in 1.16 (warnings in 1.18, removed in ?)
*/
function wfLoadExtensionMessages( $extensionName, $langcode = false ) {
}
*/
function wfLoadExtensionMessages( $extensionName, $langcode = false ) {
}
@@
-3081,21
+3084,6
@@
function wfMaxlagError( $host, $lag, $maxLag ) {
}
}
}
}
-/**
- * Displays a avglag error
- *
- * @param $lag Integer: avglag (actual)
- * @param $avgLag Integer: avglag (requested)
- */
-function wfAvglagError( $lag, $avgLag ) {
- header( 'HTTP/1.1 503 Service Unavailable' );
- header( 'Retry-After: ' . max( intval( $avgLag ), 5 ) );
- header( 'X-Database-Lag: ' . intval( $lag ) );
- header( 'Content-Type: text/plain' );
-
- echo "Lagged: $lag seconds average\n";
-}
-
/**
* Throws a warning that $function is deprecated
* @param $function String
/**
* Throws a warning that $function is deprecated
* @param $function String
@@
-3161,7
+3149,7
@@
function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
function wfWaitForSlaves( $maxLag, $wiki = false ) {
if( $maxLag ) {
$lb = wfGetLB( $wiki );
function wfWaitForSlaves( $maxLag, $wiki = false ) {
if( $maxLag ) {
$lb = wfGetLB( $wiki );
- list( $host, $lag ) = $lb->getMaxLag();
+ list( $host, $lag ) = $lb->getMaxLag(
$wiki
);
while( $lag > $maxLag ) {
$name = @gethostbyaddr( $host );
if( $name !== false ) {
while( $lag > $maxLag ) {
$name = @gethostbyaddr( $host );
if( $name !== false ) {
@@
-3338,3
+3326,14
@@
function wfBCP47( $code ) {
$langCode = implode ( '-' , $codeBCP );
return $langCode;
}
$langCode = implode ( '-' , $codeBCP );
return $langCode;
}
+
+function wfArrayMap( $function, $input ) {
+ $ret = array_map( $function, $input );
+ foreach ( $ret as $key => $value ) {
+ $taint = istainted( $input[$key] );
+ if ( $taint ) {
+ taint( $ret[$key], $taint );
+ }
+ }
+ return $ret;
+}