", and the Izini banner * runs them once that category is accepted (widget W4). This reaches scripts * from themes, plugins and pasted snippets alike, because it works on the * finished page. * * The finished page comes from WordPress's own template output buffer (6.9 * and later): the plugin adds a filter to it and opens no buffer of its own. * On older versions nothing is held back, and the Scripts tab says so. */ defined( 'ABSPATH' ) || exit; define( 'IZINI_RULES_OPTION', 'izini_script_rules' ); /** * The saved rules: each { kind: 'src'|'inline', match: string, category: string }. * * @return array */ function izini_script_rules() { $rules = get_option( IZINI_RULES_OPTION, array() ); if ( ! is_array( $rules ) ) { return array(); } return array_values( array_filter( $rules, function ( $r ) { return is_array( $r ) && isset( $r['kind'], $r['match'], $r['category'] ) && in_array( $r['kind'], array( 'src', 'inline' ), true ) && '' !== $r['match'] && izini_is_valid_category( $r['category'] ); } ) ); } /** Category ids are short and plain (e.g. analytics_storage). */ function izini_is_valid_category( $id ) { return is_string( $id ) && 1 === preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $id ); } /** * Code with each run of spaces, tabs and line breaks read as one space, as the * Scripts tab lists it: a script written over several lines still matches. */ function izini_flatten_code( $code ) { return trim( preg_replace( '/\s+/', ' ', $code ) ); } /** The rule a script tag falls under, or null. */ function izini_rule_for( $src, $body, $rules ) { $flat = '' === $src ? izini_flatten_code( $body ) : ''; foreach ( $rules as $rule ) { if ( 'src' === $rule['kind'] && '' !== $src && false !== stripos( $src, $rule['match'] ) ) { return $rule; } if ( 'inline' === $rule['kind'] && '' === $src && false !== strpos( $flat, izini_flatten_code( $rule['match'] ) ) ) { return $rule; } } return null; } /** * Rewrites the matching #is', $html, $all, PREG_SET_ORDER ) ) { foreach ( $all as $m ) { if ( preg_match( '/\bid\s*=\s*["\']izini-/i', $m[1] ) ) { continue; } if ( preg_match( '/\btype\s*=\s*(["\'])(.*?)\1/i', $m[1], $t ) && ! in_array( strtolower( trim( $t[2] ) ), array( 'text/javascript', 'application/javascript', 'module', 'text/plain' ), true ) ) { continue; } if ( preg_match( '/\bsrc\s*=\s*(["\'])(.*?)\1/i', $m[1], $s ) ) { $src = html_entity_decode( $s[2] ); $parts = wp_parse_url( $src ); $match = ( isset( $parts['host'] ) ? $parts['host'] : '' ) . ( isset( $parts['path'] ) ? $parts['path'] : '' ); // The admin bar's own scripts, which only signed-in users get. if ( '' === $match || isset( $seen[ 'src' . $match ] ) || preg_match( '#/wp-includes/js/(admin-bar|hoverintent-js)#', $match ) ) { continue; } $seen[ 'src' . $match ] = true; $scripts[] = array( 'kind' => 'src', 'label' => $match, 'match' => $match ); } else { $code = izini_flatten_code( $m[2] ); if ( '' === $code ) { continue; } $label = function_exists( 'mb_substr' ) ? mb_substr( $code, 0, 90 ) : substr( $code, 0, 90 ); $match = substr( $code, 0, 40 ); if ( isset( $seen[ 'inline' . $match ] ) ) { continue; } $seen[ 'inline' . $match ] = true; $scripts[] = array( 'kind' => 'inline', 'label' => $label, 'match' => $match ); } } } return $scripts; }