Skip to content

Commit dee7634

Browse files
authored
fix (blocksy): show blocksy theme styles in the design library (#3630)
* show blocksy theme styles in the design library * add mime checking, read local file * sanitize css * coderabbit's qa fix * sanitize styles from files * remove redundant code * move code
1 parent 1e56ba3 commit dee7634

File tree

5 files changed

+119
-6
lines changed

5 files changed

+119
-6
lines changed

src/compatibility/blocksy/index.php

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,108 @@ function stackable_blocksy_global_color_schemes_compatibility( $styles, $scheme,
8787
}
8888

8989
add_filter( 'stackable.global-settings.global-color-schemes.add-theme-compatibility', 'stackable_blocksy_global_color_schemes_compatibility', 10, 6 );
90-
}
90+
}
91+
92+
if ( ! function_exists( 'stackable_blocksy_theme_global_styles' ) ) {
93+
function stackable_sanitize_css_string( $css ) {
94+
if ( ! is_string( $css ) ) {
95+
return '';
96+
}
97+
98+
// sanitize css content
99+
$css = wp_strip_all_tags( $css );
100+
$css = preg_replace('/\bexpression\s*\([^)]*\)/i', '', $css);
101+
$css = preg_replace('/\bjavascript\s*:/i', '', $css);
102+
103+
// Only allow URLs from the theme directory
104+
$theme_uri = preg_quote( get_template_directory_uri(), '/' );
105+
$css = preg_replace_callback(
106+
'/url\(\s*[\'"]?\s*(https?:\/\/[^\'")]+)\s*[\'"]?\s*\)/i',
107+
function( $matches ) use ( $theme_uri ) {
108+
if ( preg_match( "/^{$theme_uri}/i", $matches[1] ) ) {
109+
return $matches[0]; // Keep theme URLs
110+
}
111+
return 'url("")'; // Remove others
112+
},
113+
$css
114+
);
115+
116+
// Block unsafe tokens
117+
$css = preg_replace('/\b(?:eval|mocha)\b(\s*:|\s*\()/i', '/* blocked */$1', $css);
118+
119+
// Block behavior and vendor-prefixed behavior
120+
$css = preg_replace('/(?<![a-zA-Z0-9-])(?:-+[a-zA-Z]*behavior|behavior)\b(\s*:|\s*\()/i', '/* blocked */$1', $css);
121+
122+
// Remove redundant semicolons
123+
$css = preg_replace('/;+/', ';', $css);
124+
125+
// Remove empty rule blocks (e.g. ".selector { }")
126+
$css = preg_replace('/[^{]+\{\s*\}/m', '', $css);
127+
128+
// Normalize spacing and line breaks
129+
$css = preg_replace('/\s+/', ' ', $css);
130+
$css = trim($css);
131+
132+
return $css;
133+
}
134+
135+
function stackable_blocksy_theme_global_styles( $styles ) {
136+
137+
if ( function_exists( 'blocksy_manager' ) ) {
138+
$blocksy_css = blocksy_manager()->dynamic_css->load_backend_dynamic_css([
139+
'echo' => false
140+
] );
141+
142+
$styles .= $blocksy_css;
143+
}
144+
145+
if ( class_exists( 'Blocksy_Static_Css_Files' ) ) {
146+
$blocksy_static_files = ( new Blocksy_Static_Css_Files() )->all_static_files();
147+
148+
$blocksy_static_files = array_filter(
149+
$blocksy_static_files,
150+
function( $file ) {
151+
return isset( $file['id'] ) && in_array( $file['id'], array( 'ct-main-styles', 'ct-stackable-styles' ), true );
152+
}
153+
);
154+
155+
$styles_from_files = '';
156+
foreach ( $blocksy_static_files as $file ) {
157+
if ( isset( $file['url'] ) ) {
158+
// Normalize and validate the path to prevent traversal
159+
$file_url = ltrim( $file['url'], '/' );
160+
$file_path = get_template_directory() . '/' . $file_url;
161+
$file_path = realpath( $file_path );
162+
$theme_dir = realpath( get_template_directory() );
163+
164+
// Ensure the resolved path is within the theme directory
165+
if ( ! $file_path || strpos( $file_path, $theme_dir ) !== 0 ) {
166+
continue;
167+
}
168+
169+
if ( file_exists( $file_path ) && is_readable( $file_path ) ) {
170+
$extension = strtolower( pathinfo( $file_path, PATHINFO_EXTENSION ) );
171+
if ( $extension !== 'css' ) {
172+
continue;
173+
}
174+
$content = file_get_contents( $file_path );
175+
if ( $content !== false ) {
176+
$styles_from_files .= $content;
177+
}
178+
179+
}
180+
}
181+
}
182+
183+
if ( $styles_from_files ) {
184+
// sanitize styles from files
185+
$styles_from_files = stackable_sanitize_css_string( $styles_from_files );
186+
$styles .= $styles_from_files;
187+
}
188+
}
189+
190+
return $styles;
191+
}
192+
193+
add_filter( 'stackable.design-library.global-theme-styles', 'stackable_blocksy_theme_global_styles' );
194+
}

