diff options
author | Alexander Vorwerk <zabe@avorwerk.net> | 2022-09-19 17:51:15 +0200 |
---|---|---|
committer | Jforrester <jforrester@wikimedia.org> | 2022-09-29 14:40:13 +0000 |
commit | 872970a21ccdb7e9deb1f88311d9e58d6e87458b (patch) | |
tree | 4ddda58a354991ba4834ce890c5768debd3a48cd | |
parent | deaa06a21d866c23b622f76eea17d083e3799167 (diff) | |
download | mediawikicore-872970a21ccdb7e9deb1f88311d9e58d6e87458b.tar.gz mediawikicore-872970a21ccdb7e9deb1f88311d9e58d6e87458b.zip |
Drop some pre-7.4 php compat code
Change-Id: Ie92e4b2722692c64f38557bfcd3687168d245e8e
(cherry picked from commit eec198b245901d9a5dbe52a426e909ffbff32ac0)
-rw-r--r-- | includes/WebResponse.php | 5 | ||||
-rw-r--r-- | includes/language/Message.php | 23 | ||||
-rw-r--r-- | includes/libs/http/SetCookieCompat.php | 234 | ||||
-rw-r--r-- | tests/phpunit/unit/includes/libs/http/SetCookieCompatTest.php | 277 |
4 files changed, 3 insertions, 536 deletions
diff --git a/includes/WebResponse.php b/includes/WebResponse.php index c046c95122c8..67f4ca2ebf38 100644 --- a/includes/WebResponse.php +++ b/includes/WebResponse.php @@ -22,7 +22,6 @@ use MediaWiki\MainConfigNames; use MediaWiki\MediaWikiServices; -use Wikimedia\Http\SetCookieCompat; /** * Allow programs to request this object from WebRequest::response() @@ -242,9 +241,9 @@ class WebResponse { wfDebugLog( 'cookie', $logDesc ); if ( $func === 'setrawcookie' ) { - SetCookieCompat::setrawcookie( $prefixedName, $value, $setOptions ); + setrawcookie( $prefixedName, $value, $setOptions ); } else { - SetCookieCompat::setcookie( $prefixedName, $value, $setOptions ); + setcookie( $prefixedName, $value, $setOptions ); } self::$setCookies[$key] = $deleting ? null : $optionsForDeduplication; } diff --git a/includes/language/Message.php b/includes/language/Message.php index 3f599f78b337..88c08457d464 100644 --- a/includes/language/Message.php +++ b/includes/language/Message.php @@ -25,7 +25,6 @@ use MediaWiki\MediaWikiServices; use MediaWiki\Message\UserGroupMembershipParam; use MediaWiki\Page\PageReference; use MediaWiki\Page\PageReferenceValue; -use Wikimedia\RequestTimeout\TimeoutException; /** * The Message class deals with fetching and processing of interface message @@ -1029,27 +1028,7 @@ class Message implements MessageSpecifier, Serializable { * @return string */ public function __toString() { - // PHP before 7.4.0 doesn't allow __toString to throw exceptions and will - // trigger a fatal error if it does. So, catch any exceptions. - if ( version_compare( PHP_VERSION, '7.4.0', '<' ) ) { - try { - return $this->format( self::FORMAT_PARSE ); - } catch ( TimeoutException $e ) { - // Fatal is OK in this case - throw $e; - } catch ( Exception $ex ) { - try { - trigger_error( "Exception caught in " . __METHOD__ . " (message " . $this->key . "): " - . $ex, E_USER_WARNING ); - } catch ( Exception $ex ) { - // Doh! Cause a fatal error after all? - } - - return '⧼' . htmlspecialchars( $this->key ) . '⧽'; - } - } else { - return $this->format( self::FORMAT_PARSE ); - } + return $this->format( self::FORMAT_PARSE ); } /** diff --git a/includes/libs/http/SetCookieCompat.php b/includes/libs/http/SetCookieCompat.php deleted file mode 100644 index 4f5a3fc5e98e..000000000000 --- a/includes/libs/http/SetCookieCompat.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php - -namespace Wikimedia\Http; - -/** - * @internal - * @since 1.35 - */ -class SetCookieCompat { - /** - * Temporary emulation for setcookie() with a SameSite option and encoding - * spaces in values as "%20" rather than "+". - * - * Prior to PHP 7.4.3, setcookie() encoded spaces in cookie values as plus - * signs. PHP 7.4.2 and later no longer decode plus signs as spaces, which - * is a backward incompatible change that poses a problem when upgrading a - * live site, especially if not all servers are to be upgraded at once. - * - * Once MediaWiki requires PHP 7.4.3, this can be replaced with a setcookie() - * call in the caller. - * - * @see https://phabricator.wikimedia.org/T291127 - * @see https://bugs.php.net/bug.php?id=79174 - * @param string $name The full cookie name - * @param string $value The cookie value - * @param array $options The options as passed to setcookie() in PHP 7.3+ - * @return bool - */ - public static function setcookie( $name, $value, $options = [] ) { - return ( new self )->setCookieInternal( true, $name, $value, $options ); - } - - /** - * Temporary emulation for setrawcookie() with a SameSite option - * - * Once MediaWiki requires PHP 7.3, this can be replaced with a setrawcookie() - * call in the caller. - * - * @param string $name The full cookie name - * @param string $value The cookie value - * @param array $options The options as passed to setrawcookie() in PHP 7.3+ - * @return bool - */ - public static function setrawcookie( $name, $value, $options = [] ) { - return ( new self )->setCookieInternal( false, $name, $value, $options ); - } - - /** - * @internal - * @param bool $urlEncode True for setcookie(), false for setrawcookie() - * @param string $name The full cookie name - * @param string $value The cookie value - * @param array $options The options as passed to setcookie() in PHP 7.3+ - * @return bool - */ - public function setCookieInternal( $urlEncode, $name, $value, $options = [] ) { - $supportsAssoc = version_compare( PHP_VERSION, '7.3.0', '>=' ); - if ( $supportsAssoc ) { - if ( $urlEncode && version_compare( PHP_VERSION, '7.4.3', '>=' ) ) { - return setcookie( $name, $value, $options ); - } elseif ( $urlEncode ) { - return setrawcookie( $name, rawurlencode( $value ), $options ); - } else { - return setrawcookie( $name, $value, $options ); - } - } - - if ( !isset( $options['samesite'] ) || !strlen( $options['samesite'] ) ) { - return setrawcookie( - $name, - $urlEncode ? rawurlencode( $value ) : $value, - $options['expires'], - $options['path'], - $options['domain'], - $options['secure'], - $options['httponly'] - ); - } - - return self::setCookieEmulated( $urlEncode, $name, $value, $options ); - } - - /** - * Temporary emulation for setcookie() or setrawcookie() to match PHP 7.4.3 - * - * This function corresponds to php_head_parse_cookie_options_array() and - * php_setcookie() in the PHP source code: - * - * https://github.com/php/php-src/blob/PHP-7.4.3/ext/standard/head.c#L189-L226 - * https://github.com/php/php-src/blob/PHP-7.4.3/ext/standard/head.c#L79-L187 - * - * @internal - * @param bool $urlEncode True for setcookie(), false for setrawcookie() - * @param string $name The full cookie name - * @param string|null $value The cookie value - * @param array $options The options as passed to setcookie() in PHP 7.3+ - * @return bool - */ - public function setCookieEmulated( $urlEncode, $name, $value, $options = [] ) { - $func = $urlEncode ? 'setcookie()' : 'setrawcookie()'; - $expires = 0; - $path = null; - $domain = null; - $secure = false; - $httponly = false; - $samesite = null; - $found = 0; - foreach ( $options as $key => $opt ) { - if ( $key === 'expires' ) { - $expires = (int)$opt; - $found++; - } elseif ( $key === 'path' ) { - $path = (string)$opt; - $found++; - } elseif ( $key === 'domain' ) { - $domain = (string)$opt; - $found++; - } elseif ( $key === 'secure' ) { - $secure = (bool)$opt; - $found++; - } elseif ( $key === 'httponly' ) { - $httponly = (bool)$opt; - $found++; - } elseif ( $key === 'samesite' ) { - $samesite = (string)$opt; - $found++; - } else { - $this->error( "$func: Unrecognized key '$key' found in the options array" ); - } - } - - if ( $found == 0 && count( $options ) > 0 ) { - $this->error( "$func: No valid options were found in the given array" ); - } - - if ( !strlen( $name ) ) { - $this->error( 'Cookie names must not be empty' ); - return false; - } elseif ( strpbrk( $name, "=,; \t\r\n\013\014" ) !== false ) { - $this->error( "Cookie names cannot contain any of the following " . - "'=,; \\t\\r\\n\\013\\014'" ); - return false; - } - - if ( !$urlEncode && $value !== null - && strpbrk( $value, ",; \t\r\n\013\014" ) !== false - ) { - $this->error( "Cookie values cannot contain any of the following ',; \\t\\r\\n\\013\\014'" ); - return false; - } - - if ( $path !== null && strpbrk( $path, ",; \t\r\n\013\014" ) !== false ) { - $this->error( "Cookie paths cannot contain any of the following ',; \\t\\r\\n\\013\\014'" ); - return false; - } - - if ( $domain !== null && strpbrk( $domain, ",; \t\r\n\013\014" ) !== false ) { - $this->error( "Cookie domains cannot contain any of the following ',; \\t\\r\\n\\013\\014'" ); - return false; - } - - $buf = ''; - if ( $value === null || strlen( $value ) === 0 ) { - $dt = gmdate( "D, d-M-Y H:i:s T", 1 ); - $buf .= "Set-Cookie: $name=deleted; expires=$dt; Max-Age=0"; - } else { - $buf .= "Set-Cookie: $name="; - if ( $urlEncode ) { - $buf .= rawurlencode( $value ); - } else { - $buf .= $value; - } - - if ( $expires > 0 ) { - $dt = gmdate( "D, d-M-Y H:i:s T", $expires ); - $p = strrpos( $dt, '-' ); - if ( $p === false || substr( $dt, $p + 5, 1 ) !== ' ' ) { - $this->error( "Expiry date cannot have a year greater than 9999" ); - return false; - } - - $buf .= "; expires=$dt"; - - $diff = $expires - $this->time(); - if ( $diff < 0 ) { - $diff = 0; - } - $buf .= "; Max-Age=$diff"; - } - } - - if ( $path !== null && strlen( $path ) ) { - $buf .= "; path=$path"; - } - if ( $domain !== null && strlen( $domain ) ) { - $buf .= "; domain=$domain"; - } - if ( $secure ) { - $buf .= "; secure"; - } - if ( $httponly ) { - $buf .= "; HttpOnly"; - } - if ( $samesite !== null && strlen( $samesite ) ) { - $buf .= "; SameSite=$samesite"; - } - - // sapi_header_op() returns a value which setcookie() uses, but - // header() discards it. The most likely way for sapi_header_op() to - // fail is due to headers already being sent. - if ( $this->headers_sent() ) { - $this->error( "Cannot modify header information - headers already sent" ); - return false; - } - $this->header( $buf ); - return true; - } - - protected function time() { - return time(); - } - - protected function error( $message ) { - trigger_error( $message, E_USER_WARNING ); - } - - protected function headers_sent() { - return headers_sent(); - } - - protected function header( $header ) { - header( $header, false ); - } -} diff --git a/tests/phpunit/unit/includes/libs/http/SetCookieCompatTest.php b/tests/phpunit/unit/includes/libs/http/SetCookieCompatTest.php deleted file mode 100644 index 90d98a18feba..000000000000 --- a/tests/phpunit/unit/includes/libs/http/SetCookieCompatTest.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php - -use PHPUnit\Framework\TestCase; -use Wikimedia\Http\SetCookieCompat; - -/** - * @covers \Wikimedia\Http\SetCookieCompat - */ -class SetCookieCompatTest extends TestCase { - use MediaWikiCoversValidator; - - public static function provideSetCookieEmulated() { - // Expected values are all copied from PHP 7.4 - return [ - 'unrecognised key' => [ - true, 'a', '', - [ - 'path' => '/', - 'foo' => 'bar' - ], - [ - 'headers' => [ - 'Set-Cookie: a=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/', - ], - 'returnValue' => true, - 'errors' => [ - 'setcookie(): Unrecognized key \'foo\' found in the options array', - ], - ], - ], - 'no valid options' => [ - true, 'a', '', - [ - 'foo' => 'bar' - ], - [ - 'headers' => [ - 'Set-Cookie: a=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0', - ], - 'returnValue' => true, - 'errors' => [ - 'setcookie(): Unrecognized key \'foo\' found in the options array', - 'setcookie(): No valid options were found in the given array', - ], - ] - ], - 'empty name' => [ - true, '', '', [], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Cookie names must not be empty', - ], - ], - ], - 'invalid name' => [ - true, "\n", '', [], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Cookie names cannot contain any of the following \'=,; \\t\\r\\n\\013\\014\'', - ], - ] - ], - 'invalid value' => [ - false, 'a', "\n", [], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Cookie values cannot contain any of the following \',; \\t\\r\\n\\013\\014\'', - ], - ] - ], - 'escaped invalid value' => [ - true, 'a', "\n", [], - [ - 'headers' => [ - 'Set-Cookie: a=%0A', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'invalid path' => [ - true, 'a', 'b', [ 'path' => "\n" ], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Cookie paths cannot contain any of the following \',; \\t\\r\\n\\013\\014\'', - ], - ] - ], - 'invalid domain' => [ - true, 'a', 'b', [ 'domain' => "\013" ], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Cookie domains cannot contain any of the following \',; \\t\\r\\n\\013\\014\'', - ], - ] - ], - 'empty value' => [ - true, 'a', '', [], - [ - 'headers' => [ - 'Set-Cookie: a=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'encoded value' => [ - true, 'a', '%', [], - [ - 'headers' => [ - 'Set-Cookie: a=%25', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'encoded value with space' => [ - true, 'a', 'b c', [], - [ - 'headers' => [ - 'Set-Cookie: a=b%20c', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'raw value' => [ - false, 'a', '%', [], - [ - 'headers' => [ - 'Set-Cookie: a=%', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'expires too large' => [ - true, 'a', 'b', [ 'expires' => 253430725200 ], - [ - 'headers' => [], - 'returnValue' => false, - 'errors' => [ - 'Expiry date cannot have a year greater than 9999', - ], - ] - ], - 'expires in the past' => [ - true, 'a', 'b', [ 'expires' => 979477200 ], - [ - 'headers' => [ - 'Set-Cookie: a=b; expires=Sun, 14-Jan-2001 13:00:00 GMT; Max-Age=0', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'expires in the future' => [ - true, 'a', 'b', [ 'expires' => 32504889600 ], - [ - 'headers' => [ - 'Set-Cookie: a=b; expires=Wed, 15-Jan-3000 00:00:00 GMT; Max-Age=30911234470', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'path' => [ - false, 'a', 'b', [ 'path' => '%%' ], - [ - 'headers' => [ - 'Set-Cookie: a=b; path=%%', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'domain' => [ - false, 'a', 'b', [ 'domain' => '%%' ], - [ - 'headers' => [ - 'Set-Cookie: a=b; domain=%%', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'secure' => [ - false, 'a', 'b', [ 'secure' => true ], - [ - 'headers' => [ - 'Set-Cookie: a=b; secure', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'httponly' => [ - false, 'a', 'b', [ 'httponly' => true ], - [ - 'headers' => [ - 'Set-Cookie: a=b; HttpOnly', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'samesite' => [ - false, 'a', 'b', [ 'samesite' => 'None' ], - [ - 'headers' => [ - 'Set-Cookie: a=b; SameSite=None', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - 'multiple options' => [ - false, 'a', 'b', [ - 'expires' => 32504889600, - 'path' => '/%', - 'domain' => '%.com', - 'secure' => true, - 'httponly' => true - ], - [ - 'headers' => [ - 'Set-Cookie: a=b; expires=Wed, 15-Jan-3000 00:00:00 GMT; Max-Age=30911234470; path=/%; domain=%.com; secure; HttpOnly', - ], - 'returnValue' => true, - 'errors' => [], - ] - ], - - ]; - } - - /** - * @dataProvider provideSetCookieEmulated - */ - public function testSetCookieEmulated( $urlEncode, $name, $value, $options, $expected ) { - $instance = new class extends SetCookieCompat { - public $headers = []; - public $errors = []; - - protected function time() { - return 1593655130; - } - - protected function error( $error ) { - $this->errors[] = $error; - } - - protected function headers_sent() { - return false; - } - - protected function header( $header ) { - $this->headers[] = $header; - } - }; - - $ret = $instance->setCookieEmulated( $urlEncode, $name, $value, $options ); - $this->assertSame( $expected['headers'], $instance->headers ); - $this->assertSame( $expected['errors'], $instance->errors ); - $this->assertSame( $expected['returnValue'], $ret ); - } -} |