diff --git a/src/wp-includes/html-api/class-wp-html-open-elements.php b/src/wp-includes/html-api/class-wp-html-open-elements.php
index 1265e81513a00..f0b0fcb595f56 100644
--- a/src/wp-includes/html-api/class-wp-html-open-elements.php
+++ b/src/wp-includes/html-api/class-wp-html-open-elements.php
@@ -145,25 +145,45 @@ public function current_node() {
}
/**
- * Checks if the node at the top of the stack matches provided node name.
+ * Indicates if the current node is of a given type or name.
*
- * @example
- * // Is the current node a text node:
- * $stack->current_node_is( '#text' );
+ * It's possible to pass either a node type or a node name to this function.
+ * In the case there is no current element it will always return `false`.
*
- * // Is the current node a DIV element:
- * $stack->current_node_is( 'DIV' );
+ * Example:
+ *
+ * // Is the current node a text node?
+ * $stack->current_node_is( '#text' );
+ *
+ * // Is the current node a DIV element?
+ * $stack->current_node_is( 'DIV' );
+ *
+ * // Is the current node any element/tag?
+ * $stack->current_node_is( '#tag' );
+ *
+ * @see WP_HTML_Tag_Processor::get_token_type
+ * @see WP_HTML_Tag_Processor::get_token_name
*
* @since 6.7.0
*
- * @param string $node_name The node name to match. Provide a tag name for tags or a
- * token name for other types of tokens.
- * @return bool True if there are nodes on the stack and the top node has
- * a matching node_name.
+ * @access private
+ *
+ * @param string $identity Check if the current node has this name or type (depending on what is provided).
+ * @return bool Whether there is a current element that matches the given identity, whether a token name or type.
*/
- public function current_node_is( string $node_name ): bool {
+ public function current_node_is( string $identity ): bool {
$current_node = end( $this->stack );
- return $current_node && $current_node->node_name === $node_name;
+ if ( false === $current_node ) {
+ return false;
+ }
+
+ $current_node_name = $current_node->node_name;
+
+ return (
+ $current_node_name === $identity ||
+ ( '#doctype' === $identity && 'html' === $current_node_name ) ||
+ ( '#tag' === $identity && ctype_upper( $current_node_name ) )
+ );
}
/**
diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php
index 49634d8571f12..2c2baadd2ce26 100644
--- a/src/wp-includes/html-api/class-wp-html-processor.php
+++ b/src/wp-includes/html-api/class-wp-html-processor.php
@@ -1035,7 +1035,7 @@ private function step_in_body() {
}
$this->generate_implied_end_tags();
- if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) {
+ if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) {
// @todo Record parse error: this error doesn't impact parsing.
}
$this->state->stack_of_open_elements->pop_until( $token_name );
@@ -1100,7 +1100,7 @@ private function step_in_body() {
$this->generate_implied_end_tags();
- if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) {
+ if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) {
// @todo Record parse error: this error doesn't impact parsing.
}
@@ -1126,7 +1126,7 @@ private function step_in_body() {
if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) {
$node_name = $is_li ? 'LI' : $node->node_name;
$this->generate_implied_end_tags( $node_name );
- if ( $node_name !== $this->state->stack_of_open_elements->current_node()->node_name ) {
+ if ( ! $this->state->stack_of_open_elements->current_node_is( $node_name ) ) {
// @todo Indicate a parse error once it's possible. This error does not impact the logic here.
}
@@ -1203,7 +1203,7 @@ private function step_in_body() {
$this->generate_implied_end_tags( $token_name );
- if ( $token_name !== $this->state->stack_of_open_elements->current_node()->node_name ) {
+ if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) {
// @todo Indicate a parse error once it's possible. This error does not impact the logic here.
}
diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php
index 04a4ef8b55797..0e9e0d4579c19 100644
--- a/src/wp-includes/pluggable.php
+++ b/src/wp-includes/pluggable.php
@@ -2224,7 +2224,15 @@ function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' )
/* translators: %s: User login. */
$message = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
$message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
- $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . "\r\n\r\n";
+
+ /*
+ * Since some user login names end in a period, this could produce ambiguous URLs that
+ * end in a period. To avoid the ambiguity, ensure that the login is not the last query
+ * arg in the URL. If moving it to the end, a trailing period will need to be escaped.
+ *
+ * @see https://core.trac.wordpress.org/tickets/42957
+ */
+ $message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user->user_login ) . "&key=$key&action=rp", 'login' ) . "\r\n\r\n";
$message .= wp_login_url() . "\r\n";
diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php
index 38ff198286b3e..5a05fff2f4c73 100644
--- a/src/wp-includes/user.php
+++ b/src/wp-includes/user.php
@@ -3219,7 +3219,15 @@ function retrieve_password( $user_login = null ) {
$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
$message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n";
$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
- $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n";
+
+ /*
+ * Since some user login names end in a period, this could produce ambiguous URLs that
+ * end in a period. To avoid the ambiguity, ensure that the login is not the last query
+ * arg in the URL. If moving it to the end, a trailing period will need to be escaped.
+ *
+ * @see https://core.trac.wordpress.org/tickets/42957
+ */
+ $message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user_login ) . "&key=$key&action=rp", 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n";
if ( ! is_user_logged_in() ) {
$requester_ip = $_SERVER['REMOTE_ADDR'];
diff --git a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php
index 6b03aa3af1f42..b01ada9be28ff 100644
--- a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php
@@ -272,12 +272,12 @@ protected function check_get_revision_response( $response_revision_item, $revisi
// Global styles.
$config = ( new WP_Theme_JSON( json_decode( $revision_expected_item->post_content, true ), 'custom' ) )->get_raw_data();
- $this->assertEquals(
+ $this->assertSame(
$config['settings'],
$response_revision_item['settings'],
'Check that the revision settings exist in the response.'
);
- $this->assertEquals(
+ $this->assertSame(
$config['styles'],
$response_revision_item['styles'],
'Check that the revision styles match the updated styles.'
@@ -371,7 +371,7 @@ public function test_get_items_eligible_roles() {
$data = $response->get_data();
$this->assertCount( $this->total_revisions + 1, $data, 'Check that extra revision exist' );
- $this->assertEquals( self::$second_admin_id, $data[0]['author'], 'Check that second author id returns expected value.' );
+ $this->assertSame( self::$second_admin_id, $data[0]['author'], 'Check that second author id returns expected value.' );
}
/**