Merge "Hygiene: Use strtr() instead of str_replace() for character swapping"
[lhc/web/wiklou.git] / includes / GlobalFunctions.php
index 7a9b27b..21b584b 100644 (file)
@@ -402,12 +402,17 @@ function wfRandomString( $length = 32 ) {
  *
  * ;:@&=$-_.+!*'(),
  *
+ * RFC 1738 says ~ is unsafe, however RFC 3986 considers it an unreserved
+ * character which should not be encoded. More importantly, google chrome
+ * always converts %7E back to ~, and converting it in this function can
+ * cause a redirect loop (T105265).
+ *
  * 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:
  *
- * ;:@$!*(),/
+ * ;:@$!*(),/~
  *
  * However, IIS7 redirects fail when the url contains a colon (Bug 22709),
  * so no fancy : for IIS7.
@@ -426,7 +431,7 @@ function wfUrlencode( $s ) {
        }
 
        if ( is_null( $needle ) ) {
-               $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
+               $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F', '%7E' );
                if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
                        ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
                ) {
@@ -437,7 +442,7 @@ function wfUrlencode( $s ) {
        $s = urlencode( $s );
        $s = str_ireplace(
                $needle,
-               array( ';', '@', '$', '!', '*', '(', ')', ',', '/', ':' ),
+               array( ';', '@', '$', '!', '*', '(', ')', ',', '/', '~', ':' ),
                $s
        );
 
@@ -1248,7 +1253,7 @@ function wfLogProfilingData() {
        $profiler->logData();
 
        $config = $context->getConfig();
-       if ( $config->has( 'StatsdServer' ) ) {
+       if ( $config->get( 'StatsdServer' ) ) {
                $statsdServer = explode( ':', $config->get( 'StatsdServer' ) );
                $statsdHost = $statsdServer[0];
                $statsdPort = isset( $statsdServer[1] ) ? $statsdServer[1] : 8125;
@@ -1756,7 +1761,7 @@ function wfMsgExt( $key, $options ) {
        }
 
        if ( in_array( 'escape', $options, true ) ) {
-               $string = htmlspecialchars ( $string );
+               $string = htmlspecialchars( $string );
        } elseif ( in_array( 'escapenoentities', $options, true ) ) {
                $string = Sanitizer::escapeHtmlAllowEntities( $string );
        }
@@ -2758,7 +2763,7 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
 
        $useLogPipe = false;
        if ( is_executable( '/bin/bash' ) ) {
-               $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
+               $time = intval( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
                if ( isset( $limits['walltime'] ) ) {
                        $wallTime = intval( $limits['walltime'] );
                } elseif ( isset( $limits['time'] ) ) {
@@ -2766,8 +2771,8 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
                } else {
                        $wallTime = intval( $wgMaxShellWallClockTime );
                }
-               $mem = intval ( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
-               $filesize = intval ( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
+               $mem = intval( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
+               $filesize = intval( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
 
                if ( $time > 0 || $mem > 0 || $filesize > 0 || $wallTime > 0 ) {
                        $cmd = '/bin/bash ' . escapeshellarg( "$IP/includes/limit.sh" ) . ' ' .
@@ -3495,7 +3500,7 @@ function wfGetPrecompiledData( $name ) {
 }
 
 /**
- * Get a cache key
+ * Make a cache key for the local wiki.
  *
  * @param string $args,...
  * @return string
@@ -3505,12 +3510,13 @@ function wfMemcKey( /*...*/ ) {
        $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
        $args = func_get_args();
        $key = $prefix . ':' . implode( ':', $args );
-       $key = str_replace( ' ', '_', $key );
-       return $key;
+       return strtr( $key, ' ', '_' );
 }
 
 /**
- * Get a cache key for a foreign DB
+ * Make a cache key for a foreign DB.
+ *
+ * Must match what wfMemcKey() would produce in context of the foreign wiki.
  *
  * @param string $db
  * @param string $prefix
@@ -3520,11 +3526,29 @@ function wfMemcKey( /*...*/ ) {
 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
        $args = array_slice( func_get_args(), 2 );
        if ( $prefix ) {
+               // Match wfWikiID() logic
                $key = "$db-$prefix:" . implode( ':', $args );
        } else {
                $key = $db . ':' . implode( ':', $args );
        }
-       return str_replace( ' ', '_', $key );
+       return strtr( $key, ' ', '_' );
+}
+
+/**
+ * Make a cache key with database-agnostic prefix.
+ *
+ * Doesn't have a wiki-specific namespace. Uses a generic 'global' prefix
+ * instead. Must have a prefix as otherwise keys that use a database name
+ * in the first segment will clash with wfMemcKey/wfForeignMemcKey.
+ *
+ * @since 1.26
+ * @param string $args,...
+ * @return string
+ */
+function wfGlobalCacheKey( /*...*/ ) {
+       $args = func_get_args();
+       $key = 'global:' . implode( ':', $args );
+       return strtr( $key, ' ', '_' );
 }
 
 /**