Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/wp-admin/includes/class-pclzip.php
Original file line number Diff line number Diff line change
Expand Up @@ -3988,7 +3988,7 @@ function privExtractFileUsingTempFile(&$p_entry, &$p_options)


// ----- Write gz file format header
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, chr($p_entry['compression']), chr(0x00), time(), chr(0x00), chr(3));
@fwrite($v_dest_file, $v_binary_data, 10);

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
Expand Down Expand Up @@ -4616,10 +4616,10 @@ function privReadEndCentralDir(&$p_central_dir)
$v_byte = @fread($this->zip_fd, 1);

// ----- Add the byte
//$v_bytes = ($v_bytes << 8) | Ord($v_byte);
//$v_bytes = ($v_bytes << 8) | ord($v_byte);
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | ord($v_byte);

// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
Expand Down
11 changes: 8 additions & 3 deletions src/wp-includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1031,14 +1031,19 @@ function is_new_day() {
* This is a convenient function for easily building URL queries.
* It sets the separator to '&' and uses the _http_build_query() function.
*
* Unlike PHP's native http_build_query(), this function does NOT URL-encode
* the keys or values. Callers are responsible for encoding values beforehand
* with urlencode() or rawurlencode(), or late-escaping the output with
* esc_url() before use.
*
* @since 2.3.0
*
* @see _http_build_query() Used to build the query
* @see _http_build_query() Used to build the query.
* @link https://www.php.net/manual/en/function.http-build-query.php for more on what
* http_build_query() does.
*
* @param array $data URL-encode key/value pairs.
* @return string URL-encoded string.
* @param array $data Array of key/value pairs to build the query from.
* @return string Query string, without URL encoding applied.
*/
function build_query( $data ) {
return _http_build_query( $data, null, '&', '', false );
Expand Down
132 changes: 112 additions & 20 deletions src/wp-includes/html-api/class-wp-html-processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor {
*/
private $element_queue = array();

/**
* Whether the end-of-file token has been processed through the insertion modes.
*
* @since 7.1.0
*
* @var bool
*/
private $has_processed_eof = false;

/**
* Stores the current breadcrumbs.
*
Expand Down Expand Up @@ -399,7 +408,7 @@ public function __construct( $html, $use_the_static_create_methods_instead = nul

$this->state->stack_of_open_elements->set_push_handler(
function ( WP_HTML_Token $token ): void {
$is_virtual = ! isset( $this->state->current_token ) || $this->is_tag_closer();
$is_virtual = $this->is_eof_token() || ! isset( $this->state->current_token ) || $this->is_tag_closer();
$same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name;
$provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real';
$this->element_queue[] = new WP_HTML_Stack_Event( $token, WP_HTML_Stack_Event::PUSH, $provenance );
Expand All @@ -410,7 +419,7 @@ function ( WP_HTML_Token $token ): void {

$this->state->stack_of_open_elements->set_pop_handler(
function ( WP_HTML_Token $token ): void {
$is_virtual = ! isset( $this->state->current_token ) || ! $this->is_tag_closer();
$is_virtual = $this->is_eof_token() || ! isset( $this->state->current_token ) || ! $this->is_tag_closer();
$same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name;
$provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real';
$this->element_queue[] = new WP_HTML_Stack_Event( $token, WP_HTML_Stack_Event::POP, $provenance );
Expand Down Expand Up @@ -1036,20 +1045,31 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool {
}
}

// Finish stepping when there are no more tokens in the document.
// Process EOF once in the insertion modes before finishing.
$is_eof = false;
if (
WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT === $this->parser_state ||
WP_HTML_Tag_Processor::STATE_COMPLETE === $this->parser_state
) {
return false;
if ( self::PROCESS_NEXT_NODE === $node_to_process ) {
if ( $this->has_processed_eof || ! isset( $this->state->current_token ) ) {
return false;
}

$this->has_processed_eof = true;
} elseif ( ! isset( $this->state->current_token ) ) {
return false;
}

$is_eof = true;
}

$adjusted_current_node = $this->get_adjusted_current_node();
$is_closer = $this->is_tag_closer();
$is_start_tag = WP_HTML_Tag_Processor::STATE_MATCHED_TAG === $this->parser_state && ! $is_closer;
$token_name = $this->get_token_name();

if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) {
if ( self::REPROCESS_CURRENT_NODE !== $node_to_process && ! $is_eof ) {
try {
$bookmark_name = $this->bookmark_token();
} catch ( Exception $e ) {
Expand Down Expand Up @@ -1088,6 +1108,33 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool {
)
);

if ( $is_eof && ! $parse_in_current_insertion_mode ) {
if ( ! empty( $this->state->stack_of_template_insertion_modes ) ) {
return $this->step_in_template();
}

return false;
}

if ( $is_eof ) {
switch ( $this->state->insertion_mode ) {
case WP_HTML_Processor_State::INSERTION_MODE_BEFORE_HEAD:
case WP_HTML_Processor_State::INSERTION_MODE_IN_HEAD:
case WP_HTML_Processor_State::INSERTION_MODE_IN_HEAD_NOSCRIPT:
case WP_HTML_Processor_State::INSERTION_MODE_AFTER_HEAD:
case WP_HTML_Processor_State::INSERTION_MODE_IN_BODY:
case WP_HTML_Processor_State::INSERTION_MODE_IN_TEMPLATE:
break;

default:
if ( ! empty( $this->state->stack_of_template_insertion_modes ) ) {
return $this->step_in_template();
}

return false;
}
}

try {
if ( ! $parse_in_current_insertion_mode ) {
return $this->step_in_foreign_content();
Expand Down Expand Up @@ -3243,6 +3290,17 @@ private function step_in_body(): bool {
return $this->step();
}

/*
* > An end-of-file token
*/
if ( null === $token_name ) {
if ( ! empty( $this->state->stack_of_template_insertion_modes ) ) {
return $this->step_in_template();
}

return false;
}

if ( ! parent::is_tag_closer() ) {
/*
* > Any other start tag
Expand Down Expand Up @@ -4417,6 +4475,23 @@ private function step_in_template(): bool {
return $this->step( self::REPROCESS_CURRENT_NODE );
}

/*
* > An end-of-file token
*/
if ( null === $token_name ) {
if ( ! $this->state->stack_of_open_elements->contains( 'TEMPLATE' ) ) {
// Stop parsing.
return false;
}

// @todo Indicate a parse error once it's possible.
$this->state->stack_of_open_elements->pop_until( 'TEMPLATE' );
$this->state->active_formatting_elements->clear_up_to_last_marker();
array_pop( $this->state->stack_of_template_insertion_modes );
$this->reset_insertion_mode_appropriately();
return $this->step( self::REPROCESS_CURRENT_NODE );
}

/*
* > Any other start tag
*/
Expand All @@ -4435,20 +4510,7 @@ private function step_in_template(): bool {
return $this->step();
}

/*
* > An end-of-file token
*/
if ( ! $this->state->stack_of_open_elements->contains( 'TEMPLATE' ) ) {
// Stop parsing.
return false;
}

// @todo Indicate a parse error once it's possible.
$this->state->stack_of_open_elements->pop_until( 'TEMPLATE' );
$this->state->active_formatting_elements->clear_up_to_last_marker();
array_pop( $this->state->stack_of_template_insertion_modes );
$this->reset_insertion_mode_appropriately();
return $this->step( self::REPROCESS_CURRENT_NODE );
return false;
}

/**
Expand Down Expand Up @@ -5204,6 +5266,20 @@ private function step_in_foreign_content(): bool {
* Internal helpers
*/

/**
* Indicates if the Tag Processor has consumed all input.
*
* @since 7.1.0
*
* @return bool Whether the current token is the end-of-file token.
*/
private function is_eof_token(): bool {
return (
WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT === $this->parser_state ||
WP_HTML_Tag_Processor::STATE_COMPLETE === $this->parser_state
);
}

/**
* Creates a new bookmark for the currently-matched token and returns the generated name.
*
Expand Down Expand Up @@ -5680,6 +5756,7 @@ public function seek( $bookmark_name ): bool {
$this->state->current_token = null;
$this->current_element = null;
$this->element_queue = array();
$this->has_processed_eof = false;

/*
* The absence of a context node indicates a full parse.
Expand Down Expand Up @@ -6418,7 +6495,22 @@ private function insert_foreign_element( WP_HTML_Token $token, bool $only_add_to
*/
private function insert_virtual_node( $token_name, $bookmark_name = null ): WP_HTML_Token {
$here = $this->bookmarks[ $this->state->current_token->bookmark_name ];
$name = $bookmark_name ?? $this->bookmark_token();
if (
null === $bookmark_name &&
(
WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT === $this->parser_state ||
WP_HTML_Tag_Processor::STATE_COMPLETE === $this->parser_state
)
) {
if ( count( $this->bookmarks ) >= static::MAX_BOOKMARKS ) {
$this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS;
throw new Exception( 'could not allocate bookmark' );
}

$name = (string) ++$this->bookmark_counter;
} else {
$name = $bookmark_name ?? $this->bookmark_token();
}

$this->bookmarks[ $name ] = new WP_HTML_Span( $here->start, 0 );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1086,8 +1086,7 @@ private function data_wp_bind_processor( WP_Interactivity_API_Directives_Process
*/
private function data_wp_class_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ) {
if ( 'enter' === $mode ) {
$all_class_directives = $p->get_attribute_names_with_prefix( 'data-wp-class--' );
$entries = $this->get_directive_entries( $p, 'class' );
$entries = $this->get_directive_entries( $p, 'class' );
foreach ( $entries as $entry ) {
if ( empty( $entry['suffix'] ) ) {
continue;
Expand Down
Loading
Loading