custom-css.php 2.64 KB
Newer Older
ale's avatar
ale committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
/*
 * Plugin Name: A/I - Sanitize Custom CSS
 * Description: Sanitize Custom CSS by preventing url() references
 * Version: 0.0.1
 * Author: Autistici/Inventati
 * Author URI: https://autistici.org
 */

// The following code is heavily inspired by the Jetpack plugin custom-css module.
function ai_sanitize_css( $css, $args = array() ) {
    require_once(__DIR__ . '/csstidy/class.csstidy.php');

    $args = wp_parse_args(
        $args,
        array(
            'force'        => false,
        )
    );
	
    if ($args['force'] || !current_user_can('unfiltered_html')) {
        $warnings = array();
	
        safecss_class();
        $csstidy           = new csstidy();
        $csstidy->optimise = new safecss( $csstidy );

        $csstidy->set_cfg( 'remove_bslash', false );
        $csstidy->set_cfg( 'compress_colors', false );
        $csstidy->set_cfg( 'compress_font-weight', false );
        $csstidy->set_cfg( 'optimise_shorthands', 0 );
        $csstidy->set_cfg( 'remove_last_;', false );
        $csstidy->set_cfg( 'case_properties', false );
        $csstidy->set_cfg( 'discard_invalid_properties', true );
        $csstidy->set_cfg( 'css_level', 'CSS3.0' );
        $csstidy->set_cfg( 'preserve_css', true );
        $csstidy->set_cfg( 'template', __DIR__ . '/csstidy/wordpress-standard.tpl' );

        // Test for some preg_replace stuff.
        $prev = $css;
        $css  = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
        // prevent content: '\3434' from turning into '\\3434'.
        $css = str_replace( array( '\'\\\\', '"\\\\' ), array( '\'\\', '"\\' ), $css );
        if ( $css !== $prev ) {
            $warnings[] = 'preg_replace found stuff';
        }

        // Some people put weird stuff in their CSS, KSES tends to be greedy.
        $css = str_replace( '<=', '&lt;=', $css );

        // Test for some kses stuff.
        $prev = $css;
        // Why KSES instead of strip_tags?  Who knows?
        $css = wp_kses_split( $css, array(), array() );
        $css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
        // Why both KSES and strip_tags?  Because we just added some '>'.
        $css = strip_tags( $css ); // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- scared to update this to wp_strip_all_tags since we're building a CSS file here.

        if ( $css !== $prev ) {
            $warnings[] = 'kses found stuff';
        }

        $csstidy->parse( $css );
        $css = $csstidy->print->plain();
    }
    return $css;
}

add_filter('update_custom_css_data', function($args) {
    $css = $args['css'];
    $args['css'] = ai_sanitize_css($css);
    return $args;
}, 10, 2);