# MediaWiki install & usage
/cache
+/docs/coverage
/docs/js
/images/[0-9a-f]
/images/archive
$wgTidyConf, $wgTidyOpts, $wgTidyInternal, and $wgDebugTidy, all
deprecated since 1.26, have now all been removed. The $wgTidyConfig
setting remains only for Remex experimental features or debugging.
+* $wgEnableParserCache, deprecated since 1.26, was removed.
+ If disabling the parser cache is still desirable,
+ set `$wgParserCacheType = CACHE_NONE;` instead.
=== New features in 1.33 ===
* (T96041) __EXPECTUNUSEDCATEGORY__ on a category page causes the category
* The class WebInstallerOutput is now marked as @private.
* (T209699) The jquery.async module has been deprecated. JavaScript code that
needs asynchronous behaviour should use Promises.
+* Password::equals() is deprecated, use verify().
=== Other changes in 1.33 ===
* (T208871) The hard-coded Google search form on the database error page was
"wikimedia/testing-access-wrapper": "~1.0",
"wmde/hamcrest-html-matchers": "^0.1.0"
},
+ "replace": {
+ "symfony/polyfill-ctype": "1.99",
+ "symfony/polyfill-mbstring": "1.99"
+ },
"suggest": {
"ext-apcu": "Local data cache for greatly improved performance",
"ext-curl": "Improved http communication abilities",
+++ /dev/null
-This directory is for the auto-generated phpunit code coverage.
-Run 'make coverage' in the tests/phpunit subdirectory to build.
*/
$wgFileCacheDepth = 2;
-/**
- * Kept for extension compatibility; see $wgParserCacheType
- * @deprecated since 1.26
- */
-$wgEnableParserCache = true;
-
/**
* Append a configured value to the parser cache and the sitenotice key so
* that they can be kept separate for some class of activity.
$wgGitInfoCacheDirectory = "{$wgCacheDirectory}/gitinfo";
}
-if ( $wgEnableParserCache === false ) {
- $wgParserCacheType = CACHE_NONE;
-}
-
// Fix path to icon images after they were moved in 1.24
if ( $wgRightsIcon ) {
$wgRightsIcon = str_replace(
}
$pwhash = $this->getPassword( $row->user_password );
- if ( !$pwhash->equals( $req->password ) ) {
+ if ( !$pwhash->verify( $req->password ) ) {
if ( $this->config->get( 'LegacyEncoding' ) ) {
// Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
// Check for this with iconv
$cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $req->password );
- if ( $cp1252Password === $req->password || !$pwhash->equals( $cp1252Password ) ) {
+ if ( $cp1252Password === $req->password || !$pwhash->verify( $cp1252Password ) ) {
return $this->failResponse( $req );
}
} else {
}
$pwhash = $this->getPassword( $row->user_newpassword );
- if ( !$pwhash->equals( $req->password ) ) {
+ if ( !$pwhash->verify( $req->password ) ) {
return $this->failResponse( $req );
}
return false;
}
+ public function verify( $password ) {
+ return false;
+ }
+
public function needsUpdate() {
return false;
}
* @file
*/
+use Wikimedia\Assert\Assert;
+
/**
* Represents a password hash for use in authentication
*
* Password::toString() for each object. This can be overridden to do
* custom comparison, but it is not recommended unless necessary.
*
+ * @deprecated since 1.33, use verify()
+ *
* @param Password|string $other The other password
* @return bool True if equal, false otherwise
*/
public function equals( $other ) {
- if ( !$other instanceof self ) {
- // No need to use the factory because we're definitely making
- // an object of the same type.
- $obj = clone $this;
- $obj->crypt( $other );
- $other = $obj;
+ if ( is_string( $other ) ) {
+ return $this->verify( $other );
}
return hash_equals( $this->toString(), $other->toString() );
}
+ /**
+ * Checks whether the given password matches the hash stored in this object.
+ *
+ * @param string $password Password to check
+ * @return bool
+ */
+ public function verify( $password ) {
+ Assert::parameter( is_string( $password ),
+ '$password', 'must be string, actual: ' . gettype( $password )
+ );
+
+ // No need to use the factory because we're definitely making
+ // an object of the same type.
+ $obj = clone $this;
+ $obj->crypt( $password );
+
+ return hash_equals( $this->toString(), $obj->toString() );
+ }
+
/**
* Convert this hash to a string that can be stored in the database
*
"mark" => true,
];
+ /**
+ * For the purposes of this class, "metadata" elements are those that
+ * should neither trigger p-wrapping nor stop an outer p-wrapping,
+ * typically those that are themselves invisible in a browser's rendering.
+ * This isn't a complete list, it's just the tags that we're likely to
+ * encounter in practice.
+ * @var array
+ */
+ private static $metadataElements = [
+ 'style' => true,
+ 'script' => true,
+ 'link' => true,
+ 'meta' => true,
+ ];
+
private static $formattingElements = [
'a' => true,
'b' => true,
$under = $preposition === TreeBuilder::UNDER;
$elementToEnd = null;
- if ( $under && $parentData->isPWrapper && !$inline ) {
+ if ( isset( self::$metadataElements[$elementName] ) ) {
+ // The element is a metadata element, that we allow to appear in
+ // both inline and block contexts.
+ $this->trace( 'insert metadata' );
+ } elseif ( $under && $parentData->isPWrapper && !$inline ) {
// [B/b] The element is non-inline and the parent is a p-wrapper,
// close the parent and insert into its parent instead
$this->trace( 'insert B/b' );
return self::loginHook( $user, $bp,
Status::newFatal( 'botpasswords-needs-reset', $name, $appId ) );
}
- if ( !$passwordObj->equals( $password ) ) {
+ if ( !$passwordObj->verify( $password ) ) {
return self::loginHook( $user, $bp, Status::newFatal( 'wrongpassword' ) );
}
${PU} --tap
coverage:
- ${PU} --coverage-html ../../docs/code-coverage
+ ${PU} --coverage-html ../../docs/coverage
parser:
${PU} --group Parser
}
$passwordFactory = MediaWikiServices::getInstance()->getPasswordFactory();
- if ( !$passwordFactory->newFromCiphertext( $row->user_password )->equals( $password ) ) {
+ if ( !$passwordFactory->newFromCiphertext( $row->user_password )->verify( $password ) ) {
$passwordHash = $passwordFactory->newFromPlaintext( $password );
$dbw->update(
'user',
$totalPassword = $this->passwordFactory->newFromType( 'testLargeLayeredTop' );
$totalPassword->partialCrypt( $partialPassword );
- $this->assertTrue( $totalPassword->equals( 'testPassword123' ) );
+ $this->assertTrue( $totalPassword->verify( 'testPassword123' ) );
}
}
* @dataProvider providePasswordTests
*/
public function testHashing( $shouldMatch, $hash, $password ) {
- $hash = $this->passwordFactory->newFromCiphertext( $hash );
- $password = $this->passwordFactory->newFromPlaintext( $password, $hash );
- $this->assertSame( $shouldMatch, $hash->equals( $password ) );
+ $fromHash = $this->passwordFactory->newFromCiphertext( $hash );
+ $fromPassword = $this->passwordFactory->newFromPlaintext( $password, $fromHash );
+ $this->assertSame( $shouldMatch, $fromHash->equals( $fromPassword ) );
}
/**
$hashObj = $this->passwordFactory->newFromCiphertext( $hash );
$serialized = $hashObj->toString();
$unserialized = $this->passwordFactory->newFromCiphertext( $serialized );
- $this->assertTrue( $hashObj->equals( $unserialized ) );
+ $this->assertEquals( $hashObj->toString(), $unserialized->toString() );
}
/**
'<i><blockquote><p></i>',
'<i></i><blockquote><p><i></i></p><p><i></i></p></blockquote>',
],
+ [
+ 'style tag isn\'t p-wrapped (T186965)',
+ '<style>/* ... */</style>',
+ '<style>/* ... */</style>',
+ ],
+ [
+ 'link tag isn\'t p-wrapped (T186965)',
+ '<link rel="foo" href="bar" />',
+ '<link rel="foo" href="bar" />',
+ ],
+ [
+ 'style tag doesn\'t split p-wrapping (T208901)',
+ 'foo <style>/* ... */</style> bar',
+ '<p>foo <style>/* ... */</style> bar</p>',
+ ],
+ [
+ 'link tag doesn\'t split p-wrapping (T208901)',
+ 'foo <link rel="foo" href="bar" /> bar',
+ '<p>foo <link rel="foo" href="bar" /> bar</p>',
+ ],
];
public function provider() {