return gzinflate( substr( $data, 10, -8 ) );
}
}
+
+// hash_equals function only exists in PHP >= 5.6.0
+if ( !function_exists( 'hash_equals' ) ) {
+ /**
+ * Check whether a user-provided string is equal to a fixed-length secret without
+ * revealing bytes of the secret through timing differences.
+ *
+ * This timing guarantee -- that a partial match takes the same time as a complete
+ * mismatch -- is why this function is used in some security-sensitive parts of the code.
+ * For example, it shouldn't be possible to guess an HMAC signature one byte at a time.
+ *
+ * Longer explanation: http://www.emerose.com/timing-attacks-explained
+ *
+ * @codeCoverageIgnore
+ * @param string $known_string Fixed-length secret to compare against
+ * @param string $user_string User-provided string
+ * @return bool True if the strings are the same, false otherwise
+ */
+ function hash_equals( $known_string, $user_string ) {
+ // Strict type checking as in PHP's native implementation
+ if ( !is_string( $known_string ) ) {
+ trigger_error( 'hash_equals(): Expected known_string to be a string, ' .
+ gettype( $known_string ) . ' given', E_USER_WARNING );
+
+ return false;
+ }
+
+ if ( !is_string( $user_string ) ) {
+ trigger_error( 'hash_equals(): Expected user_string to be a string, ' .
+ gettype( $user_string ) . ' given', E_USER_WARNING );
+
+ return false;
+ }
+
+ // Note that we do one thing PHP doesn't: try to avoid leaking information about
+ // relative lengths of $known_string and $user_string, and of multiple $known_strings.
+ // However, lengths may still inevitably leak through, for example, CPU cache misses.
+ $known_string_len = strlen( $known_string );
+ $user_string_len = strlen( $user_string );
+ $result = $known_string_len ^ $user_string_len;
+ for ( $i = 0; $i < $user_string_len; $i++ ) {
+ $result |= ord( $known_string[$i % $known_string_len] ) ^ ord( $user_string[$i] );
+ }
+
+ return ( $result === 0 );
+ }
+}
/// @endcond
/**
* no valid URL can be constructed
*/
function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
- global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest;
+ global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest,
+ $wgHttpsPort;
if ( $defaultProto === PROTO_CANONICAL ) {
$serverUrl = $wgCanonicalServer;
} elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
}
$bits = wfParseUrl( $url );
+
+ // ensure proper port for HTTPS arrives in URL
+ // https://bugzilla.wikimedia.org/show_bug.cgi?id=65184
+ if ( $defaultProto === PROTO_HTTPS && $wgHttpsPort != 443 ) {
+ $bits['port'] = $wgHttpsPort;
+ }
+
if ( $bits && isset( $bits['path'] ) ) {
$bits['path'] = wfRemoveDotSegments( $bits['path'] );
return wfAssembleUrl( $bits );
/**
* Send a line giving PHP memory usage.
*
- * @param bool $exact Print exact values instead of kilobytes (default: false)
+ * @param bool $exact Print exact byte values instead of kibibytes (default: false)
*/
function wfDebugMem( $exact = false ) {
$mem = memory_get_usage();
if ( !$exact ) {
- $mem = floor( $mem / 1024 ) . ' kilobytes';
+ $mem = floor( $mem / 1024 ) . ' KiB';
} else {
- $mem .= ' bytes';
+ $mem .= ' B';
}
wfDebug( "Memory usage: $mem\n" );
}
}
if ( $parseInline ) {
- $m = array();
- if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
- $string = $m[1];
- }
+ $string = Parser::stripOuterParagraph( $string );
}
} elseif ( in_array( 'parsemag', $options, true ) ) {
$string = $messageCache->transform( $string,
$readyPipes = $pipes;
// Clear last error
+ // @codingStandardsIgnoreStart Generic.PHP.NoSilencedErrors.Discouraged
@trigger_error( '' );
if ( @stream_select( $readyPipes, $emptyArray, $emptyArray, null ) === false ) {
+ // @codingStandardsIgnoreEnd
$error = error_get_last();
if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
continue;
$decimal = bcadd( $decimal, $baseChars[$char] );
}
+ // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
$result .= $baseChars[bcmod( $decimal, $destBase )];
}
+ // @codingStandardsIgnoreEnd
$result = strrev( $result );
} else {
* Checks if an IP is a trusted proxy provider.
* Useful to tell if X-Forwarded-For data is possibly bogus.
* Squid cache servers for the site are whitelisted.
+ * @deprecated Since 1.24, use IP::isTrustedProxy()
*
* @param string $ip
* @return bool
*/
function wfIsTrustedProxy( $ip ) {
- $trusted = wfIsConfiguredProxy( $ip );
- wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
- return $trusted;
+ return IP::isTrustedProxy( $ip );
}
/**
* Checks if an IP matches a proxy we've configured.
+ * @deprecated Since 1.24, use IP::isConfiguredProxy()
*
* @param string $ip
* @return bool
* @since 1.23 Supports CIDR ranges in $wgSquidServersNoPurge
*/
function wfIsConfiguredProxy( $ip ) {
- global $wgSquidServers, $wgSquidServersNoPurge;
-
- // quick check of known proxy servers
- $trusted = in_array( $ip, $wgSquidServers )
- || in_array( $ip, $wgSquidServersNoPurge );
-
- if ( !$trusted ) {
- // slightly slower check to see if the ip is listed directly or in a CIDR
- // block in $wgSquidServersNoPurge
- foreach ( $wgSquidServersNoPurge as $block ) {
- if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
- $trusted = true;
- break;
- }
- }
- }
- return $trusted;
+ return IP::isTrustedProxy( $ip );
}