From a508f5daeee0f93f00cb262a8ba519a2af0870a5 Mon Sep 17 00:00:00 2001 From: Kevin Israel Date: Fri, 12 Feb 2016 18:49:01 -0500 Subject: [PATCH] FormatJson: Remove PHP 5.3 compatibility code MediaWiki now only works with PHP versions that are new enough to have the encoding options required by encode54(). So fold that into encode() and remove encode53() and prettyPrint(). Change-Id: I6b22daf8fa01ef608efbde9c6aecdbb5ce03e2b9 --- includes/json/FormatJson.php | 176 ++++++++--------------------------- 1 file changed, 38 insertions(+), 138 deletions(-) diff --git a/includes/json/FormatJson.php b/includes/json/FormatJson.php index f85ee920da..285f1ec31d 100644 --- a/includes/json/FormatJson.php +++ b/includes/json/FormatJson.php @@ -129,11 +129,46 @@ class FormatJson { $pretty = $pretty ? ' ' : false; } - if ( defined( 'JSON_UNESCAPED_UNICODE' ) ) { - return self::encode54( $value, $pretty, $escaping ); + static $bug66021; + if ( $pretty !== false && $bug66021 === null ) { + $bug66021 = json_encode( array(), JSON_PRETTY_PRINT ) !== '[]'; + } + + // PHP escapes '/' to prevent breaking out of inline script blocks using '', + // which is hardly useful when '<' and '>' are escaped (and inadequate), and such + // escaping negatively impacts the human readability of URLs and similar strings. + $options = JSON_UNESCAPED_SLASHES; + $options |= $pretty !== false ? JSON_PRETTY_PRINT : 0; + $options |= ( $escaping & self::UTF8_OK ) ? JSON_UNESCAPED_UNICODE : 0; + $options |= ( $escaping & self::XMLMETA_OK ) ? 0 : ( JSON_HEX_TAG | JSON_HEX_AMP ); + $json = json_encode( $value, $options ); + if ( $json === false ) { + return false; + } + + if ( $pretty !== false ) { + // Workaround for + if ( $bug66021 ) { + $json = preg_replace( self::WS_CLEANUP_REGEX, '', $json ); + } + if ( $pretty !== ' ' ) { + // Change the four-space indent to a tab indent + $json = str_replace( "\n ", "\n\t", $json ); + while ( strpos( $json, "\t " ) !== false ) { + $json = str_replace( "\t ", "\t\t", $json ); + } + + if ( $pretty !== "\t" ) { + // Change the tab indent to the provided indent + $json = str_replace( "\t", $pretty, $json ); + } + } + } + if ( $escaping & self::UTF8_OK ) { + $json = str_replace( self::$badChars, self::$badCharsEscaped, $json ); } - return self::encode53( $value, $pretty, $escaping ); + return $json; } /** @@ -226,141 +261,6 @@ class FormatJson { return Status::newFatal( $msg ); } - /** - * JSON encoder wrapper for PHP >= 5.4, which supports useful encoding options. - * - * @param mixed $value - * @param string|bool $pretty - * @param int $escaping - * @return string|false - */ - private static function encode54( $value, $pretty, $escaping ) { - static $bug66021; - if ( $pretty !== false && $bug66021 === null ) { - $bug66021 = json_encode( array(), JSON_PRETTY_PRINT ) !== '[]'; - } - - // PHP escapes '/' to prevent breaking out of inline script blocks using '', - // which is hardly useful when '<' and '>' are escaped (and inadequate), and such - // escaping negatively impacts the human readability of URLs and similar strings. - $options = JSON_UNESCAPED_SLASHES; - $options |= $pretty !== false ? JSON_PRETTY_PRINT : 0; - $options |= ( $escaping & self::UTF8_OK ) ? JSON_UNESCAPED_UNICODE : 0; - $options |= ( $escaping & self::XMLMETA_OK ) ? 0 : ( JSON_HEX_TAG | JSON_HEX_AMP ); - $json = json_encode( $value, $options ); - if ( $json === false ) { - return false; - } - - if ( $pretty !== false ) { - // Workaround for - if ( $bug66021 ) { - $json = preg_replace( self::WS_CLEANUP_REGEX, '', $json ); - } - if ( $pretty !== ' ' ) { - // Change the four-space indent to a tab indent - $json = str_replace( "\n ", "\n\t", $json ); - while ( strpos( $json, "\t " ) !== false ) { - $json = str_replace( "\t ", "\t\t", $json ); - } - - if ( $pretty !== "\t" ) { - // Change the tab indent to the provided indent - $json = str_replace( "\t", $pretty, $json ); - } - } - } - if ( $escaping & self::UTF8_OK ) { - $json = str_replace( self::$badChars, self::$badCharsEscaped, $json ); - } - - return $json; - } - - /** - * JSON encoder wrapper for PHP 5.3, which lacks native support for some encoding options. - * Therefore, the missing options are implemented here purely in PHP code. - * - * @param mixed $value - * @param string|bool $pretty - * @param int $escaping - * @return string|false - */ - private static function encode53( $value, $pretty, $escaping ) { - $options = ( $escaping & self::XMLMETA_OK ) ? 0 : ( JSON_HEX_TAG | JSON_HEX_AMP ); - $json = json_encode( $value, $options ); - if ( $json === false ) { - return false; - } - - // Emulate JSON_UNESCAPED_SLASHES. Because the JSON contains no unescaped slashes - // (only escaped slashes), a simple string replacement works fine. - $json = str_replace( '\/', '/', $json ); - - if ( $escaping & self::UTF8_OK ) { - // JSON hex escape sequences follow the format \uDDDD, where DDDD is four hex digits - // indicating the equivalent UTF-16 code unit's value. To most efficiently unescape - // them, we exploit the JSON extension's built-in decoder. - // * We escape the input a second time, so any such sequence becomes \\uDDDD. - // * To avoid interpreting escape sequences that were in the original input, - // each double-escaped backslash (\\\\) is replaced with \\\u005c. - // * We strip one of the backslashes from each of the escape sequences to unescape. - // * Then the JSON decoder can perform the actual unescaping. - $json = str_replace( "\\\\\\\\", "\\\\\\u005c", addcslashes( $json, '\"' ) ); - $json = json_decode( preg_replace( "/\\\\\\\\u(?!00[0-7])/", "\\\\u", "\"$json\"" ) ); - $json = str_replace( self::$badChars, self::$badCharsEscaped, $json ); - } - - if ( $pretty !== false ) { - return self::prettyPrint( $json, $pretty ); - } - - return $json; - } - - /** - * Adds non-significant whitespace to an existing JSON representation of an object. - * Only needed for PHP < 5.4, which lacks the JSON_PRETTY_PRINT option. - * - * @param string $json - * @param string $indentString - * @return string - */ - private static function prettyPrint( $json, $indentString ) { - $buf = ''; - $indent = 0; - $json = strtr( $json, array( '\\\\' => '\\\\', '\"' => "\x01" ) ); - for ( $i = 0, $n = strlen( $json ); $i < $n; $i += $skip ) { - $skip = 1; - switch ( $json[$i] ) { - case ':': - $buf .= ': '; - break; - case '[': - case '{': - ++$indent; - // falls through - case ',': - $buf .= $json[$i] . "\n" . str_repeat( $indentString, $indent ); - break; - case ']': - case '}': - $buf .= "\n" . str_repeat( $indentString, --$indent ) . $json[$i]; - break; - case '"': - $skip = strcspn( $json, '"', $i + 1 ) + 2; - $buf .= substr( $json, $i, $skip ); - break; - default: - $skip = strcspn( $json, ',]}"', $i + 1 ) + 1; - $buf .= substr( $json, $i, $skip ); - } - } - $buf = preg_replace( self::WS_CLEANUP_REGEX, '', $buf ); - - return str_replace( "\x01", '\"', $buf ); - } - /** * Remove multiline and single line comments from an otherwise valid JSON * input string. This can be used as a preprocessor for to allow JSON -- 2.20.1