PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/helpers/FrmAppHelper.php +55 -16 6.31 → trunk View file →
@@ -9,9 +9,9 @@
9 9 * Version of the database we are moving to.
10 10 *
11 11 * @var int
12 12 */
13 - public static $db_version = 105;
13 + public static $db_version = 106;
14 14
15 15 /**
16 16 * Used by the API add-on.
17 17 *
@@ -28,9 +28,9 @@
28 28 * @since 2.0
29 29 *
30 30 * @var string
31 31 */
32 - public static $plug_version = '6.31';
32 + public static $plug_version = '6.35';
33 33
34 34 /**
35 35 * @var bool
36 36 */
@@ -937,8 +937,9 @@
937 937 } else {
938 938 self::sanitize_value( self::class . '::strip_most_html', $value );
939 939 }
940 940 self::decode_specialchars( $value );
941 + self::sanitize_value( 'FrmHtmlSanitizer::sanitize_url_attributes', $value );
941 942 }
942 943
943 944 /**
944 945 * Allow only a small set of very basic HTML for unprivileged users.
@@ -1368,10 +1369,9 @@
1368 1369 if ( isset( $atts['echo'] ) ) {
1369 1370 unset( $atts['echo'] );
1370 1371 }
1371 1372
1372 - $html_atts = self::array_to_html_params( $atts );
1373 - $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1373 + $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1374 1374
1375 1375 // Replace icons that have been removed or renamed.
1376 1376 $deprecated = array(
1377 1377 'frm_clone_solid_icon' => 'frm_clone_icon',
@@ -1383,11 +1383,11 @@
1383 1383 $icon = $deprecated[ $icon ];
1384 1384 $class = str_replace( $icon, $deprecated[ $icon ], $class );
1385 1385 }
1386 1386
1387 - if ( $icon === $class ) {
1388 - $icon = '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>';
1389 - } else {
1387 + $is_font_icon = $icon === $class;
1388 +
1389 + if ( ! $is_font_icon ) {
1390 1390 $class = str_contains( $icon, ' ' ) ? ' ' . $icon : '';
1391 1391
1392 1392 if ( str_contains( $icon, ' ' ) ) {
1393 1393 $icon = explode( ' ', $icon );
@@ -1392,18 +1392,46 @@
1392 1392 if ( str_contains( $icon, ' ' ) ) {
1393 1393 $icon = explode( ' ', $icon );
1394 1394 $icon = reset( $icon );
1395 1395 }
1396 + }
1396 1397
1397 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use href="#' . esc_attr( $icon ) . '" /></svg>';
1398 - }
1398 + if ( $atts ) {
1399 + // A caller passed attributes, so kses still has to decide which of them survive. Its
1400 + // allowlist comes from safe_html() through the frm_striphtml_allowed_tags filter, and
1401 + // add-ons widen it around their own icons, so there is no fixed list to check against.
1402 + $html_atts = self::array_to_html_params( $atts );
1403 + $markup = $is_font_icon
1404 + ? '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>'
1405 + : '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use href="#' . esc_attr( $icon ) . '" /></svg>';
1399 1406
1400 - if ( $echo ) {
1401 - echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1407 + if ( ! $echo ) {
1408 + return $markup;
1409 + }
1410 +
1411 + echo self::kses_icon( $markup ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1402 1412 return null;
1403 1413 }
1404 1414
1405 - return $icon;
1415 + /**
1416 + * With no attributes from the caller, the tag is nothing but this method's own markup
1417 + * around an escaped class and icon id, so there is nothing left for kses to decide and it
1418 + * can be skipped. Echoing the pieces rather than a finished string keeps that safe to the
1419 + * escaping sniff without an annotation.
1420 + *
1421 + * This is the path the form builder takes for most of the tens of thousands of icons it
1422 + * renders on a large form, and the kses pass was most of what each one cost.
1423 + */
1424 + $callback = function () use ( $is_font_icon, $class, $icon ) {
1425 + if ( $is_font_icon ) {
1426 + echo '<i class="' . esc_attr( $class ) . '"></i>';
1427 + return;
1428 + }
1429 +
1430 + echo '<svg class="frmsvg' . esc_attr( $class ) . '"><use href="#' . esc_attr( $icon ) . '" /></svg>';
1431 + };
1432 +
1433 + return self::clip( $callback, $echo );
1406 1434 }
1407 1435
1408 1436 /**
1409 1437 * Run kses for icons. It needs to add a few filters first in order to preserve some custom style values.
@@ -1535,8 +1563,10 @@
1535 1563 * @param Closure $echo_function
1536 1564 * @param bool $echo
1537 1565 *
1538 1566 * @return string|null
1567 + *
1568 + * @psalm-return ($echo is true ? null : string)
1539 1569 */
1540 1570 public static function clip( $echo_function, $echo = false ) {
1541 1571 if ( ! $echo ) {
1542 1572 ob_start();
@@ -1628,9 +1658,9 @@
1628 1658
1629 1659 printf(
1630 1660 /* translators: %1$s: Start link HTML, %2$s: CTA text ("upgrading to PRO" by default), %3$s: End link HTML */
1631 1661 esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$s%2$s%3$s.', 'formidable' ),
1632 - '<a href="' . esc_url( $upgrade_link ) . '">',
1662 + '<a href="' . esc_url( $upgrade_link ) . '" target="_blank" rel="noopener">',
1633 1663 esc_html( $cta_text ),
1634 1664 '</a>'
1635 1665 );
1636 1666 ?>
@@ -4051,10 +4081,14 @@
4051 4081 if ( $square_connected ) {
4052 4082 $gateway_texts['square'] = esc_html__( 'Square', 'formidable' );
4053 4083 }
4054 4084
4085 + if ( $paypal_connected ) {
4086 + $gateway_texts['paypal'] = esc_html__( 'PayPal', 'formidable' );
4087 + }
4088 +
4055 4089 $admin_script_strings['pricingFieldsModal']['msg'] = sprintf(
4056 - // translators: %s: Stripe or Square.
4090 + // translators: %s: Stripe, Square, or PayPal.
4057 4091 esc_html__( 'You already have %s connected, so these have already been unlocked.', 'formidable' ),
4058 4092 esc_html( implode( ' ' . esc_html__( 'and', 'formidable' ) . ' ', $gateway_texts ) )
4059 4093 );
4060 4094 } else {
@@ -4061,9 +4095,9 @@
4061 4095 $admin_script_strings['pricingFieldsModal']['closeText'] = __( 'I\'ll do it later!', 'formidable' );
4062 4096 $admin_script_strings['pricingFieldsModal']['actionText'] = __( 'Setup Payments Now', 'formidable' );
4063 4097 $admin_script_strings['pricingFieldsModal']['actionUrl'] = $payments_settings_url;
4064 4098 // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
4065 - $admin_script_strings['pricingFieldsModal']['msg'] = __( 'We\'ve unlocked Product, Quantity, and Total fields for Lite users! You can now transform your forms into checkout pages. To start collecting revenue, simply connect your preferred payment gateway (Stripe, or Square) in your settings.', 'formidable' );
4099 + $admin_script_strings['pricingFieldsModal']['msg'] = __( 'We\'ve unlocked Product, Quantity, and Total fields for Lite users! You can now transform your forms into checkout pages. To start collecting revenue, simply connect your preferred payment gateway (Stripe, Square, or PayPal) in your settings.', 'formidable' );
4066 4100 }//end if
4067 4101
4068 4102 delete_option( 'frm_show_pricing_fields_modal' );
4069 4103 }
@@ -5103,13 +5137,18 @@
5103 5137 * Check if a string is valid UTF-8.
5104 5138 *
5105 5139 * @since 6.24
5106 5140 *
5107 - * @param string $string The string to check.
5141 + * @param string|null $string The string to check.
5108 5142 *
5109 5143 * @return bool
5110 5144 */
5111 5145 public static function is_valid_utf8( $string ) {
5146 + if ( is_null( $string ) ) {
5147 + // Return true so we do not attempt to change encoding on a null value.
5148 + return true;
5149 + }
5150 +
5112 5151 // wp_is_valid_utf8 is added in WP 6.9.
5113 5152 if ( function_exists( 'wp_is_valid_utf8' ) ) {
5114 5153 return wp_is_valid_utf8( $string );
5115 5154 }