PluginProbe
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts / trunk
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts vtrunk
2.7.7 2.7.6 2.7.5 2.7.4 trunk 1.3 2.0.4 2.0.6 2.1.91 2.2.4 2.2.7 2.2.9 2.3.1 2.3.10 2.4.10 2.4.2 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.6.0 2.6.1 2.7.0 All 28 releases
← All changes | includes/shortcodes/shortcodes.php +243 -156 2.4.10trunk View file →
@@ -1,156 +1,243 @@
1 -<?php
2 -/**
3 - * A base shortcode for all lockers
4 - *
5 - * @since 1.0.0
6 - */
7 -
8 -// Exit if accessed directly
9 -if ( ! defined( 'ABSPATH' ) ) {
10 - exit;
11 -}
12 -
13 -class WINP_SnippetShortcode extends Wbcr_FactoryShortcodes333_Shortcode {
14 -
15 - public $shortcode_name = 'wbcr_php_snippet';
16 -
17 - /**
18 - * Includes assets
19 - * @var bool
20 - */
21 - public $assets_in_header = true;
22 -
23 - /**
24 - * Filter attributes
25 - *
26 - * @param $attr
27 - * @param $post_id
28 - *
29 - * @return mixed
30 - */
31 - public function filterAttributes( $attr, $post_id ) {
32 - if ( ! empty( $attr ) ) {
33 - $available_tags = WINP_Helper::getMetaOption( $post_id, 'snippet_tags', null );
34 -
35 - if ( ! empty( $available_tags ) ) {
36 - $available_tags = explode( ',', $available_tags );
37 - $available_tags = array_map( 'trim', $available_tags );
38 - }
39 -
40 - foreach ( $attr as $name => $value ) {
41 - $is_allow_attr = in_array( $name, array( 'id', 'title' ) );
42 - $validate_name = preg_match( '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $name );
43 -
44 - if ( ! $is_allow_attr && ( ( ! empty( $available_tags ) && ! in_array( $name, $available_tags ) ) || ! $validate_name ) ) {
45 - unset( $attr[ $name ] );
46 - } else {
47 - // issue PCS-1
48 - // before sending the value to the shortcode, using encodeURIComponent(val).replace(/\./g, ‘%2E’); fixes the issue. Will the next update stop this from working?
49 - $value = urldecode( $value );
50 -
51 - // Remove script tag
52 - $value = preg_replace( '#<script(.*?)>(.*?)</script>#is', '', $value );
53 -
54 - // Remove any attribute starting with "on" or xmlns
55 - $value = preg_replace( '#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $value );
56 -
57 - // Remove javascript: and vbscript: protocols
58 - $value = preg_replace( '#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $value );
59 - $value = preg_replace( '#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $value );
60 - $value = preg_replace( '#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $value );
61 -
62 - // Filter value
63 - if ( version_compare( phpversion(), '7.3.0', '>=' ) ) {
64 - $filter = FILTER_SANITIZE_ADD_SLASHES;
65 - } else {
66 - $filter = FILTER_SANITIZE_MAGIC_QUOTES;
67 - }
68 - $value = filter_var( $value, FILTER_SANITIZE_SPECIAL_CHARS );
69 - $attr[ $name ] = filter_var( $value, $filter );
70 - }
71 - }
72 - }
73 -
74 - return $attr;
75 - }
76 -
77 - /**
78 - * Get snippet id
79 - *
80 - * @param $attr
81 - * @param $type
82 - *
83 - * @return int|null
84 - */
85 - public function getSnippetId( $attr, $type ) {
86 - $id = isset( $attr['id'] ) ? (int) $attr['id'] : null;
87 - if ( $id && $type != WINP_Helper::get_snippet_type( $id ) ) {
88 - $id = 0;
89 - }
90 -
91 - return $id;
92 - }
93 -
94 - /**
95 - * Get snippet activate
96 - *
97 - * @param $snippet_meta
98 - *
99 - * @return bool
100 - */
101 - public function getSnippetActivate( $snippet_meta ) {
102 - // WPML Compatibility
103 - if ( defined( 'WPML_PLUGIN_FILE' ) ) {
104 - $wpml_langs = isset( $snippet_meta[ $this->plugin->getPrefix() . 'snippet_wpml_lang' ][0] ) ? $snippet_meta[ $this->plugin->getPrefix() . 'snippet_wpml_lang' ][0] : '';
105 - if ( $wpml_langs !== '' && defined( 'ICL_LANGUAGE_CODE' ) ) {
106 - if ( ! in_array( ICL_LANGUAGE_CODE, explode( ',', $wpml_langs ) ) ) {
107 - return false;
108 - }
109 - }
110 - }
111 -
112 - return isset( $snippet_meta[ $this->plugin->getPrefix() . 'snippet_activate' ] ) && $snippet_meta[ $this->plugin->getPrefix() . 'snippet_activate' ][0];
113 - }
114 -
115 - /**
116 - * Get snippet scope
117 - *
118 - * @param $snippet_meta
119 - *
120 - * @return null
121 - */
122 - public function getSnippetScope( $snippet_meta ) {
123 - return isset( $snippet_meta[ $this->plugin->getPrefix() . 'snippet_scope' ] ) ? $snippet_meta[ $this->plugin->getPrefix() . 'snippet_scope' ][0] : null;
124 - }
125 -
126 - /**
127 - * Get snippet content
128 - *
129 - * @param WP_Post $snippet
130 - * @param array $snippet_meta
131 - * @param int $id
132 - *
133 - * @return null|string
134 - */
135 - public function getSnippetContent( $snippet, $snippet_meta, $id ) {
136 - $snippet_code = WINP_Helper::get_snippet_code( $snippet );
137 -
138 - if ( WINP_Plugin::app()->getOption( 'execute_shortcode' ) ) {
139 - $snippet_code = do_shortcode( $snippet_code );
140 - }
141 -
142 - return WINP_Plugin::app()->getExecuteObject()->prepareCode( $snippet_code, $id );
143 - }
144 -
145 - /**
146 - * Content render
147 - *
148 - * @param array $attr
149 - * @param string $content
150 - * @param string $tag
151 - */
152 - public function html( $attr, $content, $tag ) {
153 -
154 - }
155 -
156 -}
1 +<?php
2 +/**
3 + * A base shortcode for all snippets
4 + *
5 + * @since 1.0.0
6 + */
7 +
8 +// Exit if accessed directly
9 +if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 +}
12 +
13 +/**
14 + * Base shortcode class for all snippet shortcodes
15 + */
16 +class WINP_SnippetShortcode {
17 +
18 + /**
19 + * Plugin instance
20 + *
21 + * @var WINP_Plugin
22 + */
23 + public $plugin;
24 +
25 + /**
26 + * Shortcode name(s)
27 + *
28 + * @var string|array<string>
29 + */
30 + public $shortcode_name = 'wbcr_php_snippet';
31 +
32 + /**
33 + * Includes assets in header
34 + *
35 + * @var bool
36 + */
37 + public $assets_in_header = true;
38 +
39 + /**
40 + * Constructor
41 + *
42 + * @param WINP_Plugin $plugin Plugin instance.
43 + */
44 + public function __construct( $plugin ) {
45 + $this->plugin = $plugin;
46 +
47 + // Ensure shortcode_name is an array.
48 + if ( ! is_array( $this->shortcode_name ) ) {
49 + $this->shortcode_name = [ $this->shortcode_name ];
50 + }
51 +
52 + // Register shortcode(s) with WordPress.
53 + foreach ( $this->shortcode_name as $name ) {
54 + if ( ! empty( $name ) ) {
55 + add_shortcode( $name, [ $this, 'render' ] );
56 + }
57 + }
58 +
59 + // Enqueue assets in header if needed.
60 + if ( $this->assets_in_header ) {
61 + add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] );
62 + }
63 + }
64 +
65 + /**
66 + * Enqueue assets if needed.
67 + *
68 + * @return void
69 + */
70 + public function enqueue_assets() {
71 + // Override in child classes if needed.
72 + }
73 +
74 + /**
75 + * Shortcode render callback.
76 + *
77 + * @param array<string, mixed> $attr Shortcode attributes.
78 + * @param string|null $content Shortcode content.
79 + * @param string $tag Shortcode tag.
80 + *
81 + * @return string
82 + */
83 + public function render( $attr, $content, $tag ) {
84 + if ( WINP_Helper::is_safe_mode() ) {
85 + return '';
86 + }
87 +
88 + ob_start();
89 + $result = $this->html( $attr, $content ?? '', $tag );
90 + $html = ob_get_clean();
91 +
92 + if ( is_string( $result ) ) {
93 + $html = ( false !== $html ? $html : '' ) . $result;
94 + }
95 +
96 + return false !== $html ? $html : '';
97 + }
98 +
99 + /**
100 + * Filter attributes
101 + *
102 + * @param array<string, mixed> $attr Shortcode attributes.
103 + * @param int $post_id Post ID.
104 + *
105 + * @return array<string, mixed>
106 + */
107 + public function filter_attributes( $attr, $post_id ) {
108 + if ( ! empty( $attr ) ) {
109 + $available_tags = WINP_Helper::getMetaOption( $post_id, 'snippet_tags', null );
110 +
111 + if ( ! empty( $available_tags ) ) {
112 + $available_tags = explode( ',', $available_tags );
113 + $available_tags = array_map( 'trim', $available_tags );
114 + }
115 +
116 + foreach ( $attr as $name => $value ) {
117 + $is_allow_attr = in_array( $name, [ 'id', 'title' ] );
118 + $validate_name = preg_match( '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $name );
119 +
120 + if ( ! $is_allow_attr && ( ( ! empty( $available_tags ) && ! in_array( $name, $available_tags ) ) || ! $validate_name ) ) {
121 + unset( $attr[ $name ] );
122 + } else {
123 + // issue PCS-1
124 + // before sending the value to the shortcode, using encodeURIComponent(val).replace(/\./g, ‘%2E’); fixes the issue. Will the next update stop this from working?
125 + $value = urldecode( $value );
126 +
127 + // Remove script tag
128 + $value = preg_replace( '#<script(.*?)>(.*?)</script>#is', '', $value );
129 +
130 + // Remove any attribute starting with "on" or xmlns
131 + $value = preg_replace( '#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $value );
132 +
133 + // Remove javascript: and vbscript: protocols
134 + $value = preg_replace( '#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $value );
135 + $value = preg_replace( '#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $value );
136 + $value = preg_replace( '#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $value );
137 +
138 + // Filter value
139 + if ( version_compare( phpversion(), '7.3.0', '>=' ) ) {
140 + $filter = FILTER_SANITIZE_ADD_SLASHES;
141 + } else {
142 + $filter = FILTER_SANITIZE_MAGIC_QUOTES;
143 + }
144 + $value = filter_var( $value, FILTER_SANITIZE_SPECIAL_CHARS );
145 + $attr[ $name ] = filter_var( $value, $filter );
146 + }
147 + }
148 + }
149 +
150 + return $attr;
151 + }
152 +
153 + /**
154 + * Get snippet id
155 + *
156 + * @param array<string, mixed> $attr Shortcode attributes.
157 + * @param string $type Snippet type.
158 + *
159 + * @return int|null
160 + */
161 + public function get_snippet_id( $attr, $type ) {
162 + $id = isset( $attr['id'] ) ? (int) $attr['id'] : null;
163 +
164 + $snippet_type = null;
165 +
166 + // Only resolve snippet type when a valid (truthy) ID is provided to avoid
167 + // unnecessary request parsing or database lookups for invalid IDs.
168 + if ( $id ) {
169 + $snippet_type = WINP_Helper::get_snippet_type( $id );
170 +
171 + // Security: Reject if get_snippet_type() returned false (invalid post type)
172 + // or if the snippet type doesn't match the expected type.
173 + if ( false === $snippet_type || $snippet_type !== $type ) {
174 + $id = 0;
175 + }
176 + }
177 +
178 + return $id;
179 + }
180 +
181 + /**
182 + * Get snippet activate
183 + *
184 + * @param array<string, mixed> $snippet_meta Snippet metadata.
185 + *
186 + * @return bool
187 + */
188 + public function get_snippet_activate( $snippet_meta ) {
189 + // WPML Compatibility.
190 + if ( defined( 'WPML_PLUGIN_FILE' ) ) {
191 + $wpml_langs = isset( $snippet_meta['wbcr_inp_snippet_wpml_lang'][0] ) ? $snippet_meta['wbcr_inp_snippet_wpml_lang'][0] : '';
192 + if ( $wpml_langs !== '' && defined( 'ICL_LANGUAGE_CODE' ) ) {
193 + if ( ! in_array( ICL_LANGUAGE_CODE, explode( ',', $wpml_langs ) ) ) {
194 + return false;
195 + }
196 + }
197 + }
198 +
199 + return isset( $snippet_meta['wbcr_inp_snippet_activate'] ) && $snippet_meta['wbcr_inp_snippet_activate'][0];
200 + }
201 +
202 + /**
203 + * Get snippet scope
204 + *
205 + * @param array<string, mixed> $snippet_meta Snippet metadata.
206 + *
207 + * @return string|null
208 + */
209 + public function get_snippet_scope( $snippet_meta ) {
210 + return isset( $snippet_meta['wbcr_inp_snippet_scope'] ) ? $snippet_meta['wbcr_inp_snippet_scope'][0] : null;
211 + }
212 +
213 + /**
214 + * Get snippet content
215 + *
216 + * @param WP_Post $snippet Snippet post object.
217 + * @param array<string, mixed> $snippet_meta Snippet metadata.
218 + * @param int $id Snippet ID.
219 + *
220 + * @return string|null
221 + */
222 + public function get_snippet_content( $snippet, $snippet_meta, $id ) {
223 + $snippet_code = WINP_Helper::get_snippet_code( $snippet );
224 +
225 + if ( get_option( 'wbcr_inp_execute_shortcode' ) ) {
226 + $snippet_code = do_shortcode( $snippet_code );
227 + }
228 +
229 + return WINP_Plugin::app()->get_execute_object()->prepareCode( $snippet_code, $id );
230 + }
231 +
232 + /**
233 + * Content render
234 + *
235 + * @param array<string, mixed> $attr Shortcode attributes.
236 + * @param string $content Shortcode content.
237 + * @param string $tag Shortcode tag.
238 + *
239 + * @return mixed Rendered content when returned directly, if any.
240 + */
241 + public function html( $attr, $content, $tag ) {
242 + }
243 +}