Formidable Forms – Form Builder for WordPress - Version 5.0.13

Version Description

  • FrmAppHelper::jquery_ui_base_url and an unused dropdown view file have been deprecated.
  • Security: Back end form settings will now always filter on render when the DISALLOW_UNFILTERED_HTML constant is on.
  • Security: Added additional sanitizing when saving a custom style, added additional filtering to icons, and improved how some content is escaped.
  • New: Added a new frm_disallow_unfiltered_html filter that will always filter back form settings without having to set the DISALLOW_UNFILTERED_HTML constant.
  • New: A name field will always be used when sending comment author information to Akismet if one is set to avoid false positives that could cause another field value to possibly get sent instead.
  • Fix: When importing a grid or table view, [/if x] and [/foreach x] shortcodes were not properly being replaced.
  • Fix: Too much was being stripped from custom submit button HTML for underpriveleged users or when disallowing unfiltered html.
  • Fix: Too many calls were being made to Akismet for forms with multiple pages.
  • Fix: A conflict with WooCommerce was sometimes triggering an error when checking for addon updates.
  • Fix: The comment author information sent to Akismet was not getting set if the author information was set in a name field.
Download this release

Release Info

Developer formidableforms
Plugin Icon 128x128 Formidable Forms – Form Builder for WordPress
Version 5.0.13
Comparing to
See all releases

Code changes from version 5.0.12 to 5.0.13

Files changed (80) hide show
  1. classes/controllers/FrmEntriesController.php +7 -7
  2. classes/controllers/FrmFieldsController.php +1 -1
  3. classes/controllers/FrmFormsController.php +20 -21
  4. classes/controllers/FrmSMTPController.php +4 -4
  5. classes/controllers/FrmStylesController.php +1 -0
  6. classes/controllers/FrmWelcomeController.php +1 -1
  7. classes/helpers/FrmAppHelper.php +258 -55
  8. classes/helpers/FrmCSVExportHelper.php +2 -2
  9. classes/helpers/FrmEntriesHelper.php +17 -24
  10. classes/helpers/FrmEntriesListHelper.php +2 -2
  11. classes/helpers/FrmFieldsHelper.php +19 -15
  12. classes/helpers/FrmFormsHelper.php +13 -11
  13. classes/helpers/FrmListHelper.php +13 -13
  14. classes/helpers/FrmStylesHelper.php +9 -29
  15. classes/helpers/FrmXMLHelper.php +1 -1
  16. classes/models/FrmAddon.php +9 -3
  17. classes/models/FrmDb.php +3 -3
  18. classes/models/FrmEntry.php +3 -3
  19. classes/models/FrmEntryMeta.php +4 -4
  20. classes/models/FrmEntryValidate.php +175 -37
  21. classes/models/FrmField.php +1 -1
  22. classes/models/FrmFieldFormHtml.php +2 -2
  23. classes/models/FrmForm.php +8 -5
  24. classes/models/FrmFormAction.php +2 -1
  25. classes/models/FrmMigrate.php +7 -7
  26. classes/models/FrmNotification.php +1 -1
  27. classes/models/FrmSolution.php +1 -1
  28. classes/models/FrmStyle.php +40 -6
  29. classes/models/fields/FrmFieldCaptcha.php +2 -1
  30. classes/models/fields/FrmFieldCombo.php +2 -5
  31. classes/models/fields/FrmFieldDefault.php +2 -2
  32. classes/models/fields/FrmFieldTextarea.php +3 -3
  33. classes/models/fields/FrmFieldType.php +3 -3
  34. classes/models/fields/FrmFieldUserID.php +1 -1
  35. classes/views/frm-entries/direct.php +1 -1
  36. classes/views/frm-entries/errors.php +1 -1
  37. classes/views/frm-entries/form.php +4 -4
  38. classes/views/frm-entries/new.php +2 -2
  39. classes/views/frm-entries/show.php +1 -1
  40. classes/views/frm-entries/sidebar-shared.php +4 -4
  41. classes/views/frm-fields/back-end/ajax-field-placeholder.php +1 -1
  42. classes/views/frm-fields/back-end/dropdown-field.php +11 -32
  43. classes/views/frm-fields/back-end/field-choices.php +1 -1
  44. classes/views/frm-fields/back-end/field-description.php +1 -1
  45. classes/views/frm-fields/back-end/html-content.php +1 -1
  46. classes/views/frm-fields/back-end/radio-field.php +2 -2
  47. classes/views/frm-fields/back-end/settings.php +2 -2
  48. classes/views/frm-fields/front-end/checkbox-field.php +2 -2
  49. classes/views/frm-fields/front-end/combo-field/combo-field.php +10 -15
  50. classes/views/frm-fields/front-end/dropdown-field.php +1 -1
  51. classes/views/frm-fields/front-end/radio-field.php +2 -2
  52. classes/views/frm-fields/input.php +1 -1
  53. classes/views/frm-form-actions/_action_icon.php +2 -4
  54. classes/views/frm-form-actions/_email_settings.php +1 -1
  55. classes/views/frm-form-actions/settings.php +1 -3
  56. classes/views/frm-forms/add_field.php +3 -3
  57. classes/views/frm-forms/add_field_links.php +1 -1
  58. classes/views/frm-forms/settings-advanced.php +2 -2
  59. classes/views/frm-forms/settings-html.php +4 -4
  60. classes/views/frm-settings/form.php +1 -1
  61. classes/views/frm-settings/tabs.php +1 -1
  62. classes/views/inbox/list.php +2 -2
  63. classes/views/shared/admin-header.php +1 -1
  64. classes/views/shared/errors.php +5 -5
  65. classes/views/shared/form-nav.php +1 -1
  66. classes/views/shared/upgrade_overlay.php +1 -1
  67. classes/views/solutions/_import.php +2 -2
  68. classes/views/styles/custom_css.php +1 -1
  69. classes/views/styles/show.php +1 -1
  70. classes/views/xml/forms_xml.php +12 -12
  71. classes/views/xml/posts_xml.php +9 -9
  72. classes/widgets/FrmShowForm.php +4 -4
  73. css/_single_theme.css.php +5 -5
  74. css/custom_theme.css.php +9 -9
  75. deprecated/FrmDeprecated.php +5 -19
  76. deprecated/FrmEDD_SL_Plugin_Updater.php +5 -5
  77. formidable.php +1 -1
  78. js/formidable_admin.js +0 -37
  79. languages/formidable.pot +568 -568
  80. readme.txt +14 -9
