PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
← All changes | app/Services/FormBuilder/EditorShortcodeParser.php +164 -74 3.6.646.2.14 View file →
@@ -1,16 +1,16 @@
1 1 <?php
2 2
3 3 namespace FluentForm\App\Services\FormBuilder;
4 4
5 +use FluentForm\App\Helpers\Helper;
5 6 use FluentForm\App\Services\Browser\Browser;
6 -use FluentForm\Framework\Helpers\ArrayHelper;
7 -use FluentForm\Request;
8 7
9 8 class EditorShortcodeParser
10 9 {
11 10 /**
12 11 * Available dynamic short codes
12 + *
13 13 * @var null
14 14 */
15 15 private static $dynamicShortcodes = null;
16 16
@@ -15,8 +15,9 @@
15 15 private static $dynamicShortcodes = null;
16 16
17 17 /**
18 18 * mappings of methods to parse the shortcode
19 + *
19 20 * @var array
20 21 */
21 22 private static $handlers = [
22 23 'ip' => 'parseIp',
@@ -41,24 +42,26 @@
41 42
42 43 'browser.name' => 'parseBrowserProperties',
43 44 'browser.platform' => 'parseBrowserProperties',
44 45
45 - 'get.param_name' => 'parseQueryParam'
46 + 'get.param_name' => 'parseRequestParam',
47 + 'random_string.param_name' => 'parseRandomString',
46 48 ];
47 49
48 50 /**
49 51 * Filter dynamic shortcodes in input value
52 + *
50 53 * @param string $value
54 + *
51 55 * @return string
52 56 */
53 57 public static function filter($value, $form)
54 58 {
55 - if (strpos($value, '{ ') === 0) {
59 + if (0 === strpos($value, '{ ')) {
56 60 // it's the css
57 61 return $value;
58 62 }
59 63
60 -
61 64 if (is_null(static::$dynamicShortcodes)) {
62 65 static::$dynamicShortcodes = fluentFormEditorShortCodes();
63 66 }
64 67
@@ -69,44 +72,53 @@
69 72 return call_user_func_array(
70 73 [__CLASS__, static::$handlers[$handler]],
71 74 ['{' . $handler . '}', $form]
72 75 );
73 - } elseif (strpos($handler, 'get.') !== false) {
74 - return static::parseQueryParam($handler);
75 - } else if (strpos($handler, 'user.meta.') !== false) {
76 - $key = substr(str_replace(['{', '}'], '', $value), 10);
77 - $user = wp_get_current_user();
78 - if ($user) {
79 - $value = get_post_meta($user->ID, $key, true);
80 - if (!is_array($value) && !is_object($value)) {
81 - return $value;
82 - }
83 - }
84 - return '';
85 - } else if (strpos($handler, 'user.') !== false) {
86 - $value = self::parseUserProperties($handler);
87 - if (is_array($value) || is_object($value)) {
76 + }
77 +
78 + if (false !== strpos($handler, 'get.')) {
79 + return static::parseRequestParam($handler);
80 + }
81 + if (false !== strpos($handler, 'random_string.')) {
82 + return static::parseRandomString($handler);
83 + }
84 +
85 + if (false !== strpos($handler, 'user.')) {
86 + $parsedValue = self::parseUserProperties($handler);
87 + if (is_array($parsedValue) || is_object($parsedValue)) {
88 88 return '';
89 89 }
90 - return $value;
91 - } else if (strpos($handler, 'date.') !== false) {
92 - return self::parseDate($handler);
93 - } else if (strpos($handler, 'embed_post.meta.') !== false) {
90 + return esc_html($parsedValue);
91 + }
92 +
93 + if (false !== strpos($handler, 'date.')) {
94 + return esc_html(self::parseDate($handler));
95 + }
96 +
97 + if (false !== strpos($handler, 'embed_post.meta.')) {
94 98 $key = substr(str_replace(['{', '}'], '', $value), 16);
95 99 global $post;
96 100 if ($post) {
97 - $value = get_post_meta($post->ID, $key, true);
98 - if (!is_array($value) && !is_object($value)) {
99 - return $value;
101 + $metaValue = get_post_meta($post->ID, $key, true);
102 + if (!is_array($metaValue) && !is_object($metaValue)) {
103 + return esc_html($metaValue);
100 104 }
101 105 }
102 106 return '';
103 - } else if (strpos($handler, 'embed_post.') !== false) {
107 + }
108 +
109 + if (false !== strpos($handler, 'embed_post.')) {
104 110 return self::parsePostProperties($handler, $form);
105 - } else if (strpos($handler, 'cookie.') !== false) {
111 + }
112 +
113 + if (false !== strpos($handler, 'cookie.')) {
106 114 $scookieProperty = substr($handler, strlen('cookie.'));
107 - return ArrayHelper::get($_COOKIE, $scookieProperty);
108 - } else if (strpos($handler, 'dynamic.') !== false) {
115 + $cookieValue = array_key_exists($scookieProperty, $_COOKIE) ? sanitize_text_field(wp_unslash($_COOKIE[$scookieProperty])) : '';
116 +
117 + return esc_attr($cookieValue);
118 + }
119 +
120 + if (false !== strpos($handler, 'dynamic.')) {
109 121 $dynamicKey = substr($handler, strlen('dynamic.'));
110 122 // maybe has fallback value
111 123 $dynamicKey = explode('|', $dynamicKey);
112 124 $fallBack = '';
@@ -113,21 +125,35 @@
113 125 $ref = '';
114 126 if (count($dynamicKey) > 1) {
115 127 $fallBack = $dynamicKey[1];
116 128 }
117 - $ref = $dynamicKey[0];
129 + if (isset($dynamicKey[0])) {
130 + $ref = $dynamicKey[0];
131 + }
118 132
119 - if ($ref == 'payment_summary') {
120 - return '<div class="ff_dynamic_value ff_dynamic_payment_summary" data-ref="payment_summary"><div class="ff_payment_summary"></div><div class="ff_payment_summary_fallback">' . $fallBack . '</div></div>';
133 + if ('payment_summary' == $ref) {
134 + return fluentform_sanitize_html('<div class="ff_dynamic_value ff_dynamic_payment_summary" data-ref="payment_summary"><div class="ff_payment_summary"></div><div class="ff_payment_summary_fallback">' . $fallBack . '</div></div>');
121 135 }
122 136
123 - return '<span class="ff_dynamic_value" data-ref="' . $ref . '" data-fallback="' . $fallBack . '">' . $fallBack . '</span>';
124 - } else {
125 - // This can be the css
126 - $handlerValue = apply_filters('fluentform_editor_shortcode_callback_' . $handler, '{' . $handler . '}', $form);
127 - // In not found then return the original please
128 - $filteredValue = $handlerValue;
137 + return fluentform_sanitize_html('<span class="ff_dynamic_value" data-ref="' . $ref . '" data-fallback="' . $fallBack . '">' . $fallBack . '</span>');
129 138 }
139 +
140 + // if it's multi line then just return
141 + if (false !== strpos($handler, PHP_EOL)) { // most probably it's a css
142 + return '{' . $handler . '}';
143 + }
144 +
145 + $handlerArray = explode('.', $handler);
146 +
147 + if (count($handlerArray) > 1) {
148 + // it's a grouped handler
149 + $group = array_shift($handlerArray);
150 + $parsedValue = apply_filters('fluentform_editor_shortcode_callback_group_' . $group, '{' . $handler . '}', $form, $handlerArray);
151 + return apply_filters('fluentform/editor_shortcode_callback_group_' . $group, $parsedValue, $form, $handlerArray);
152 + }
153 +
154 + $parsedValue = apply_filters('fluentform_editor_shortcode_callback_' . $handler, '{' . $handler . '}', $form);
155 + return apply_filters('fluentform/editor_shortcode_callback_' . $handler, $parsedValue, $form);
130 156 }
131 157
132 158 return $filteredValue;
133 159 }
@@ -132,10 +158,33 @@
132 158 return $filteredValue;
133 159 }
134 160
135 161 /**
162 + * Parse request query param.
163 + *
164 + * @param string $value
165 + * @param \stdClass $form
166 + *
167 + * @return string
168 + */
169 + public static function parseRequestParam($value)
170 + {
171 + $exploded = explode('.', $value);
172 + $param = array_pop($exploded);
173 + $value = wpFluentForm('request')->get($param);
174 +
175 + if (null === $value || '' === $value) {
176 + return '';
177 + }
178 +
179 + return esc_attr(Helper::flattenRequestValue($value));
180 + }
181 +
182 + /**
136 183 * Parse the curly braced shortcode into array
184 + *
137 185 * @param string $value
186 + *
138 187 * @return mixed
139 188 */
140 189 public static function parseValue($value)
141 190 {
@@ -142,9 +191,9 @@
142 191 if (!is_array($value)) {
143 192 return preg_split(
144 193 '/{(.*?)}/',
145 194 $value,
146 - null,
195 + -1,
147 196 PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
148 197 );
149 198 }
150 199
@@ -156,9 +205,11 @@
156 205 */
157 206
158 207 /**
159 208 * Parse loggedin user properties
209 + *
160 210 * @param string $value
211 + *
161 212 * @return string
162 213 */
163 214 private static function parseUserProperties($value, $form = null)
164 215 {
@@ -164,19 +215,28 @@
164 215 {
165 216 if ($user = wp_get_current_user()) {
166 217 $prop = substr(str_replace(['{', '}'], '', $value), 5);
167 218
168 - if (strpos($prop, 'meta.') !== false) {
219 + if (false !== strpos($prop, 'meta.')) {
169 220 $metaKey = substr($prop, strlen('meta.'));
221 + $metaKey = sanitize_text_field($metaKey);
222 + if (empty($metaKey) || ShortCodeParser::isDeniedUserProperty($metaKey)) {
223 + return '';
224 + }
170 225 $userId = $user->ID;
171 226 $data = get_user_meta($userId, $metaKey, true);
227 + $data = Helper::safeUnserialize($data);
172 228 if (!is_array($data)) {
173 - return $data;
229 + return esc_html($data);
174 230 }
231 + return esc_html(implode(',', $data));
232 + }
233 +
234 + if (ShortCodeParser::isDeniedUserProperty($prop)) {
175 235 return '';
176 236 }
177 237
178 - return $user->{$prop};
238 + return esc_html($user->{$prop});
179 239 }
180 240
181 241 return '';
182 242 }
@@ -182,9 +242,11 @@
182 242 }
183 243
184 244 /**
185 245 * Parse embedded post properties
246 + *
186 247 * @param string $value
248 + *
187 249 * @return string
188 250 */
189 251 private static function parsePostProperties($value, $form = null)
190 252 {
@@ -194,67 +256,68 @@
194 256 }
195 257
196 258 $key = $prop = substr(str_replace(['{', '}'], '', $value), 11);
197 259
198 - if (strpos($key, 'author.') !== false) {
260 + if (false !== strpos($key, 'author.')) {
199 261 $authorProperty = substr($key, strlen('author.'));
200 262 $authorId = $post->post_author;
201 - if ($authorId) {
263 + if ($authorId && !ShortCodeParser::isDeniedUserProperty($authorProperty)) {
202 264 $data = get_the_author_meta($authorProperty, $authorId);
203 265 if (!is_array($data)) {
204 - return $data;
266 + return esc_html($data);
205 267 }
206 268 }
207 269 return '';
208 - } else if (strpos($key, 'meta.') !== false) {
270 + } elseif (false !== strpos($key, 'meta.')) {
209 271 $metaKey = substr($key, strlen('meta.'));
210 272 $postId = $post->ID;
211 273 $data = get_post_meta($postId, $metaKey, true);
212 274 if (!is_array($data)) {
213 - return $data;
275 + return esc_html($data);
214 276 }
215 277 return '';
216 - } else if (strpos($key, 'acf.') !== false) {
278 + } elseif (false !== strpos($key, 'acf.')) {
217 279 $metaKey = substr($key, strlen('acf.'));
218 280 $postId = $post->ID;
219 281 if (function_exists('get_field')) {
220 282 $data = get_field($metaKey, $postId, true);
221 283 if (!is_array($data)) {
222 - return $data;
284 + return esc_html($data);
223 285 }
224 286 return '';
225 287 }
226 288 }
227 289
228 - if ($prop == 'permalink') {
229 - return htmlspecialchars(site_url(wp_unslash($_SERVER['REQUEST_URI'])));
290 + if ('permalink' == $prop) {
291 + return site_url(esc_attr(urldecode(wpFluentForm('request')->server('REQUEST_URI'))));
230 292 }
231 293
232 - if (property_exists($post, $prop)) {
233 - return $post->{$prop};
294 + if ('post_password' !== $prop && property_exists($post, $prop)) {
295 + return esc_html($post->{$prop});
234 296 }
235 297 return '';
236 298 }
237 299
238 -
239 300 /**
240 301 * Parse WP Properties
302 + *
241 303 * @param string $value
304 + *
242 305 * @return string
243 306 */
244 307 private static function parseWPProperties($value, $form = null)
245 308 {
246 - if ($value == '{wp.admin_email}') {
247 - return get_option('admin_email');
309 + if ('{wp.admin_email}' == $value) {
310 + return esc_html(get_option('admin_email'));
248 311 }
249 - if ($value == '{wp.site_url}') {
250 - return site_url();
312 + if ('{wp.site_url}' == $value) {
313 + return esc_url(site_url());
251 314 }
252 - if ($value == '{wp.site_title}') {
253 - return get_option('blogname');
315 + if ('{wp.site_title}' == $value) {
316 + return esc_html(get_option('blogname'));
254 317 }
255 - if ($value == '{http_referer}') {
256 - return wp_get_referer();
318 + if ('{http_referer}' == $value) {
319 + return esc_url(wp_get_referer());
257 320 }
258 321
259 322 return '';
260 323 }
@@ -260,18 +323,20 @@
260 323 }
261 324
262 325 /**
263 326 * Parse browser/user-agent properties
327 + *
264 328 * @param string $value
329 + *
265 330 * @return string
266 331 */
267 332 private static function parseBrowserProperties($value, $form = null)
268 333 {
269 - $browser = new Browser;
270 - if ($value == '{browser.name}') {
271 - return $browser->getBrowser();
272 - } elseif ($value == '{browser.platform}') {
273 - return $browser->getPlatform();
334 + $browser = new Browser();
335 + if ('{browser.name}' == $value) {
336 + return esc_html($browser->getBrowser());
337 + } elseif ('{browser.platform}' == $value) {
338 + return esc_html($browser->getPlatform());
274 339 }
275 340
276 341 return '';
277 342 }
@@ -277,20 +342,25 @@
277 342 }
278 343
279 344 /**
280 345 * Parse ip shortcode
346 + *
281 347 * @param string $value
348 + *
282 349 * @return string
283 350 */
284 351 private static function parseIp($value, $form = null)
285 352 {
286 - $ip = Request::getIp();
287 - return $ip ? $ip : $value;
353 + $rawIp = wpFluentForm('request')->getIp();
354 + $ip = sanitize_text_field($rawIp);
355 + return $ip ? esc_html($ip) : $value;
288 356 }
289 357
290 358 /**
291 359 * Parse date shortcode
360 + *
292 361 * @param string $value
362 + *
293 363 * @return string
294 364 */
295 365 private static function parseDate($value, $form = null)
296 366 {
@@ -295,9 +365,9 @@
295 365 private static function parseDate($value, $form = null)
296 366 {
297 367 $format = substr(str_replace(['}', '{'], '', $value), 5);
298 368 $date = date($format, strtotime(current_time('mysql')));
299 - return $date ? $date : '';
369 + return $date ? esc_html($date) : '';
300 370 }
301 371
302 372 /**
303 373 * Parse request query param.
@@ -303,8 +373,9 @@
303 373 * Parse request query param.
304 374 *
305 375 * @param string $value
306 376 * @param \stdClass $form
377 + *
307 378 * @return string
308 379 */
309 380 public static function parseQueryParam($value)
310 381 {
@@ -309,14 +380,33 @@
309 380 public static function parseQueryParam($value)
310 381 {
311 382 $exploded = explode('.', $value);
312 383 $param = array_pop($exploded);
313 - if (!isset($_REQUEST[$param])) {
384 + $value = wpFluentForm('request')->get($param);
385 +
386 + if (!$value) {
314 387 return '';
315 388 }
316 - $value = $_REQUEST[$param];
389 +
317 390 if (is_array($value)) {
318 391 return sanitize_textarea_field(implode(', ', $value));
319 392 }
393 +
320 394 return sanitize_textarea_field($value);
395 + }
396 +
397 + /**
398 + * Generate random a string with prefix
399 + *
400 + * @param $value
401 + *
402 + * @return string
403 + */
404 + public static function parseRandomString($value)
405 + {
406 + $exploded = explode('.', $value);
407 + $prefix = array_pop($exploded);
408 + $value = $prefix . uniqid();
409 +
410 + return esc_html(apply_filters('fluentform/shortcode_parser_callback_random_string', $value, $prefix, new static()));
321 411 }
322 412 }