is_html_response() ) { return $html; } $dry_run = (bool) Helper::get( 'dry_run', false ); $filtered = preg_replace_callback( '#]*)>(.*?)#is', function ( $match ) use ( $dry_run ) { return $this->process( $match, $dry_run ); }, $html ); // A backtrack limit or a catastrophic pattern returns null. Serving the // original page ungated is bad; serving an empty page is worse. return null === $filtered ? $html : $filtered; } /** * Decide what to do with one script element. * * @param array $match Regex match: 0 whole, 1 attributes, 2 contents. * @param bool $dry_run Report instead of rewrite. * @return string */ private function process( $match, $dry_run ) { $whole = $match[0]; $attrs = $match[1]; $code = $match[2]; $open = ''; } /** * Whether this script would run if left alone. * * @param string $attrs Raw attribute string. * @return bool */ private function is_executable( $attrs ) { $type = strtolower( trim( (string) $this->attribute( $attrs, 'type' ) ) ); return in_array( $type, self::$executable_types, true ); } /** * Pull one attribute's value out of a raw attribute string. * * @param string $attrs Raw attribute string. * @param string $name Attribute name. * @return string */ private function attribute( $attrs, $name ) { if ( preg_match( '/\s' . preg_quote( $name, '/' ) . '\s*=\s*("([^"]*)"|\'([^\']*)\'|([^\s>]+))/i', ' ' . $attrs, $found ) ) { foreach ( [ 2, 3, 4 ] as $group ) { if ( isset( $found[ $group ] ) && '' !== $found[ $group ] ) { return $found[ $group ]; } } } return ''; } /** * Only rewrite documents that are actually HTML. A plugin that hijacks the * request to return XML or a file download still passes through this * buffer, and must come out the other side untouched. * * @return bool */ private function is_html_response() { foreach ( headers_list() as $header ) { if ( 0 === stripos( $header, 'content-type:' ) ) { return (bool) stripos( $header, 'text/html' ); } } // No explicit header means PHP's default, which is text/html. return true; } }