classes/controllers/FrmEntriesController.php CHANGED
@@ -406,7 +406,7 @@ class FrmEntriesController {
406
  if ( $pagenum > $total_pages && $total_pages > 0 ) {
407
  $url = add_query_arg( 'paged', $total_pages );
408
  if ( headers_sent() ) {
409
- echo FrmAppHelper::js_redirect( $url ); // WPCS: XSS ok.
410
  } else {
411
  wp_redirect( esc_url_raw( $url ) );
412
  }
@@ -417,7 +417,7 @@ class FrmEntriesController {
417
  $message = __( 'Your import is complete', 'formidable' );
418
  }
419
 
420
- require( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/list.php' );
421
  }
422
 
423
  private static function get_delete_form_time( $form, &$errors ) {
@@ -491,7 +491,7 @@ class FrmEntriesController {
491
 
492
  public static function process_entry( $errors = '', $ajax = false ) {
493
  $form_id = FrmAppHelper::get_post_param( 'form_id', '', 'absint' );
494
- if ( FrmAppHelper::is_admin() || empty( $_POST ) || empty( $form_id ) || ! isset( $_POST['item_key'] ) ) {
495
  return;
496
  }
497
 
@@ -514,7 +514,7 @@ class FrmEntriesController {
514
  }
515
 
516
  if ( $errors == '' && ! $ajax ) {
517
- $errors = FrmEntryValidate::validate( wp_unslash( $_POST ) );
518
  }
519
 
520
  /**
@@ -530,9 +530,9 @@ class FrmEntriesController {
530
  if ( empty( $errors ) ) {
531
  $_POST['frm_skip_cookie'] = 1;
532
  $do_success = false;
533
- if ( $params['action'] == 'create' ) {
534
  if ( apply_filters( 'frm_continue_to_create', true, $form_id ) && ! isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) {
535
- $frm_vars['created_entries'][ $form_id ]['entry_id'] = FrmEntry::create( $_POST );
536
 
537
  $params['id'] = $frm_vars['created_entries'][ $form_id ]['entry_id'];
538
  $do_success = true;
@@ -543,7 +543,7 @@ class FrmEntriesController {
543
  if ( $do_success ) {
544
  FrmFormsController::maybe_trigger_redirect( $form, $params, array( 'ajax' => $ajax ) );
545
  }
546
- unset( $_POST['frm_skip_cookie'] );
547
  }
548
  }
549
 
406
  if ( $pagenum > $total_pages && $total_pages > 0 ) {
407
  $url = add_query_arg( 'paged', $total_pages );
408
  if ( headers_sent() ) {
409
+ FrmAppHelper::js_redirect( $url, true );
410
  } else {
411
  wp_redirect( esc_url_raw( $url ) );
412
  }
417
  $message = __( 'Your import is complete', 'formidable' );
418
  }
419
 
420
+ require FrmAppHelper::plugin_path() . '/classes/views/frm-entries/list.php';
421
  }
422
 
423
  private static function get_delete_form_time( $form, &$errors ) {
491
 
492
  public static function process_entry( $errors = '', $ajax = false ) {
493
  $form_id = FrmAppHelper::get_post_param( 'form_id', '', 'absint' );
494
+ if ( FrmAppHelper::is_admin() || empty( $_POST ) || empty( $form_id ) || ! isset( $_POST['item_key'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
495
  return;
496
  }
497
 
514
  }
515
 
516
  if ( $errors == '' && ! $ajax ) {
517
+ $errors = FrmEntryValidate::validate( wp_unslash( $_POST ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
518
  }
519
 
520
  /**
530
  if ( empty( $errors ) ) {
531
  $_POST['frm_skip_cookie'] = 1;
532
  $do_success = false;
533
+ if ( $params['action'] === 'create' ) {
534
  if ( apply_filters( 'frm_continue_to_create', true, $form_id ) && ! isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) {
535
+ $frm_vars['created_entries'][ $form_id ]['entry_id'] = FrmEntry::create( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
536
 
537
  $params['id'] = $frm_vars['created_entries'][ $form_id ]['entry_id'];
538
  $do_success = true;
543
  if ( $do_success ) {
544
  FrmFormsController::maybe_trigger_redirect( $form, $params, array( 'ajax' => $ajax ) );
545
  }
546
+ unset( $_POST['frm_skip_cookie'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
547
  }
548
  }
549
 
classes/controllers/FrmFieldsController.php CHANGED
@@ -444,7 +444,7 @@ class FrmFieldsController {
444
  $add_html = ' ' . implode( ' ', $add_html ) . ' ';
445
 
446
  if ( $echo ) {
447
- echo $add_html; // WPCS: XSS ok.
448
  }
449
 
450
  return $add_html;
444
  $add_html = ' ' . implode( ' ', $add_html ) . ' ';
445
 
446
  if ( $echo ) {
447
+ echo $add_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
448
  }
449
 
450
  return $add_html;
classes/controllers/FrmFormsController.php CHANGED
@@ -130,8 +130,8 @@ class FrmFormsController {
130
 
131
  $id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
132
 
133
- $errors = FrmForm::validate( $_POST );
134
- $warnings = FrmFormsHelper::check_for_warnings( $_POST );
135
 
136
  if ( count( $errors ) > 0 ) {
137
  return self::get_settings_vars( $id, $errors, compact( 'warnings' ) );
@@ -141,9 +141,9 @@ class FrmFormsController {
141
 
142
  $antispam_was_on = self::antispam_was_on( $id );
143
 
144
- FrmForm::update( $id, $_POST );
145
 
146
- $antispam_is_on = ! empty( $_POST['options']['antispam'] );
147
  if ( $antispam_is_on !== $antispam_was_on ) {
148
  FrmAntiSpam::clear_caches();
149
  }
@@ -164,7 +164,7 @@ class FrmFormsController {
164
 
165
  public static function update( $values = array() ) {
166
  if ( empty( $values ) ) {
167
- $values = $_POST;
168
  }
169
 
170
  // Set radio button and checkbox meta equal to "other" value.
@@ -196,7 +196,7 @@ class FrmFormsController {
196
  }
197
 
198
  if ( defined( 'DOING_AJAX' ) ) {
199
- wp_die( FrmAppHelper::kses( $message, array( 'a' ) ) ); // WPCS: XSS ok.
200
  }
201
 
202
  return self::get_edit_vars( $id, array(), $message );
@@ -267,7 +267,7 @@ class FrmFormsController {
267
  * @since 3.0
268
  */
269
  public static function show_page_preview() {
270
- echo self::page_preview(); // WPCS: XSS ok.
271
  }
272
 
273
  public static function preview() {
@@ -646,8 +646,8 @@ class FrmFormsController {
646
  $menu_name = FrmAppHelper::get_menu_name();
647
  $icon = apply_filters( 'frm_media_icon', FrmAppHelper::svg_logo() );
648
  echo '<a href="#TB_inline?width=50&height=50&inlineId=frm_insert_form" class="thickbox button add_media frm_insert_form" title="' . esc_attr__( 'Add forms and content', 'formidable' ) . '">' .
649
- FrmAppHelper::kses( $icon, 'all' ) .
650
- ' ' . esc_html( $menu_name ) . '</a>'; // WPCS: XSS ok.
651
  }
652
  }
653
 
@@ -1368,7 +1368,7 @@ class FrmFormsController {
1368
  FrmAppHelper::permission_check( 'frm_view_forms' );
1369
  check_ajax_referer( 'frm_ajax', 'nonce' );
1370
 
1371
- echo FrmEntriesController::show_entry_shortcode( // WPCS: XSS ok.
1372
  array(
1373
  'form_id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
1374
  'default_email' => true,
@@ -1465,11 +1465,11 @@ class FrmFormsController {
1465
  $vars = array();
1466
  FrmAppHelper::include_svg();
1467
 
1468
- if ( isset( $_POST['frm_compact_fields'] ) ) {
1469
  FrmAppHelper::permission_check( 'frm_edit_forms' );
1470
 
1471
  // Javascript needs to be allowed in some field settings.
1472
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1473
  $json_vars = htmlspecialchars_decode( nl2br( str_replace( '&quot;', '"', wp_unslash( $_POST['frm_compact_fields'] ) ) ) );
1474
  $json_vars = json_decode( $json_vars, true );
1475
  if ( empty( $json_vars ) ) {
@@ -1483,9 +1483,9 @@ class FrmFormsController {
1483
  } else {
1484
  $vars = FrmAppHelper::json_to_array( $json_vars );
1485
  $action = $vars[ $action ];
1486
- unset( $_REQUEST['frm_compact_fields'], $_POST['frm_compact_fields'] );
1487
- $_REQUEST = array_merge( $_REQUEST, $vars );
1488
- $_POST = array_merge( $_POST, $_REQUEST );
1489
  }
1490
  } else {
1491
  $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
@@ -1746,7 +1746,7 @@ class FrmFormsController {
1746
  }
1747
 
1748
  private static function is_viewable_draft_form( $form ) {
1749
- return $form->status == 'draft' && current_user_can( 'frm_edit_forms' ) && ! FrmAppHelper::is_preview_page();
1750
  }
1751
 
1752
  public static function get_form( $form, $title, $description, $atts = array() ) {
@@ -1776,7 +1776,7 @@ class FrmFormsController {
1776
  $reset = false;
1777
  $pass_args = compact( 'form', 'fields', 'errors', 'title', 'description', 'reset' );
1778
 
1779
- $handle_process_here = $params['action'] == 'create' && $params['posted_form_id'] == $form->id && $_POST;
1780
 
1781
  if ( ! $handle_process_here ) {
1782
  do_action( 'frm_display_form_action', $params, $fields, $form, $title, $description );
@@ -1817,7 +1817,7 @@ class FrmFormsController {
1817
  private static function get_saved_errors( $form, $params ) {
1818
  global $frm_vars;
1819
 
1820
- if ( $params['posted_form_id'] == $form->id && $_POST && isset( $frm_vars['created_entries'][ $form->id ] ) ) {
1821
  $errors = $frm_vars['created_entries'][ $form->id ]['errors'];
1822
  } else {
1823
  $errors = array();
@@ -1917,7 +1917,7 @@ class FrmFormsController {
1917
  $old_post = $post;
1918
  $post = $page;
1919
  $content = apply_filters( 'frm_content', $page->post_content, $args['form'], $args['entry_id'] );
1920
- echo apply_filters( 'the_content', $content ); // WPCS: XSS ok.
1921
  $post = $old_post;
1922
  }
1923
  }
@@ -1955,8 +1955,7 @@ class FrmFormsController {
1955
  die(); // do not use wp_die or redirect fails
1956
  } else {
1957
  add_filter( 'frm_use_wpautop', '__return_true' );
1958
-
1959
- echo $redirect_msg; // WPCS: XSS ok.
1960
  echo "<script type='text/javascript'>window.onload = function(){setTimeout(window.location='" . esc_url_raw( $success_url ) . "', 8000);}</script>";
1961
  }
1962
  }
130
 
131
  $id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
132
 
133
+ $errors = FrmForm::validate( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
134
+ $warnings = FrmFormsHelper::check_for_warnings( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
135
 
136
  if ( count( $errors ) > 0 ) {
137
  return self::get_settings_vars( $id, $errors, compact( 'warnings' ) );
141
 
142
  $antispam_was_on = self::antispam_was_on( $id );
143
 
144
+ FrmForm::update( $id, $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
145
 
146
+ $antispam_is_on = ! empty( $_POST['options']['antispam'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
147
  if ( $antispam_is_on !== $antispam_was_on ) {
148
  FrmAntiSpam::clear_caches();
149
  }
164
 
165
  public static function update( $values = array() ) {
166
  if ( empty( $values ) ) {
167
+ $values = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
168
  }
169
 
170
  // Set radio button and checkbox meta equal to "other" value.
196
  }
197
 
198
  if ( defined( 'DOING_AJAX' ) ) {
199
+ wp_die( FrmAppHelper::kses( $message, array( 'a' ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
200
  }
201
 
202
  return self::get_edit_vars( $id, array(), $message );
267
  * @since 3.0
268
  */
269
  public static function show_page_preview() {
270
+ echo self::page_preview(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
271
  }
272
 
273
  public static function preview() {
646
  $menu_name = FrmAppHelper::get_menu_name();
647
  $icon = apply_filters( 'frm_media_icon', FrmAppHelper::svg_logo() );
648
  echo '<a href="#TB_inline?width=50&height=50&inlineId=frm_insert_form" class="thickbox button add_media frm_insert_form" title="' . esc_attr__( 'Add forms and content', 'formidable' ) . '">' .
649
+ FrmAppHelper::kses( $icon, 'all' ) . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
650
+ ' ' . esc_html( $menu_name ) . '</a>';
651
  }
652
  }
653
 
1368
  FrmAppHelper::permission_check( 'frm_view_forms' );
1369
  check_ajax_referer( 'frm_ajax', 'nonce' );
1370
 
1371
+ echo FrmEntriesController::show_entry_shortcode( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1372
  array(
1373
  'form_id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
1374
  'default_email' => true,
1465
  $vars = array();
1466
  FrmAppHelper::include_svg();
1467
 
1468
+ if ( isset( $_POST['frm_compact_fields'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1469
  FrmAppHelper::permission_check( 'frm_edit_forms' );
1470
 
1471
  // Javascript needs to be allowed in some field settings.
1472
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
1473
  $json_vars = htmlspecialchars_decode( nl2br( str_replace( '&quot;', '"', wp_unslash( $_POST['frm_compact_fields'] ) ) ) );
1474
  $json_vars = json_decode( $json_vars, true );
1475
  if ( empty( $json_vars ) ) {
1483
  } else {
1484
  $vars = FrmAppHelper::json_to_array( $json_vars );
1485
  $action = $vars[ $action ];
1486
+ unset( $_REQUEST['frm_compact_fields'], $_POST['frm_compact_fields'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1487
+ $_REQUEST = array_merge( $_REQUEST, $vars ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1488
+ $_POST = array_merge( $_POST, $_REQUEST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1489
  }
1490
  } else {
1491
  $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
1746
  }
1747
 
1748
  private static function is_viewable_draft_form( $form ) {
1749
+ return $form->status === 'draft' && current_user_can( 'frm_edit_forms' ) && ! FrmAppHelper::is_preview_page();
1750
  }
1751
 
1752
  public static function get_form( $form, $title, $description, $atts = array() ) {
1776
  $reset = false;
1777
  $pass_args = compact( 'form', 'fields', 'errors', 'title', 'description', 'reset' );
1778
 
1779
+ $handle_process_here = $params['action'] === 'create' && $params['posted_form_id'] == $form->id && $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
1780
 
1781
  if ( ! $handle_process_here ) {
1782
  do_action( 'frm_display_form_action', $params, $fields, $form, $title, $description );
1817
  private static function get_saved_errors( $form, $params ) {
1818
  global $frm_vars;
1819
 
1820
+ if ( $params['posted_form_id'] == $form->id && $_POST && isset( $frm_vars['created_entries'][ $form->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1821
  $errors = $frm_vars['created_entries'][ $form->id ]['errors'];
1822
  } else {
1823
  $errors = array();
1917
  $old_post = $post;
1918
  $post = $page;
1919
  $content = apply_filters( 'frm_content', $page->post_content, $args['form'], $args['entry_id'] );
1920
+ echo apply_filters( 'the_content', $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1921
  $post = $old_post;
1922
  }
1923
  }
1955
  die(); // do not use wp_die or redirect fails
1956
  } else {
1957
  add_filter( 'frm_use_wpautop', '__return_true' );
1958
+ echo FrmAppHelper::maybe_kses( $redirect_msg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
 
1959
  echo "<script type='text/javascript'>window.onload = function(){setTimeout(window.location='" . esc_url_raw( $success_url ) . "', 8000);}</script>";
1960
  }
1961
  }
classes/controllers/FrmSMTPController.php CHANGED
@@ -221,14 +221,14 @@ class FrmSMTPController {
221
  <span><a rel="%4$s" class="button button-primary frm-button-primary %5$s" aria-label="%6$s">%7$s</a></span>
222
  </div>
223
  </section>',
224
- FrmAppHelper::kses( $icon, array( 'a', 'i', 'span', 'use', 'svg' ) ), // WPCS: XSS ok.
225
  esc_html( $label ),
226
  esc_html__( 'Install WP Mail SMTP from the WordPress.org plugin repository.', 'formidable' ),
227
  esc_attr( $step['plugin'] ),
228
  esc_attr( $step['button_class'] ),
229
  esc_attr( $step['button_action'] ),
230
  esc_html( $step['button_text'] )
231
- ); // WPCS: XSS ok.
232
  }
233
 
234
  /**
@@ -266,13 +266,13 @@ class FrmSMTPController {
266
  </div>
267
  </section>',
268
  esc_attr( $step['section_class'] ),
269
- FrmAppHelper::kses( $icon, array( 'a', 'i', 'span', 'use', 'svg' ) ), // WPCS: XSS ok.
270
  esc_html__( 'Set Up WP Mail SMTP', 'formidable' ),
271
  esc_html__( 'Select and configure your mailer.', 'formidable' ),
272
  esc_url( admin_url( $this->config['smtp_settings'] ) ),
273
  esc_attr( $step['button_class'] ),
274
  esc_html( $step['button_text'] )
275
- ); // WPCS: XSS ok.
276
  }
277
 
278
  /**
221
  <span><a rel="%4$s" class="button button-primary frm-button-primary %5$s" aria-label="%6$s">%7$s</a></span>
222
  </div>
223
  </section>',
224
+ FrmAppHelper::kses( $icon, array( 'a', 'i', 'span', 'use', 'svg' ) ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
225
  esc_html( $label ),
226
  esc_html__( 'Install WP Mail SMTP from the WordPress.org plugin repository.', 'formidable' ),
227
  esc_attr( $step['plugin'] ),
228
  esc_attr( $step['button_class'] ),
229
  esc_attr( $step['button_action'] ),
230
  esc_html( $step['button_text'] )
231
+ );
232
  }
233
 
234
  /**
266
  </div>
267
  </section>',
268
  esc_attr( $step['section_class'] ),
269
+ FrmAppHelper::kses( $icon, array( 'a', 'i', 'span', 'use', 'svg' ) ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
270
  esc_html__( 'Set Up WP Mail SMTP', 'formidable' ),
271
  esc_html__( 'Select and configure your mailer.', 'formidable' ),
272
  esc_url( admin_url( $this->config['smtp_settings'] ) ),
273
  esc_attr( $step['button_class'] ),
274
  esc_html( $step['button_text'] )
275
+ );
276
  }
277
 
278
  /**
classes/controllers/FrmStylesController.php CHANGED
@@ -267,6 +267,7 @@ class FrmStylesController {
267
 
268
  private static function manage_styles() {
269
  $style_nonce = FrmAppHelper::get_post_param( 'frm_manage_style', '', 'sanitize_text_field' );
 
270
  if ( ! $_POST || ! isset( $_POST['style'] ) || ! wp_verify_nonce( $style_nonce, 'frm_manage_style_nonce' ) ) {
271
  return self::manage();
272
  }
267
 
268
  private static function manage_styles() {
269
  $style_nonce = FrmAppHelper::get_post_param( 'frm_manage_style', '', 'sanitize_text_field' );
270
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
271
  if ( ! $_POST || ! isset( $_POST['style'] ) || ! wp_verify_nonce( $style_nonce, 'frm_manage_style_nonce' ) ) {
272
  return self::manage();
273
  }
classes/controllers/FrmWelcomeController.php CHANGED
@@ -42,7 +42,7 @@ class FrmWelcomeController {
42
  }
43
 
44
  // Only do this for single site installs.
45
- if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // WPCS: CSRF ok.
46
  return;
47
  }
48
 
42
  }
43
 
44
  // Only do this for single site installs.
45
+ if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
46
  return;
47
  }
48
 
classes/helpers/FrmAppHelper.php CHANGED
@@ -11,7 +11,7 @@ class FrmAppHelper {
11
  /**
12
  * @since 2.0
13
  */
14
- public static $plug_version = '5.0.12';
15
 
16
  /**
17
  * @since 1.07.02
@@ -169,7 +169,7 @@ class FrmAppHelper {
169
  * @since 4.0
170
  */
171
  public static function show_logo( $atts = array() ) {
172
- echo self::kses( self::svg_logo( $atts ), 'all' ); // WPCS: XSS ok.
173
  }
174
 
175
  /**
@@ -192,7 +192,7 @@ class FrmAppHelper {
192
  $icon = '<div style="height:39px"></div>';
193
  }
194
  }
195
- echo self::kses( $icon, 'all' ); // WPCS: XSS ok.
196
  }
197
 
198
  /**
@@ -410,10 +410,9 @@ class FrmAppHelper {
410
  $param = $params[0];
411
  }
412
 
413
- if ( $src == 'get' ) {
414
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
415
- $value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default );
416
- if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) {
417
  // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
418
  $value = htmlspecialchars_decode( wp_unslash( $_GET[ $param ] ) );
419
  }
@@ -497,19 +496,19 @@ class FrmAppHelper {
497
  $value = $args['default'];
498
  if ( $args['type'] == 'get' ) {
499
  if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
500
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
501
  $value = wp_unslash( $_GET[ $args['param'] ] );
502
  }
503
  } elseif ( $args['type'] == 'post' ) {
504
- if ( isset( $_POST[ $args['param'] ] ) ) {
505
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
506
  $value = wp_unslash( $_POST[ $args['param'] ] );
507
  if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
508
  self::unserialize_or_decode( $value );
509
  }
510
  }
511
  } else {
512
- if ( isset( $_REQUEST[ $args['param'] ] ) ) {
513
  // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
514
  $value = wp_unslash( $_REQUEST[ $args['param'] ] );
515
  }
@@ -645,6 +644,72 @@ class FrmAppHelper {
645
  return wp_kses( $value, $allowed_html );
646
  }
647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  /**
649
  * @since 2.05.03
650
  */
@@ -672,13 +737,14 @@ class FrmAppHelper {
672
  );
673
 
674
  return array(
675
- 'a' => array(
676
- 'class' => true,
677
- 'href' => true,
678
- 'id' => true,
679
- 'rel' => true,
680
- 'target' => true,
681
- 'title' => true,
 
682
  ),
683
  'abbr' => array(
684
  'title' => true,
@@ -704,6 +770,7 @@ class FrmAppHelper {
704
  'id' => true,
705
  'title' => true,
706
  'style' => true,
 
707
  ),
708
  'dl' => array(),
709
  'dt' => array(),
@@ -768,17 +835,19 @@ class FrmAppHelper {
768
  'viewbox' => true,
769
  ),
770
  'svg' => array(
771
- 'class' => true,
772
- 'id' => true,
773
- 'xmlns' => true,
774
- 'viewbox' => true,
775
- 'width' => true,
776
- 'height' => true,
777
- 'style' => true,
778
- 'fill' => true,
 
 
779
  ),
780
  'use' => array(
781
- 'href' => true,
782
  'xlink:href' => true,
783
  ),
784
  'ul' => $allow_class,
@@ -861,18 +930,78 @@ class FrmAppHelper {
861
  $icon = explode( ' ', $icon );
862
  $icon = reset( $icon );
863
  }
864
- $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
865
  <use xlink:href="#' . esc_attr( $icon ) . '" />
866
  </svg>';
867
  }
868
 
869
  if ( $echo ) {
870
- echo $icon; // WPCS: XSS ok.
871
  } else {
872
  return $icon;
873
  }
874
  }
875
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876
  /**
877
  * Include svg images.
878
  *
@@ -886,17 +1015,44 @@ class FrmAppHelper {
886
  * Convert an associative array to HTML values.
887
  *
888
  * @since 4.0.02
 
 
889
  * @param array $atts
890
- * @return string
891
- */
892
- public static function array_to_html_params( $atts ) {
893
- $html = '';
894
- if ( ! empty( $atts ) ) {
895
- foreach ( $atts as $key => $value ) {
896
- $html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
 
 
897
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
  }
899
- return $html;
900
  }
901
 
902
  /**
@@ -1541,17 +1697,6 @@ class FrmAppHelper {
1541
  return $val;
1542
  }
1543
 
1544
- /**
1545
- * @since 2.0
1546
- * @return string The base Google APIS url for the current version of jQuery UI
1547
- */
1548
- public static function jquery_ui_base_url() {
1549
- $url = 'http' . ( is_ssl() ? 's' : '' ) . '://ajax.googleapis.com/ajax/libs/jqueryui/' . self::script_version( 'jquery-ui-core', '1.11.4' );
1550
- $url = apply_filters( 'frm_jquery_ui_base_url', $url );
1551
-
1552
- return $url;
1553
- }
1554
-
1555
  /**
1556
  * @param string $handle
1557
  */
@@ -1574,8 +1719,18 @@ class FrmAppHelper {
1574
  return $ver;
1575
  }
1576
 
1577
- public static function js_redirect( $url ) {
1578
- return '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
 
 
 
 
 
 
 
 
 
 
1579
  }
1580
 
1581
  public static function get_user_id_param( $user_id ) {
@@ -1733,7 +1888,7 @@ class FrmAppHelper {
1733
  }
1734
 
1735
  if ( empty( $post_values ) ) {
1736
- $post_values = wp_unslash( $_POST );
1737
  }
1738
 
1739
  $values = array(
@@ -1753,9 +1908,9 @@ class FrmAppHelper {
1753
 
1754
  self::prepare_field_arrays( $fields, $record, $values, array_merge( $args, compact( 'default', 'post_values' ) ) );
1755
 
1756
- if ( $table == 'entries' ) {
1757
  $values = FrmEntriesHelper::setup_edit_vars( $values, $record );
1758
- } elseif ( $table == 'forms' ) {
1759
  $values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
1760
  }
1761
 
@@ -2564,7 +2719,7 @@ class FrmAppHelper {
2564
  'updating' => __( 'Please wait while your site updates.', 'formidable' ),
2565
  'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
2566
  'private_label' => __( 'Private', 'formidable' ),
2567
- 'jquery_ui_url' => self::jquery_ui_base_url(),
2568
  'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
2569
  'no_licenses' => __( 'No new licenses were found', 'formidable' ),
2570
  'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
@@ -2983,12 +3138,32 @@ class FrmAppHelper {
2983
  * @return bool true if the current user is allowed to save unfiltered HTML.
2984
  */
2985
  public static function allow_unfiltered_html() {
2986
- if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
2987
  return false;
2988
  }
2989
  return current_user_can( 'unfiltered_html' );
2990
  }
2991
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2992
  /**
2993
  * @since 5.0.07
2994
  *
@@ -3012,6 +3187,23 @@ class FrmAppHelper {
3012
  return $values;
3013
  }
3014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3015
  /**
3016
  * @since 4.07
3017
  * @deprecated 4.09.01
@@ -3238,4 +3430,15 @@ class FrmAppHelper {
3238
  public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
3239
  return FrmDeprecated::prepend_and_or_where( $starts_with, $where );
3240
  }
 
 
 
 
 
 
 
 
 
 
 
3241
  }
11
  /**
12
  * @since 2.0
13
  */
14
+ public static $plug_version = '5.0.13';
15
 
16
  /**
17
  * @since 1.07.02
169
  * @since 4.0
170
  */
171
  public static function show_logo( $atts = array() ) {
172
+ echo self::kses( self::svg_logo( $atts ), 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
173
  }
174
 
175
  /**
192
  $icon = '<div style="height:39px"></div>';
193
  }
194
  }
195
+ echo self::kses( $icon, 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
196
  }
197
 
198
  /**
410
  $param = $params[0];
411
  }
412
 
413
+ if ( $src === 'get' ) {
414
+ $value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
415
+ if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
 
416
  // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
417
  $value = htmlspecialchars_decode( wp_unslash( $_GET[ $param ] ) );
418
  }
496
  $value = $args['default'];
497
  if ( $args['type'] == 'get' ) {
498
  if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
499
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
500
  $value = wp_unslash( $_GET[ $args['param'] ] );
501
  }
502
  } elseif ( $args['type'] == 'post' ) {
503
+ if ( isset( $_POST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
504
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
505
  $value = wp_unslash( $_POST[ $args['param'] ] );
506
  if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
507
  self::unserialize_or_decode( $value );
508
  }
509
  }
510
  } else {
511
+ if ( isset( $_REQUEST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
512
  // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
513
  $value = wp_unslash( $_REQUEST[ $args['param'] ] );
514
  }
644
  return wp_kses( $value, $allowed_html );
645
  }
646
 
647
+ /**
648
+ * The regular kses function strips [button_action] from submit button HTML.
649
+ *
650
+ * @since 5.0.13
651
+ *
652
+ * @param string $html
653
+ * @return string
654
+ */
655
+ public static function kses_submit_button( $html ) {
656
+ $included_button_action = false !== strpos( $html, '[button_action]' );
657
+ $included_back_hook = false !== strpos( $html, '[back_hook]' );
658
+ $included_draft_hook = false !== strpos( $html, '[draft_hook]' );
659
+ add_filter( 'safe_style_css', 'FrmAppHelper::allow_visibility_style' );
660
+ add_filter( 'frm_striphtml_allowed_tags', 'FrmAppHelper::add_allowed_submit_button_tags' );
661
+ $html = self::kses( $html, 'all' );
662
+ remove_filter( 'safe_style_css', 'FrmAppHelper::allow_visibility_style' );
663
+ remove_filter( 'frm_striphtml_allowed_tags', 'FrmAppHelper::add_allowed_submit_button_tags' );
664
+ if ( $included_button_action ) {
665
+ if ( false !== strpos( $html, '<input type="submit"' ) ) {
666
+ $pattern = '/(<input type="submit")([^>]*)(\/>)/';
667
+ $html = preg_replace( $pattern, '$1$2[button_action] $3', $html, 1 );
668
+ } else {
669
+ $pattern = '/(<button)(.*)(class=")(.*)(frm_button_submit)(.*)(")(.*)([^>]+)(>)/';
670
+ $html = preg_replace( $pattern, '$1$2$3$4$5$6$7 [button_action]$8$9$10', $html, 1 );
671
+ }
672
+ }
673
+ if ( $included_back_hook ) {
674
+ $html = str_replace( 'class="frm_prev_page"', 'class="frm_prev_page" [back_hook]', $html );
675
+ }
676
+ if ( $included_draft_hook ) {
677
+ $html = str_replace( 'class="frm_save_draft"', 'class="frm_save_draft" [draft_hook]', $html );
678
+ }
679
+ return $html;
680
+ }
681
+
682
+ /**
683
+ * @since 5.0.13
684
+ *
685
+ * @param array $allowed_attr
686
+ * @return array
687
+ */
688
+ public static function allow_visibility_style( $allowed_attr ) {
689
+ $allowed_attr[] = 'visibility';
690
+ return $allowed_attr;
691
+ }
692
+
693
+ /**
694
+ * @since 5.0.13
695
+ *
696
+ * @param array $allowed_html
697
+ * @return array
698
+ */
699
+ public static function add_allowed_submit_button_tags( $allowed_html ) {
700
+ $allowed_html['input'] = array(
701
+ 'type' => true,
702
+ 'value' => true,
703
+ 'formnovalidate' => true,
704
+ 'name' => true,
705
+ 'class' => true,
706
+ );
707
+ $allowed_html['button']['formnovalidate'] = true;
708
+ $allowed_html['button']['name'] = true;
709
+ $allowed_html['img']['style'] = true;
710
+ return $allowed_html;
711
+ }
712
+
713
  /**
714
  * @since 2.05.03
715
  */
737
  );
738
 
739
  return array(
740
+ 'a' => array(
741
+ 'class' => true,
742
+ 'href' => true,
743
+ 'id' => true,
744
+ 'rel' => true,
745
+ 'target' => true,
746
+ 'title' => true,
747
+ 'tabindex' => true,
748
  ),
749
  'abbr' => array(
750
  'title' => true,
770
  'id' => true,
771
  'title' => true,
772
  'style' => true,
773
+ 'role' => true,
774
  ),
775
  'dl' => array(),
776
  'dt' => array(),
835
  'viewbox' => true,
836
  ),
837
  'svg' => array(
838
+ 'class' => true,
839
+ 'id' => true,
840
+ 'xmlns' => true,
841
+ 'viewbox' => true,
842
+ 'width' => true,
843
+ 'height' => true,
844
+ 'style' => true,
845
+ 'fill' => true,
846
+ 'aria-label' => true,
847
+ 'aria-hidden' => true,
848
  ),
849
  'use' => array(
850
+ 'href' => true,
851
  'xlink:href' => true,
852
  ),
853
  'ul' => $allow_class,
930
  $icon = explode( ' ', $icon );
931
  $icon = reset( $icon );
932
  }
933
+ $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
934
  <use xlink:href="#' . esc_attr( $icon ) . '" />
935
  </svg>';
936
  }
937
 
938
  if ( $echo ) {
939
+ echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
940
  } else {
941
  return $icon;
942
  }
943
  }
944
 
945
+ /**
946
+ * Run kses for icons. It needs to add a few filters first in order to preserve some custom style values.
947
+ *
948
+ * @since 5.0.13
949
+ *
950
+ * @param string $icon
951
+ * @return string
952
+ */
953
+ public static function kses_icon( $icon ) {
954
+ add_filter( 'safe_style_css', 'FrmAppHelper::allow_vars_in_styles' );
955
+ add_filter( 'safecss_filter_attr_allow_css', 'FrmAppHelper::allow_style', 10, 2 );
956
+ $icon = self::kses( $icon, 'all' );
957
+ remove_filter( 'safe_style_css', 'FrmAppHelper::allow_vars_in_styles' );
958
+ remove_filter( 'safecss_filter_attr_allow_css', 'FrmAppHelper::allow_style' );
959
+ return $icon;
960
+ }
961
+
962
+ /**
963
+ * @since 5.0.13
964
+ *
965
+ * @param array $allowed_attr
966
+ * @return array
967
+ */
968
+ public static function allow_vars_in_styles( $allowed_attr ) {
969
+ $allowed_attr[] = '--primary-hover';
970
+ return $allowed_attr;
971
+ }
972
+
973
+ /**
974
+ * @since 5.0.13
975
+ *
976
+ * @param bool $allow_css
977
+ * @param string $css_string
978
+ */
979
+ public static function allow_style( $allow_css, $css_string ) {
980
+ if ( ! $allow_css && 0 === strpos( $css_string, '--primary-hover:' ) ) {
981
+ $split = explode( ':', $css_string, 2 );
982
+ $allow_css = 2 === count( $split ) && self::is_a_valid_color( $split[1] );
983
+ }
984
+ return $allow_css;
985
+ }
986
+
987
+ /**
988
+ * @since 5.0.13
989
+ *
990
+ * @param string $value
991
+ * @return bool
992
+ */
993
+ private static function is_a_valid_color( $value ) {
994
+ $match = 0;
995
+ if ( 0 === strpos( $value, 'rgba(' ) ) {
996
+ $match = preg_match( '/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*(?:\.\d+)?)\)$/', $value );
997
+ } elseif ( 0 === strpos( $value, 'rgb(' ) ) {
998
+ $match = preg_match( '/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/', $value );
999
+ } elseif ( 0 === strpos( $value, '#' ) ) {
1000
+ $match = preg_match( '/^#([a-f0-9]{6}|[a-f0-9]{3})\b$/', $value );
1001
+ }
1002
+ return (bool) $match;
1003
+ }
1004
+
1005
  /**
1006
  * Include svg images.
1007
  *
1015
  * Convert an associative array to HTML values.
1016
  *
1017
  * @since 4.0.02
1018
+ * @since 5.0.13 added $echo parameter.
1019
+ *
1020
  * @param array $atts
1021
+ * @param bool $echo
1022
+ * @return string|void
1023
+ */
1024
+ public static function array_to_html_params( $atts, $echo = false ) {
1025
+ $callback = function() use ( $atts ) {
1026
+ if ( $atts ) {
1027
+ foreach ( $atts as $key => $value ) {
1028
+ echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1029
+ }
1030
  }
1031
+ };
1032
+ return self::clip( $callback, $echo );
1033
+ }
1034
+
1035
+ /**
1036
+ * Call an echo function and either echo it or return the result as a string.
1037
+ *
1038
+ * @since 5.0.13
1039
+ *
1040
+ * @param Closure $echo_function
1041
+ * @param bool $echo
1042
+ * @return string|void
1043
+ */
1044
+ public static function clip( $echo_function, $echo = false ) {
1045
+ if ( ! $echo ) {
1046
+ ob_start();
1047
+ }
1048
+
1049
+ $echo_function();
1050
+
1051
+ if ( ! $echo ) {
1052
+ $return = ob_get_contents();
1053
+ ob_end_clean();
1054
+ return $return;
1055
  }
 
1056
  }
1057
 
1058
  /**
1697
  return $val;
1698
  }
1699
 
 
 
 
 
 
 
 
 
 
 
 
1700
  /**
1701
  * @param string $handle
1702
  */
1719
  return $ver;
1720
  }
1721
 
1722
+ /**
1723
+ * @since 5.0.13 added $echo param.
1724
+ *
1725
+ * @param string $url
1726
+ * @param bool $echo
1727
+ * @return string|void
1728
+ */
1729
+ public static function js_redirect( $url, $echo = false ) {
1730
+ $callback = function() use ( $url ) {
1731
+ echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1732
+ };
1733
+ return self::clip( $callback, $echo );
1734
  }
1735
 
1736
  public static function get_user_id_param( $user_id ) {
1888
  }
1889
 
1890
  if ( empty( $post_values ) ) {
1891
+ $post_values = wp_unslash( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1892
  }
1893
 
1894
  $values = array(
1908
 
1909
  self::prepare_field_arrays( $fields, $record, $values, array_merge( $args, compact( 'default', 'post_values' ) ) );
1910
 
1911
+ if ( $table === 'entries' ) {
1912
  $values = FrmEntriesHelper::setup_edit_vars( $values, $record );
1913
+ } elseif ( $table === 'forms' ) {
1914
  $values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
1915
  }
1916
 
2719
  'updating' => __( 'Please wait while your site updates.', 'formidable' ),
2720
  'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
2721
  'private_label' => __( 'Private', 'formidable' ),
2722
+ 'jquery_ui_url' => '',
2723
  'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
2724
  'no_licenses' => __( 'No new licenses were found', 'formidable' ),
2725
  'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3138
  * @return bool true if the current user is allowed to save unfiltered HTML.
3139
  */
3140
  public static function allow_unfiltered_html() {
3141
+ if ( self::should_never_allow_unfiltered_html() ) {
3142
  return false;
3143
  }
3144
  return current_user_can( 'unfiltered_html' );
3145
  }
3146
 
3147
+ /**
3148
+ * @since 5.0.13
3149
+ *
3150
+ * @return bool
3151
+ */
3152
+ public static function should_never_allow_unfiltered_html() {
3153
+ if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
3154
+ return true;
3155
+ }
3156
+
3157
+ /**
3158
+ * Formidable will check DISALLOW_UNFILTERED_HTML to determine if some form HTML should be filtered or not.
3159
+ * In many cases, scripts are added intentionally to forms and will not be stripped if DISALLOW_UNFILTERED_HTML is not set.
3160
+ * It is also possible to filter Formidable without defining DISALLOW_UNFILTERED_HTML, with add_filter( 'frm_disallow_unfiltered_html', '__return_true' );
3161
+ *
3162
+ * @since 5.0.13
3163
+ */
3164
+ return apply_filters( 'frm_disallow_unfiltered_html', false );
3165
+ }
3166
+
3167
  /**
3168
  * @since 5.0.07
3169
  *
3187
  return $values;
3188
  }
3189
 
3190
+ /**
3191
+ * Some back end fields allow privleged users to add scripts.
3192
+ * A site that uses the DISALLOW_UNFILTERED_HTML always remove scripts on echo.
3193
+ *
3194
+ * @since 5.0.13
3195
+ *
3196
+ * @param string $value
3197
+ * @param array|string $allowed 'all' for everything included as defaults
3198
+ * @return string
3199
+ */
3200
+ public static function maybe_kses( $value, $allowed = 'all' ) {
3201
+ if ( self::should_never_allow_unfiltered_html() ) {
3202
+ $value = self::kses( $value, $allowed );
3203
+ }
3204
+ return $value;
3205
+ }
3206
+
3207
  /**
3208
  * @since 4.07
3209
  * @deprecated 4.09.01
3430
  public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
3431
  return FrmDeprecated::prepend_and_or_where( $starts_with, $where );
3432
  }
3433
+
3434
+ /**
3435
+ * @since 2.0
3436
+ * @deprecated 5.0.13
3437
+ *
3438
+ * @return string The base Google APIS url for the current version of jQuery UI
3439
+ */
3440
+ public static function jquery_ui_base_url() {
3441
+ _deprecated_function( __FUNCTION__, '5.0.13', 'FrmProAppHelper::jquery_ui_base_url' );
3442
+ return is_callable( 'FrmProAppHelper::jquery_ui_base_url' ) ? FrmProAppHelper::jquery_ui_base_url() : '';
3443
+ }
3444
  }
classes/helpers/FrmCSVExportHelper.php CHANGED
@@ -71,7 +71,7 @@ class FrmCSVExportHelper {
71
  self::get_csv_format();
72
  self::$charset = get_option( 'blog_charset' );
73
 
74
- $col_sep = ( isset( $_POST['csv_col_sep'] ) && ! empty( $_POST['csv_col_sep'] ) ) ? sanitize_text_field( wp_unslash( $_POST['csv_col_sep'] ) ) : self::$column_separator;
75
 
76
  self::$column_separator = apply_filters( 'frm_csv_column_sep', $col_sep );
77
  }
@@ -505,7 +505,7 @@ class FrmCSVExportHelper {
505
  $val = str_replace( array( "\r\n", "\r", "\n" ), self::$line_break, $val );
506
  }
507
 
508
- echo $sep . '"' . $val . '"'; // WPCS: XSS ok.
509
  $sep = self::$column_separator;
510
 
511
  unset( $k, $row );
71
  self::get_csv_format();
72
  self::$charset = get_option( 'blog_charset' );
73
 
74
+ $col_sep = ( isset( $_POST['csv_col_sep'] ) && ! empty( $_POST['csv_col_sep'] ) ) ? sanitize_text_field( wp_unslash( $_POST['csv_col_sep'] ) ) : self::$column_separator; // phpcs:ignore WordPress.Security.NonceVerification.Missing
75
 
76
  self::$column_separator = apply_filters( 'frm_csv_column_sep', $col_sep );
77
  }
505
  $val = str_replace( array( "\r\n", "\r", "\n" ), self::$line_break, $val );
506
  }
507
 
508
+ echo $sep . '"' . $val . '"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
509
  $sep = self::$column_separator;
510
 
511
  unset( $k, $row );
classes/helpers/FrmEntriesHelper.php CHANGED
@@ -114,13 +114,13 @@ class FrmEntriesHelper {
114
  */
115
  public static function value_is_posted( $field, $args ) {
116
  $value_is_posted = false;
117
- if ( $_POST ) {
118
  $repeating = isset( $args['repeating'] ) && $args['repeating'];
119
  if ( $repeating ) {
120
- if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] ) ) {
121
  $value_is_posted = true;
122
  }
123
- } elseif ( isset( $_POST['item_meta'][ $field->id ] ) ) {
124
  $value_is_posted = true;
125
  }
126
  }
@@ -322,30 +322,27 @@ class FrmEntriesHelper {
322
  * @since 4.01
323
  */
324
  private static function set_parent_field_posted_value( $field, $value, $args ) {
325
- if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ] ) &&
326
- is_array( $_POST['item_meta'][ $args['parent_field_id'] ] ) ) {
327
-
328
- if ( ! isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) ||
329
- ! is_array( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) ) {
330
- $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array();
331
  }
332
  } else {
333
  // All of the section was probably removed.
334
- $_POST['item_meta'][ $args['parent_field_id'] ] = array();
335
- $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array();
336
  }
337
 
338
- $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] = $value;
339
  }
340
 
341
  public static function get_posted_value( $field, &$value, $args ) {
342
  if ( is_array( $field ) ) {
343
  $field_id = $field['id'];
344
  $field_obj = FrmFieldFactory::get_field_object( $field['id'] );
345
- } else if ( is_object( $field ) ) {
346
  $field_id = $field->id;
347
  $field_obj = FrmFieldFactory::get_field_object( $field );
348
- } else if ( is_numeric( $field ) ) {
349
  $field_id = $field;
350
  $field_obj = FrmFieldFactory::get_field_object( $field );
351
  } else {
@@ -365,11 +362,9 @@ class FrmEntriesHelper {
365
  private static function get_posted_meta( $field_id, $args ) {
366
  if ( empty( $args['parent_field_id'] ) ) {
367
  // Sanitizing is done next.
368
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
369
- $value = isset( $_POST['item_meta'][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $field_id ] ) : '';
370
  } else {
371
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
372
- $value = isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) : '';
373
  }
374
  return $value;
375
  }
@@ -400,15 +395,14 @@ class FrmEntriesHelper {
400
  self::set_other_repeating_vals( $field, $value, $args );
401
 
402
  // Check if there are any posted "Other" values.
403
- if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta']['other'][ $field->id ] ) ) {
404
 
405
  // Save original value.
406
  $args['temp_value'] = $value;
407
  $args['other'] = true;
408
 
409
  // Sanitizing is done next.
410
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
411
- $other_vals = wp_unslash( $_POST['item_meta']['other'][ $field->id ] );
412
  FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
413
 
414
  // Set the validation value now
@@ -431,13 +425,12 @@ class FrmEntriesHelper {
431
  }
432
 
433
  // Check if there are any other posted "other" values for this field.
434
- if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] ) ) {
435
  // Save original value
436
  $args['temp_value'] = $value;
437
  $args['other'] = true;
438
 
439
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
440
- $other_vals = wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] );
441
  FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
442
 
443
  // Set the validation value now.
114
  */
115
  public static function value_is_posted( $field, $args ) {
116
  $value_is_posted = false;
117
+ if ( $_POST ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
118
  $repeating = isset( $args['repeating'] ) && $args['repeating'];
119
  if ( $repeating ) {
120
+ if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
121
  $value_is_posted = true;
122
  }
123
+ } elseif ( isset( $_POST['item_meta'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
124
  $value_is_posted = true;
125
  }
126
  }
322
  * @since 4.01
323
  */
324
  private static function set_parent_field_posted_value( $field, $value, $args ) {
325
+ if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ] ) && is_array( $_POST['item_meta'][ $args['parent_field_id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
326
+ if ( ! isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) || ! is_array( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
327
+ $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
 
 
 
328
  }
329
  } else {
330
  // All of the section was probably removed.
331
+ $_POST['item_meta'][ $args['parent_field_id'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
332
+ $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
333
  }
334
 
335
+ $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] = $value; // phpcs:ignore WordPress.Security.NonceVerification.Missing
336
  }
337
 
338
  public static function get_posted_value( $field, &$value, $args ) {
339
  if ( is_array( $field ) ) {
340
  $field_id = $field['id'];
341
  $field_obj = FrmFieldFactory::get_field_object( $field['id'] );
342
+ } elseif ( is_object( $field ) ) {
343
  $field_id = $field->id;
344
  $field_obj = FrmFieldFactory::get_field_object( $field );
345
+ } elseif ( is_numeric( $field ) ) {
346
  $field_id = $field;
347
  $field_obj = FrmFieldFactory::get_field_object( $field );
348
  } else {
362
  private static function get_posted_meta( $field_id, $args ) {
363
  if ( empty( $args['parent_field_id'] ) ) {
364
  // Sanitizing is done next.
365
+ $value = isset( $_POST['item_meta'][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $field_id ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
366
  } else {
367
+ $value = isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
368
  }
369
  return $value;
370
  }
395
  self::set_other_repeating_vals( $field, $value, $args );
396
 
397
  // Check if there are any posted "Other" values.
398
+ if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta']['other'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
399
 
400
  // Save original value.
401
  $args['temp_value'] = $value;
402
  $args['other'] = true;
403
 
404
  // Sanitizing is done next.
405
+ $other_vals = wp_unslash( $_POST['item_meta']['other'][ $field->id ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
406
  FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
407
 
408
  // Set the validation value now
425
  }
426
 
427
  // Check if there are any other posted "other" values for this field.
428
+ if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
429
  // Save original value
430
  $args['temp_value'] = $value;
431
  $args['other'] = true;
432
 
433
+ $other_vals = wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
434
  FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
435
 
436
  // Set the validation value now.
classes/helpers/FrmEntriesListHelper.php CHANGED
@@ -140,13 +140,13 @@ class FrmEntriesListHelper extends FrmListHelper {
140
 
141
  protected function extra_tablenav( $which ) {
142
  $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
143
- if ( $which == 'top' && empty( $form_id ) ) {
144
  echo '<div class="alignleft actions">';
145
 
146
  // Override the referrer to prevent it from being used for the screen options.
147
  echo '<input type="hidden" name="_wp_http_referer" value="" />';
148
 
149
- echo FrmFormsHelper::forms_dropdown( 'form', $form_id, array( 'blank' => __( 'View all forms', 'formidable' ) ) ); // WPCS: XSS ok.
150
  submit_button( __( 'Filter', 'formidable' ), 'filter_action action', '', false, array( 'id' => 'post-query-submit' ) );
151
  echo '</div>';
152
  }
140
 
141
  protected function extra_tablenav( $which ) {
142
  $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
143
+ if ( $which === 'top' && ! $form_id ) {
144
  echo '<div class="alignleft actions">';
145
 
146
  // Override the referrer to prevent it from being used for the screen options.
147
  echo '<input type="hidden" name="_wp_http_referer" value="" />';
148
 
149
+ FrmFormsHelper::forms_dropdown( 'form', $form_id, array( 'blank' => __( 'View all forms', 'formidable' ) ) );
150
  submit_button( __( 'Filter', 'formidable' ), 'filter_action action', '', false, array( 'id' => 'post-query-submit' ) );
151
  echo '</div>';
152
  }
classes/helpers/FrmFieldsHelper.php CHANGED
@@ -124,7 +124,7 @@ class FrmFieldsHelper {
124
  * @param array $values
125
  */
126
  private static function fill_default_field_opts( $field, array &$values ) {
127
- $check_post = FrmAppHelper::is_admin_page() && $_POST && isset( $_POST['field_options'] );
128
 
129
  $defaults = self::get_default_field_options_from_field( $field, $values );
130
  if ( ! $check_post ) {
@@ -180,20 +180,18 @@ class FrmFieldsHelper {
180
  * @param mixed $value
181
  */
182
  private static function get_posted_field_setting( $setting, &$value ) {
183
- if ( ! isset( $_POST['field_options'][ $setting ] ) ) {
184
  return;
185
  }
186
 
187
  if ( strpos( $setting, 'html' ) !== false ) {
188
  // Strip slashes from HTML but not regex or script tags.
189
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
190
- $value = wp_unslash( $_POST['field_options'][ $setting ] );
191
  } elseif ( strpos( $setting, 'format_' ) === 0 ) {
192
  // TODO: Remove stripslashes on output, and use on input only.
193
- $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // WPCS: sanitization ok.
194
  } else {
195
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
196
- $value = wp_unslash( $_POST['field_options'][ $setting ] );
197
  FrmAppHelper::sanitize_value( 'wp_kses_post', $value );
198
  }
199
  }
@@ -842,9 +840,9 @@ class FrmFieldsHelper {
842
  return null;
843
  }
844
 
845
- if ( isset( $atts['show'] ) && $atts['show'] == 'field_label' ) {
846
  $replace_with = $field->name;
847
- } elseif ( isset( $atts['show'] ) && $atts['show'] == 'description' ) {
848
  $replace_with = $field->description;
849
  } else {
850
  $replace_with = FrmEntryMeta::get_meta_value( $atts['entry'], $field->id );
@@ -1086,29 +1084,31 @@ class FrmFieldsHelper {
1086
 
1087
  // Check posted vals before checking saved values
1088
  // For fields inside repeating sections - note, don't check if $pointer is true because it will often be zero
1089
- if ( $parent && isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ) {
1090
  if ( FrmField::is_field_with_multiple_values( $field ) ) {
 
1091
  $other_val = isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1092
  } else {
1093
- $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) );
1094
  }
1095
 
1096
  return $other_val;
1097
 
1098
- } elseif ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) {
1099
  // For normal fields
1100
 
1101
  if ( FrmField::is_field_with_multiple_values( $field ) ) {
 
1102
  $other_val = isset( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1103
  } else {
1104
- $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ] ) );
1105
  }
1106
 
1107
  return $other_val;
1108
  }
1109
 
1110
  // For checkboxes
1111
- if ( $field['type'] == 'checkbox' && is_array( $field['value'] ) ) {
1112
  // Check if there is an "other" val in saved value and make sure the
1113
  // "other" val is not equal to the Other checkbox option
1114
  if ( isset( $field['value'][ $opt_key ] ) && $field['options'][ $opt_key ] != $field['value'][ $opt_key ] ) {
@@ -1304,10 +1304,14 @@ class FrmFieldsHelper {
1304
  $replace_with[] = '[if ' . $new . ' ';
1305
  $replace[] = '[/if ' . $old . ']';
1306
  $replace_with[] = '[/if ' . $new . ']';
 
 
1307
  $replace[] = '[foreach ' . $old . ']';
1308
  $replace_with[] = '[foreach ' . $new . ']';
1309
  $replace[] = '[/foreach ' . $old . ']';
1310
  $replace_with[] = '[/foreach ' . $new . ']';
 
 
1311
  $replace[] = '[' . $old . ']';
1312
  $replace_with[] = '[' . $new . ']';
1313
  $replace[] = '[' . $old . ' ';
@@ -1854,7 +1858,7 @@ class FrmFieldsHelper {
1854
  if ( $run_filter ) {
1855
  $field_label = apply_filters( 'frmpro_field_links', $field_label, $args['id'], $field_key );
1856
  }
1857
- echo FrmAppHelper::kses( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) ); // WPCS: XSS ok.
1858
  ?>
1859
  </li>
1860
  <?php
124
  * @param array $values
125
  */
126
  private static function fill_default_field_opts( $field, array &$values ) {
127
+ $check_post = FrmAppHelper::is_admin_page() && $_POST && isset( $_POST['field_options'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
128
 
129
  $defaults = self::get_default_field_options_from_field( $field, $values );
130
  if ( ! $check_post ) {
180
  * @param mixed $value
181
  */
182
  private static function get_posted_field_setting( $setting, &$value ) {
183
+ if ( ! isset( $_POST['field_options'][ $setting ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
184
  return;
185
  }
186
 
187
  if ( strpos( $setting, 'html' ) !== false ) {
188
  // Strip slashes from HTML but not regex or script tags.
189
+ $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
190
  } elseif ( strpos( $setting, 'format_' ) === 0 ) {
191
  // TODO: Remove stripslashes on output, and use on input only.
192
+ $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Missing
193
  } else {
194
+ $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
195
  FrmAppHelper::sanitize_value( 'wp_kses_post', $value );
196
  }
197
  }
840
  return null;
841
  }
842
 
843
+ if ( isset( $atts['show'] ) && $atts['show'] === 'field_label' ) {
844
  $replace_with = $field->name;
845
+ } elseif ( isset( $atts['show'] ) && $atts['show'] === 'description' ) {
846
  $replace_with = $field->description;
847
  } else {
848
  $replace_with = FrmEntryMeta::get_meta_value( $atts['entry'], $field->id );
1084
 
1085
  // Check posted vals before checking saved values
1086
  // For fields inside repeating sections - note, don't check if $pointer is true because it will often be zero
1087
+ if ( $parent && isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1088
  if ( FrmField::is_field_with_multiple_values( $field ) ) {
1089
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
1090
  $other_val = isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1091
  } else {
1092
+ $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1093
  }
1094
 
1095
  return $other_val;
1096
 
1097
+ } elseif ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1098
  // For normal fields
1099
 
1100
  if ( FrmField::is_field_with_multiple_values( $field ) ) {
1101
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
1102
  $other_val = isset( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1103
  } else {
1104
+ $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1105
  }
1106
 
1107
  return $other_val;
1108
  }
1109
 
1110
  // For checkboxes
1111
+ if ( $field['type'] === 'checkbox' && is_array( $field['value'] ) ) {
1112
  // Check if there is an "other" val in saved value and make sure the
1113
  // "other" val is not equal to the Other checkbox option
1114
  if ( isset( $field['value'][ $opt_key ] ) && $field['options'][ $opt_key ] != $field['value'][ $opt_key ] ) {
1304
  $replace_with[] = '[if ' . $new . ' ';
1305
  $replace[] = '[/if ' . $old . ']';
1306
  $replace_with[] = '[/if ' . $new . ']';
1307
+ $replace[] = '[\/if ' . $old . ']';
1308
+ $replace_with[] = '[\/if ' . $new . ']';
1309
  $replace[] = '[foreach ' . $old . ']';
1310
  $replace_with[] = '[foreach ' . $new . ']';
1311
  $replace[] = '[/foreach ' . $old . ']';
1312
  $replace_with[] = '[/foreach ' . $new . ']';
1313
+ $replace[] = '[\/foreach ' . $old . ']';
1314
+ $replace_with[] = '[\/foreach ' . $new . ']';
1315
  $replace[] = '[' . $old . ']';
1316
  $replace_with[] = '[' . $new . ']';
1317
  $replace[] = '[' . $old . ' ';
1858
  if ( $run_filter ) {
1859
  $field_label = apply_filters( 'frmpro_field_links', $field_label, $args['id'], $field_key );
1860
  }
1861
+ echo FrmAppHelper::kses( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1862
  ?>
1863
  </li>
1864
  <?php
classes/helpers/FrmFormsHelper.php CHANGED
@@ -48,7 +48,7 @@ class FrmFormsHelper {
48
  ?>
49
  <select name="<?php echo esc_attr( $field_name ); ?>"
50
  id="<?php echo esc_attr( $args['field_id'] ); ?>"
51
- <?php echo wp_strip_all_tags( implode( ' ', $add_html ) ); // WPCS: XSS ok. ?>>
52
  <?php if ( $args['blank'] ) { ?>
53
  <option value=""><?php echo ( $args['blank'] == 1 ) ? ' ' : '- ' . esc_attr( $args['blank'] ) . ' -'; ?></option>
54
  <?php } ?>
@@ -268,7 +268,7 @@ class FrmFormsHelper {
268
  $post_values = $values;
269
  } else {
270
  $values = array();
271
- $post_values = isset( $_POST ) ? $_POST : array();
272
  }
273
 
274
  $defaults = array(
@@ -313,7 +313,7 @@ class FrmFormsHelper {
313
  */
314
  public static function setup_edit_vars( $values, $record, $post_values = array() ) {
315
  if ( empty( $post_values ) ) {
316
- $post_values = wp_unslash( $_POST );
317
  }
318
 
319
  $values['form_key'] = isset( $post_values['form_key'] ) ? $post_values['form_key'] : $record->form_key;
@@ -427,15 +427,17 @@ BEFORE_HTML;
427
  public static function get_custom_submit( $html, $form, $submit, $form_action, $values ) {
428
  $button = self::replace_shortcodes( $html, $form, $submit, $form_action, $values );
429
  if ( ! strpos( $button, '[button_action]' ) ) {
430
- echo $button; // WPCS: XSS ok.
431
-
432
  return;
433
  }
434
 
435
  /**
436
  * @since 5.0.06
437
  */
438
- $button = apply_filters( 'frm_submit_button_html', $button, compact( 'form' ) );
 
 
 
439
  $button_parts = explode( '[button_action]', $button );
440
 
441
  $classes = apply_filters( 'frm_submit_button_class', array(), $form );
@@ -449,9 +451,9 @@ BEFORE_HTML;
449
  }
450
  }
451
 
452
- echo $button_parts[0]; // WPCS: XSS ok.
453
  do_action( 'frm_submit_button_action', $form, $form_action );
454
- echo $button_parts[1]; // WPCS: XSS ok.
455
  }
456
 
457
  /**
@@ -711,11 +713,11 @@ BEFORE_HTML;
711
  'entry_key' => true,
712
  );
713
  foreach ( $codes as $code => $show ) {
714
- if ( $code == 'form_name' ) {
715
  $replace_with = $form->name;
716
- } elseif ( $code == 'form_description' ) {
717
  $replace_with = FrmAppHelper::use_wpautop( $form->description );
718
- } elseif ( $code == 'entry_key' && isset( $_GET ) && isset( $_GET['entry'] ) ) {
719
  $replace_with = FrmAppHelper::simple_get( 'entry' );
720
  } else {
721
  $replace_with = '';
48
  ?>
49
  <select name="<?php echo esc_attr( $field_name ); ?>"
50
  id="<?php echo esc_attr( $args['field_id'] ); ?>"
51
+ <?php echo wp_strip_all_tags( implode( ' ', $add_html ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
52
  <?php if ( $args['blank'] ) { ?>
53
  <option value=""><?php echo ( $args['blank'] == 1 ) ? ' ' : '- ' . esc_attr( $args['blank'] ) . ' -'; ?></option>
54
  <?php } ?>
268
  $post_values = $values;
269
  } else {
270
  $values = array();
271
+ $post_values = isset( $_POST ) ? $_POST : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
272
  }
273
 
274
  $defaults = array(
313
  */
314
  public static function setup_edit_vars( $values, $record, $post_values = array() ) {
315
  if ( empty( $post_values ) ) {
316
+ $post_values = wp_unslash( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
317
  }
318
 
319
  $values['form_key'] = isset( $post_values['form_key'] ) ? $post_values['form_key'] : $record->form_key;
427
  public static function get_custom_submit( $html, $form, $submit, $form_action, $values ) {
428
  $button = self::replace_shortcodes( $html, $form, $submit, $form_action, $values );
429
  if ( ! strpos( $button, '[button_action]' ) ) {
430
+ echo FrmAppHelper::maybe_kses( $button ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
 
431
  return;
432
  }
433
 
434
  /**
435
  * @since 5.0.06
436
  */
437
+ $button = apply_filters( 'frm_submit_button_html', $button, compact( 'form' ) );
438
+ if ( FrmAppHelper::should_never_allow_unfiltered_html() ) {
439
+ $button = FrmAppHelper::kses_submit_button( $button );
440
+ }
441
  $button_parts = explode( '[button_action]', $button );
442
 
443
  $classes = apply_filters( 'frm_submit_button_class', array(), $form );
451
  }
452
  }
453
 
454
+ echo $button_parts[0]; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
455
  do_action( 'frm_submit_button_action', $form, $form_action );
456
+ echo $button_parts[1]; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
457
  }
458
 
459
  /**
713
  'entry_key' => true,
714
  );
715
  foreach ( $codes as $code => $show ) {
716
+ if ( $code === 'form_name' ) {
717
  $replace_with = $form->name;
718
+ } elseif ( $code === 'form_description' ) {
719
  $replace_with = FrmAppHelper::use_wpautop( $form->description );
720
+ } elseif ( $code === 'entry_key' && isset( $_GET ) && isset( $_GET['entry'] ) ) {
721
  $replace_with = FrmAppHelper::simple_get( 'entry' );
722
  } else {
723
  $replace_with = '';
classes/helpers/FrmListHelper.php CHANGED
@@ -156,7 +156,7 @@ class FrmListHelper {
156
 
157
  public function display_rows() {
158
  foreach ( $this->items as $item ) {
159
- echo "\n\t", $this->single_row( $item ); // WPCS: XSS ok.
160
  }
161
  }
162
 
@@ -331,7 +331,7 @@ class FrmListHelper {
331
  foreach ( $views as $class => $view ) {
332
  $views[ $class ] = "\t" . '<li class="' . esc_attr( $class ) . '">' . $view;
333
  }
334
- echo implode( " |</li>\n", $views ) . "</li>\n"; // WPCS: XSS ok.
335
  echo '</ul>';
336
  }
337
 
@@ -393,7 +393,7 @@ class FrmListHelper {
393
  foreach ( $this->_actions as $name => $title ) {
394
  $class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
395
 
396
- echo "\t<option value='" . esc_attr( $name ) . "'$class>" . esc_html( $title ) . "</option>\n"; // WPCS: XSS ok.
397
  }
398
 
399
  echo "</select>\n";
@@ -665,7 +665,7 @@ class FrmListHelper {
665
  }
666
  $this->_pagination = "<div class='tablenav-pages" . esc_attr( $page_class ) . "'>$output</div>";
667
 
668
- echo $this->_pagination; // WPCS: XSS ok.
669
  }
670
 
671
  private function disabled_pages( $total_pages ) {
@@ -969,7 +969,7 @@ class FrmListHelper {
969
  // Hide the labels but show the border.
970
  $column_display_name = '';
971
  }
972
- echo "<$tag $scope $id $class>$column_display_name</$tag>"; // WPCS: XSS ok.
973
  }
974
  }
975
 
@@ -993,7 +993,7 @@ class FrmListHelper {
993
  </thead>
994
  <?php } ?>
995
 
996
- <tbody id="the-list"<?php echo( $singular ? " data-wp-lists='list:" . esc_attr( $singular ) . "'" : '' ); // WPCS: XSS ok. ?>>
997
  <?php $this->display_rows_or_placeholder(); ?>
998
  </tbody>
999
 
@@ -1030,7 +1030,7 @@ class FrmListHelper {
1030
  * @param string $which
1031
  */
1032
  protected function display_tablenav( $which ) {
1033
- if ( 'top' == $which ) {
1034
  wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
1035
  if ( ! $this->has_min_items( 1 ) ) {
1036
  // Don't show bulk actions if no items.
@@ -1137,7 +1137,7 @@ class FrmListHelper {
1137
  if ( 'cb' == $column_name ) {
1138
  echo '<th scope="row" class="check-column"></th>';
1139
  } elseif ( method_exists( $this, '_column_' . $column_name ) ) {
1140
- echo call_user_func( // WPCS: XSS ok.
1141
  array( $this, '_column_' . $column_name ),
1142
  $item,
1143
  $classes,
@@ -1145,13 +1145,13 @@ class FrmListHelper {
1145
  $primary
1146
  );
1147
  } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
1148
- echo "<td $attributes>"; // WPCS: XSS ok.
1149
- echo call_user_func( array( $this, 'column_' . $column_name ), $item ); // WPCS: XSS ok.
1150
- echo $this->handle_row_actions( $item, $column_name, $primary ); // WPCS: XSS ok.
1151
  echo '</td>';
1152
  } else {
1153
- echo "<td $attributes>"; // WPCS: XSS ok.
1154
- echo $this->handle_row_actions( $item, $column_name, $primary ); // WPCS: XSS ok.
1155
  echo '</td>';
1156
  }
1157
  }
156
 
157
  public function display_rows() {
158
  foreach ( $this->items as $item ) {
159
+ echo "\n\t", $this->single_row( $item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
160
  }
161
  }
162
 
331
  foreach ( $views as $class => $view ) {
332
  $views[ $class ] = "\t" . '<li class="' . esc_attr( $class ) . '">' . $view;
333
  }
334
+ echo implode( " |</li>\n", $views ) . "</li>\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
335
  echo '</ul>';
336
  }
337
 
393
  foreach ( $this->_actions as $name => $title ) {
394
  $class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
395
 
396
+ echo "\t<option value='" . esc_attr( $name ) . "'$class>" . esc_html( $title ) . "</option>\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
397
  }
398
 
399
  echo "</select>\n";
665
  }
666
  $this->_pagination = "<div class='tablenav-pages" . esc_attr( $page_class ) . "'>$output</div>";
667
 
668
+ echo $this->_pagination; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
669
  }
670
 
671
  private function disabled_pages( $total_pages ) {
969
  // Hide the labels but show the border.
970
  $column_display_name = '';
971
  }
972
+ echo "<$tag $scope $id $class>$column_display_name</$tag>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
973
  }
974
  }
975
 
993
  </thead>
994
  <?php } ?>
995
 
996
+ <tbody id="the-list"<?php echo( $singular ? " data-wp-lists='list:" . esc_attr( $singular ) . "'" : '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
997
  <?php $this->display_rows_or_placeholder(); ?>
998
  </tbody>
999
 
1030
  * @param string $which
1031
  */
1032
  protected function display_tablenav( $which ) {
1033
+ if ( 'top' === $which ) {
1034
  wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
1035
  if ( ! $this->has_min_items( 1 ) ) {
1036
  // Don't show bulk actions if no items.
1137
  if ( 'cb' == $column_name ) {
1138
  echo '<th scope="row" class="check-column"></th>';
1139
  } elseif ( method_exists( $this, '_column_' . $column_name ) ) {
1140
+ echo call_user_func( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1141
  array( $this, '_column_' . $column_name ),
1142
  $item,
1143
  $classes,
1145
  $primary
1146
  );
1147
  } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
1148
+ echo "<td $attributes>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1149
+ echo call_user_func( array( $this, 'column_' . $column_name ), $item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1150
+ echo $this->handle_row_actions( $item, $column_name, $primary ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1151
  echo '</td>';
1152
  } else {
1153
+ echo "<td $attributes>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1154
+ echo $this->handle_row_actions( $item, $column_name, $primary ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1155
  echo '</td>';
1156
  }
1157
  }
classes/helpers/FrmStylesHelper.php CHANGED
@@ -321,7 +321,7 @@ class FrmStylesHelper {
321
  }
322
  $show = empty( $defaults ) || ( $settings[ $var ] !== '' && $settings[ $var ] !== $defaults[ $var ] );
323
  if ( $show ) {
324
- echo '--' . esc_html( str_replace( '_', '-', $var ) ) . ':' . ( $var === 'font' ? FrmAppHelper::kses( $settings[ $var ] ) : esc_html( $settings[ $var ] ) ) . ';'; // WPCS: XSS ok.
325
  }
326
  }
327
  }
@@ -335,21 +335,22 @@ class FrmStylesHelper {
335
  public static function get_settings_for_output( $style ) {
336
  if ( self::previewing_style() ) {
337
 
338
- if ( isset( $_POST['frm_style_setting'] ) ) {
 
 
339
  // Sanitizing is done later.
340
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
341
- $posted = wp_unslash( $_POST['frm_style_setting'] );
342
  if ( ! is_array( $posted ) ) {
343
  $posted = json_decode( $posted, true );
344
  FrmAppHelper::format_form_data( $posted );
345
- $settings = self::sanitize_settings( $posted['frm_style_setting']['post_content'] );
346
  $style_name = sanitize_title( $posted['style_name'] );
347
  } else {
348
- $settings = self::sanitize_settings( $posted['post_content'] );
349
  $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
350
  }
351
  } else {
352
- $settings = self::sanitize_settings( wp_unslash( $_GET ) );
353
  $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
354
  }
355
 
@@ -389,27 +390,6 @@ class FrmStylesHelper {
389
  return $settings;
390
  }
391
 
392
- /**
393
- * @since 5.0.10
394
- *
395
- * @param array $settings
396
- * @return array
397
- */
398
- private static function sanitize_settings( $settings ) {
399
- $style = new FrmStyle();
400
- $defaults = $style->get_defaults();
401
- $valid_keys = array_keys( $defaults );
402
- $sanitized_settings = array();
403
- foreach ( $valid_keys as $key ) {
404
- if ( isset( $settings[ $key ] ) ) {
405
- $sanitized_settings[ $key ] = sanitize_text_field( $settings[ $key ] );
406
- } else {
407
- $sanitized_settings[ $key ] = $defaults[ $key ];
408
- }
409
- }
410
- return $sanitized_settings;
411
- }
412
-
413
  /**
414
  * @since 2.3
415
  */
@@ -488,7 +468,7 @@ class FrmStylesHelper {
488
  * @since 2.3
489
  */
490
  public static function previewing_style() {
491
- $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] );
492
 
493
  return $ajax_change || isset( $_GET['flat'] );
494
  }
321
  }
322
  $show = empty( $defaults ) || ( $settings[ $var ] !== '' && $settings[ $var ] !== $defaults[ $var ] );
323
  if ( $show ) {
324
+ echo '--' . esc_html( str_replace( '_', '-', $var ) ) . ':' . ( $var === 'font' ? FrmAppHelper::kses( $settings[ $var ] ) : esc_html( $settings[ $var ] ) ) . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
325
  }
326
  }
327
  }
335
  public static function get_settings_for_output( $style ) {
336
  if ( self::previewing_style() ) {
337
 
338
+ if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
339
+ $style = new FrmStyle();
340
+
341
  // Sanitizing is done later.
342
+ $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
 
343
  if ( ! is_array( $posted ) ) {
344
  $posted = json_decode( $posted, true );
345
  FrmAppHelper::format_form_data( $posted );
346
+ $settings = $style->sanitize_post_content( $posted['frm_style_setting']['post_content'] );
347
  $style_name = sanitize_title( $posted['style_name'] );
348
  } else {
349
+ $settings = $style->sanitize_post_content( $posted['post_content'] );
350
  $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
351
  }
352
  } else {
353
+ $settings = $style->sanitize_post_content( wp_unslash( $_GET ) );
354
  $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
355
  }
356
 
390
  return $settings;
391
  }
392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  /**
394
  * @since 2.3
395
  */
468
  * @since 2.3
469
  */
470
  public static function previewing_style() {
471
+ $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
472
 
473
  return $ajax_change || isset( $_GET['flat'] );
474
  }
classes/helpers/FrmXMLHelper.php CHANGED
@@ -23,7 +23,7 @@ class FrmXMLHelper {
23
  echo '</' . esc_html( $tag ) . '>';
24
  }
25
  } else {
26
- echo self::cdata( $opt ); // WPCS: XSS ok.
27
  }
28
  }
29
 
23
  echo '</' . esc_html( $tag ) . '>';
24
  }
25
  } else {
26
+ echo self::cdata( $opt ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
27
  }
28
  }
29
 
classes/models/FrmAddon.php CHANGED
@@ -320,7 +320,7 @@ class FrmAddon {
320
  $id = sanitize_title( $plugin['Name'] ) . '-next';
321
 
322
  echo '<tr class="plugin-update-tr active" id="' . esc_attr( $id ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message notice error inline notice-error notice-alt"><p>';
323
- echo FrmAppHelper::kses( $message, 'a' ); // WPCS: XSS ok.
324
  echo '<script type="text/javascript">var d = document.getElementById("' . esc_attr( $id ) . '").previousSibling;if ( d !== null ){ d.className = d.className + " update"; }</script>';
325
  echo '</p></div></td></tr>';
326
  }
@@ -455,7 +455,7 @@ class FrmAddon {
455
  }
456
 
457
  private function is_license_revoked() {
458
- if ( empty( $this->license ) || empty( $this->plugin_slug ) || isset( $_POST['license'] ) ) { // WPCS: CSRF ok.
459
  return;
460
  }
461
 
@@ -697,6 +697,12 @@ class FrmAddon {
697
  }
698
 
699
  public function manually_queue_update() {
700
- set_site_transient( 'update_plugins', null );
 
 
 
 
 
 
701
  }
702
  }
320
  $id = sanitize_title( $plugin['Name'] ) . '-next';
321
 
322
  echo '<tr class="plugin-update-tr active" id="' . esc_attr( $id ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message notice error inline notice-error notice-alt"><p>';
323
+ echo FrmAppHelper::kses( $message, 'a' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
324
  echo '<script type="text/javascript">var d = document.getElementById("' . esc_attr( $id ) . '").previousSibling;if ( d !== null ){ d.className = d.className + " update"; }</script>';
325
  echo '</p></div></td></tr>';
326
  }
455
  }
456
 
457
  private function is_license_revoked() {
458
+ if ( empty( $this->license ) || empty( $this->plugin_slug ) || isset( $_POST['license'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
459
  return;
460
  }
461
 
697
  }
698
 
699
  public function manually_queue_update() {
700
+ $updates = new stdClass();
701
+ $updates->last_checked = 0;
702
+ $updates->response = array();
703
+ $updates->translations = array();
704
+ $updates->no_update = array();
705
+ $updates->checked = array();
706
+ set_site_transient( 'update_plugins', $updates );
707
  }
708
  }
classes/models/FrmDb.php CHANGED
@@ -438,7 +438,7 @@ class FrmDb {
438
  if ( is_array( $where ) || empty( $where ) ) {
439
  self::get_where_clause_and_values( $where );
440
  global $wpdb;
441
- $query = $wpdb->prepare( $query . $where['where'] . ' ' . implode( ' ', $args ), $where['values'] ); // WPCS: unprepared SQL ok.
442
  } else {
443
  /**
444
  * Allow the $where to be prepared before we recieve it here.
@@ -577,7 +577,7 @@ class FrmDb {
577
  if ( is_array( $where ) ) {
578
  global $wpdb;
579
  self::get_where_clause_and_values( $where, $starts_with );
580
- $where = $wpdb->prepare( $where['where'], $where['values'] ); // WPCS: unprepared SQL ok.
581
  } else {
582
  $where = $starts_with . $where;
583
  }
@@ -657,7 +657,7 @@ class FrmDb {
657
  $results = get_posts( $query );
658
  } elseif ( 'get_associative_results' == $type ) {
659
  global $wpdb;
660
- $results = $wpdb->get_results( $query, OBJECT_K ); // WPCS: unprepared SQL ok.
661
  } else {
662
  global $wpdb;
663
  $results = $wpdb->{$type}( $query );
438
  if ( is_array( $where ) || empty( $where ) ) {
439
  self::get_where_clause_and_values( $where );
440
  global $wpdb;
441
+ $query = $wpdb->prepare( $query . $where['where'] . ' ' . implode( ' ', $args ), $where['values'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
442
  } else {
443
  /**
444
  * Allow the $where to be prepared before we recieve it here.
577
  if ( is_array( $where ) ) {
578
  global $wpdb;
579
  self::get_where_clause_and_values( $where, $starts_with );
580
+ $where = $wpdb->prepare( $where['where'], $where['values'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
581
  } else {
582
  $where = $starts_with . $where;
583
  }
657
  $results = get_posts( $query );
658
  } elseif ( 'get_associative_results' == $type ) {
659
  global $wpdb;
660
+ $results = $wpdb->get_results( $query, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
661
  } else {
662
  global $wpdb;
663
  $results = $wpdb->{$type}( $query );
classes/models/FrmEntry.php CHANGED
@@ -334,7 +334,7 @@ class FrmEntry {
334
 
335
  $query .= is_numeric( $id ) ? 'it.id=%d' : 'it.item_key=%s';
336
  $query_args = array( $id );
337
- $query = $wpdb->prepare( $query, $query_args ); // WPCS: unprepared SQL ok.
338
 
339
  if ( ! $meta ) {
340
  $entry = FrmDb::check_cache( $id . '_nometa', 'frm_entry', $query, 'get_row' );
@@ -348,7 +348,7 @@ class FrmEntry {
348
  return $entry;
349
  }
350
 
351
- $entry = $wpdb->get_row( $query ); // WPCS: unprepared SQL ok.
352
  $entry = self::get_meta( $entry );
353
  self::prepare_entry( $entry );
354
 
@@ -473,7 +473,7 @@ class FrmEntry {
473
  // prepare the query
474
  $query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
475
 
476
- $entries = $wpdb->get_results( $query, OBJECT_K ); // WPCS: unprepared SQL ok.
477
  unset( $query );
478
 
479
  FrmDb::set_cache( $cache_key, $entries, 'frm_entry' );
334
 
335
  $query .= is_numeric( $id ) ? 'it.id=%d' : 'it.item_key=%s';
336
  $query_args = array( $id );
337
+ $query = $wpdb->prepare( $query, $query_args ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
338
 
339
  if ( ! $meta ) {
340
  $entry = FrmDb::check_cache( $id . '_nometa', 'frm_entry', $query, 'get_row' );
348
  return $entry;
349
  }
350
 
351
+ $entry = $wpdb->get_row( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
352
  $entry = self::get_meta( $entry );
353
  self::prepare_entry( $entry );
354
 
473
  // prepare the query
474
  $query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
475
 
476
+ $entries = $wpdb->get_results( $query, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
477
  unset( $query );
478
 
479
  FrmDb::set_cache( $cache_key, $entries, 'frm_entry' );
classes/models/FrmEntryMeta.php CHANGED
@@ -160,7 +160,7 @@ class FrmEntryMeta {
160
  FrmDb::get_where_clause_and_values( $where );
161
 
162
  // Delete any leftovers
163
- $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas ' . $where['where'], $where['values'] ) ); // WPCS: unprepared SQL ok.
164
  self::clear_cache();
165
  }
166
 
@@ -451,7 +451,7 @@ class FrmEntryMeta {
451
  case 'day':
452
  $value = '%' . $value . '%';
453
  }
454
- $where .= $wpdb->prepare( ' meta_value ' . $operator . ' %s and', $value ); // WPCS: unprepared SQL ok.
455
  }
456
  $where .= $wpdb->prepare( ' field_id=%d', $field_id );
457
  $query = 'SELECT DISTINCT item_id FROM ' . $wpdb->prefix . 'frm_item_metas' . FrmDb::prepend_and_or_where( ' WHERE ', $where );
@@ -459,10 +459,10 @@ class FrmEntryMeta {
459
  if ( $operator == 'LIKE' ) {
460
  $search = '%' . $search . '%';
461
  }
462
- $query = $wpdb->prepare( "SELECT DISTINCT item_id FROM {$wpdb->prefix}frm_item_metas WHERE meta_value {$operator} %s and field_id = %d", $search, $field_id ); // WPCS: unprepared SQL ok.
463
  }
464
 
465
- $results = $wpdb->get_col( $query, 0 ); // WPCS: unprepared SQL ok.
466
  FrmDb::set_cache( $cache_key, $results, 'frm_entry' );
467
 
468
  return $results;
160
  FrmDb::get_where_clause_and_values( $where );
161
 
162
  // Delete any leftovers
163
+ $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
164
  self::clear_cache();
165
  }
166
 
451
  case 'day':
452
  $value = '%' . $value . '%';
453
  }
454
+ $where .= $wpdb->prepare( ' meta_value ' . $operator . ' %s and', $value ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
455
  }
456
  $where .= $wpdb->prepare( ' field_id=%d', $field_id );
457
  $query = 'SELECT DISTINCT item_id FROM ' . $wpdb->prefix . 'frm_item_metas' . FrmDb::prepend_and_or_where( ' WHERE ', $where );
459
  if ( $operator == 'LIKE' ) {
460
  $search = '%' . $search . '%';
461
  }
462
+ $query = $wpdb->prepare( "SELECT DISTINCT item_id FROM {$wpdb->prefix}frm_item_metas WHERE meta_value {$operator} %s and field_id = %d", $search, $field_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
463
  }
464
 
465
+ $results = $wpdb->get_col( $query, 0 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
466
  FrmDb::set_cache( $cache_key, $results, 'frm_entry' );
467
 
468
  return $results;
classes/models/FrmEntryValidate.php CHANGED
@@ -112,7 +112,7 @@ class FrmEntryValidate {
112
 
113
  if ( $posted_field->required == '1' && FrmAppHelper::is_empty_value( $value ) ) {
114
  $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $posted_field, 'blank' );
115
- } elseif ( $posted_field->type == 'text' && ! isset( $_POST['item_name'] ) ) { // WPCS: CSRF ok.
116
  $_POST['item_name'] = $value;
117
  }
118
 
@@ -255,11 +255,31 @@ class FrmEntryValidate {
255
  $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
256
  } elseif ( self::blacklist_check( $values ) ) {
257
  $errors['spam'] = __( 'Your entry appears to be blocked spam!', 'formidable' );
258
- } elseif ( self::is_akismet_enabled_for_user( $values['form_id'] ) && self::is_akismet_spam( $values ) ) {
 
 
 
 
 
 
259
  $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
260
  }
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  /**
264
  * @param int $form_id
265
  * @return boolean
@@ -322,6 +342,7 @@ class FrmEntryValidate {
322
  return false;
323
  }
324
 
 
325
  $ip = FrmAppHelper::get_ip_address();
326
  $user_agent = FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' );
327
  $user_info = self::get_spam_check_user_info( $values );
@@ -391,8 +412,11 @@ class FrmEntryValidate {
391
  */
392
  private static function parse_akismet_array( &$datas, $values ) {
393
  self::add_site_info_to_akismet( $datas );
394
- self::add_user_info_to_akismet( $datas, $values );
395
  self::add_server_values_to_akismet( $datas );
 
 
 
 
396
  self::add_comment_content_to_akismet( $datas, $values );
397
  }
398
 
@@ -418,46 +442,125 @@ class FrmEntryValidate {
418
  }
419
  }
420
 
 
 
 
 
 
 
 
 
421
  private static function get_spam_check_user_info( $values ) {
422
- $datas = array();
 
 
423
 
424
- if ( is_user_logged_in() ) {
425
- $user = wp_get_current_user();
426
 
427
- $datas['user_ID'] = $user->ID;
428
- $datas['user_id'] = $user->ID;
429
- $datas['comment_author'] = $user->display_name;
430
- $datas['comment_author_email'] = $user->user_email;
431
- $datas['comment_author_url'] = $user->user_url;
432
- } else {
433
- $datas['comment_author'] = '';
434
- $datas['comment_author_email'] = '';
435
- $datas['comment_author_url'] = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
- if ( isset( $values['item_meta'] ) ) {
438
- $values = $values['item_meta'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  }
440
 
441
- $values = array_filter( $values );
442
-
443
- $datas['frm_duplicated'] = array();
444
- foreach ( $values as $index => $value ) {
445
- if ( ! is_array( $value ) ) {
446
- if ( $datas['comment_author_email'] == '' && strpos( $value, '@' ) && is_email( $value ) ) {
447
- $datas['comment_author_email'] = $value;
448
- $datas['frm_duplicated'][] = $index;
449
- } elseif ( $datas['comment_author_url'] == '' && strpos( $value, 'http' ) === 0 ) {
450
- $datas['comment_author_url'] = $value;
451
- $datas['frm_duplicated'][] = $index;
452
- } elseif ( $datas['comment_author'] == '' && ! is_numeric( $value ) && strlen( $value ) < 200 ) {
453
- $datas['comment_author'] = $value;
454
- $datas['frm_duplicated'][] = $index;
455
- }
456
  }
457
  }
458
  }
 
459
 
460
- return $datas;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  }
462
 
463
  private static function add_server_values_to_akismet( &$datas ) {
@@ -517,18 +620,22 @@ class FrmEntryValidate {
517
  * Gets field IDs that are skipped from sending to Akismet spam check.
518
  *
519
  * @since 5.0.09
 
520
  *
521
- * @param array $values Entry values.
522
  * @return array
523
  */
524
  private static function get_akismet_skipped_field_ids( $values ) {
525
- $form_ids = self::get_all_form_ids_and_flatten_meta( $values );
 
 
 
526
  $skipped_types = array( 'divider', 'form', 'hidden', 'user_id', 'file', 'date', 'time', 'scale', 'star', 'range', 'toggle', 'data', 'lookup', 'likert', 'nps' );
527
  $has_other_types = array( 'radio', 'checkbox', 'select' );
528
 
529
  $where = array(
530
  array(
531
- 'form_id' => $form_ids,
532
  array(
533
  array(
534
  'field_options not like' => ';s:5:"other";s:1:"1"',
@@ -543,22 +650,45 @@ class FrmEntryValidate {
543
  return FrmDb::get_col( 'frm_fields', $where );
544
  }
545
 
 
 
 
 
 
 
 
 
 
 
 
 
546
  /**
547
  * Gets all form IDs (include child form IDs) and flatten item_meta array. Used for skipping values sent to Akismet.
548
  * This also removes some unused data from the item_meta.
549
  *
550
  * @since 5.0.09
 
551
  *
552
  * @param array $values Entry values.
553
  * @return array Form IDs.
554
  */
555
  private static function get_all_form_ids_and_flatten_meta( &$values ) {
556
- $form_ids = array( absint( $values['form_id'] ) );
 
 
 
557
  foreach ( $values['item_meta'] as $field_id => $value ) {
558
  if ( ! is_numeric( $field_id ) ) { // Maybe `other`.
559
  continue;
560
  }
561
 
 
 
 
 
 
 
 
562
  if ( ! is_array( $value ) || empty( $value['form'] ) ) {
563
  continue;
564
  }
@@ -578,6 +708,14 @@ class FrmEntryValidate {
578
  if ( ! isset( $values['item_meta'][ $subsubindex ] ) ) {
579
  $values['item_meta'][ $subsubindex ] = array();
580
  }
 
 
 
 
 
 
 
 
581
  $values['item_meta'][ $subsubindex ][] = $subsubvalue;
582
  }
583
  }
112
 
113
  if ( $posted_field->required == '1' && FrmAppHelper::is_empty_value( $value ) ) {
114
  $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $posted_field, 'blank' );
115
+ } elseif ( $posted_field->type === 'text' && ! isset( $_POST['item_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
116
  $_POST['item_name'] = $value;
117
  }
118
 
255
  $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
256
  } elseif ( self::blacklist_check( $values ) ) {
257
  $errors['spam'] = __( 'Your entry appears to be blocked spam!', 'formidable' );
258
+ }
259
+
260
+ if ( isset( $errors['spam'] ) || self::form_is_in_progress( $values ) ) {
261
+ return;
262
+ }
263
+
264
+ if ( self::is_akismet_enabled_for_user( $values['form_id'] ) && self::is_akismet_spam( $values ) ) {
265
  $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
266
  }
267
  }
268
 
269
+ /**
270
+ * Checks if form is in progress.
271
+ *
272
+ * @since 5.0.13
273
+ *
274
+ * @param array $values The values.
275
+ * @return bool
276
+ */
277
+ private static function form_is_in_progress( $values ) {
278
+ return FrmAppHelper::pro_is_installed() &&
279
+ ( isset( $values[ 'frm_page_order_' . $values['form_id'] ] ) || FrmAppHelper::get_post_param( 'frm_next_page' ) ) &&
280
+ FrmField::get_all_types_in_form( $values['form_id'], 'break' );
281
+ }
282
+
283
  /**
284
  * @param int $form_id
285
  * @return boolean
342
  return false;
343
  }
344
 
345
+ self::prepare_values_for_spam_check( $values );
346
  $ip = FrmAppHelper::get_ip_address();
347
  $user_agent = FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' );
348
  $user_info = self::get_spam_check_user_info( $values );
412
  */
413
  private static function parse_akismet_array( &$datas, $values ) {
414
  self::add_site_info_to_akismet( $datas );
 
415
  self::add_server_values_to_akismet( $datas );
416
+
417
+ self::prepare_values_for_spam_check( $values );
418
+
419
+ self::add_user_info_to_akismet( $datas, $values );
420
  self::add_comment_content_to_akismet( $datas, $values );
421
  }
422
 
442
  }
443
  }
444
 
445
+ /**
446
+ * Gets user info for Akismet spam check.
447
+ *