src/compatibility/blocksy/style.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
:where(.stk--is-blocksy-theme.stk--has-default-container-scheme) {
44
--stk-default-link-color: var(--theme-link-initial-color);
55
--stk-default-heading-color: var(--theme-heading-color, var(--theme-headings-color));
6+
--stk-default-button-background-color: var(--theme-button-background-initial-color);
67

78
:where(.stk-block-heading) {
89
@for $i from 1 through 6 {

src/compatibility/index.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
require_once( plugin_dir_path( __FILE__ ) . './neve/index.php' );
99
require_once( plugin_dir_path( __FILE__ ) . './ewww.php' );
1010
require_once( plugin_dir_path( __FILE__ ) . './woocommerce.php' );
11+
require_once( plugin_dir_path( __FILE__ ) . './blocksy/index.php' );

src/design-library/init.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function __construct() {
3030
add_action( 'rest_api_init', array( $this, 'register_route' ) );
3131

3232
add_action( 'stackable_delete_design_library_cache', array( $this, 'delete_cache_v3' ) );
33+
34+
add_filter( 'stackable_localize_script', array( $this, 'add_wp_theme_global_styles' ) );
3335
}
3436

3537
public static function validate_string( $value, $request, $param ) {
@@ -299,6 +301,16 @@ public function get_design_library( $request ) {
299301
public static function get_cdn_url() {
300302
return trailingslashit( STACKABLE_DESIGN_LIBRARY_URL );
301303
}
304+
305+
public function add_wp_theme_global_styles( $args ) {
306+
$wp_global_styles = apply_filters( 'stackable.design-library.global-theme-styles', '' );
307+
308+
$wp_global_styles .= wp_get_global_stylesheet();
309+
310+
$args['wpGlobalStylesInlineCss'] = $wp_global_styles;
311+
312+
return $args;
313+
}
302314
}
303315

304316
new Stackable_Design_Library();

src/init.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,6 @@ public function register_block_editor_assets() {
334334

335335
$version_parts = explode( '-', STACKABLE_VERSION );
336336

337-
$wp_global_styles = wp_get_global_stylesheet();
338-
339337
global $content_width;
340338
global $wp_version;
341339
$args = apply_filters( 'stackable_localize_script', array(
@@ -373,9 +371,6 @@ public function register_block_editor_assets() {
373371
'settings' => apply_filters( 'stackable_js_settings', array() ),
374372
'isContentOnlyMode' => apply_filters( 'stackable_editor_role_is_content_only', false ),
375373
'blockCategoryIndex' => apply_filters( 'stackable_block_category_index', 0 ),
376-
377-
// Global Styles for Design Library
378-
'wpGlobalStylesInlineCss' => $wp_global_styles,
379374
) );
380375
wp_localize_script( 'wp-blocks', 'stackable', $args );
381376
}

0 commit comments

Comments
 (0)