| @@ -788,12 +788,16 @@ | ||
| 788 | 788 | function sanitize_content_preserve_styles($content, $allow_forms = false) { |
| 789 | 789 | // Decode HTML entities first (in case content was encoded in database) |
| 790 | 790 | $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8'); |
| 791 | 791 | |
| 792 | - // Escape <script> blocks to display as text instead of removing them | |
| 793 | - $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) { | |
| 794 | - return esc_html($matches[0]); // Convert to plain text | |
| 795 | - }, $content); | |
| 792 | + // Escape or strip <script> blocks | |
| 793 | + if ($allow_forms) { | |
| 794 | + $content = preg_replace('/<script\b[^>]*>[\s\S]*?<\/script>/i', '', $content); | |
| 795 | + } else { | |
| 796 | + $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) { | |
| 797 | + return esc_html($matches[0]); // Convert to plain text | |
| 798 | + }, $content); | |
| 799 | + } | |
| 796 | 800 | |
| 797 | 801 | // Strip dangerous URL-based attributes |
| 798 | 802 | $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content); |
| 799 | 803 | |
| @@ -836,10 +840,16 @@ | ||
| 836 | 840 | $css = preg_replace('/-moz-binding\s*:/i', '', $css); |
| 837 | 841 | return '<style>' . esc_html($css) . '</style>'; |
| 838 | 842 | }, $content); |
| 839 | 843 | |
| 840 | - // Allow iframes from safe sources only (e.g., YouTube, Vimeo) | |
| 844 | + // Allow iframes and styles from safe sources only | |
| 841 | 845 | $allowed_tags = wp_kses_allowed_html('post'); |
| 846 | + $allowed_tags['style'] = [ | |
| 847 | + 'type' => true, | |
| 848 | + 'id' => true, | |
| 849 | + 'class' => true, | |
| 850 | + 'media' => true, | |
| 851 | + ]; | |
| 842 | 852 | $allowed_tags['iframe'] = [ |
| 843 | 853 | 'src' => true, |
| 844 | 854 | 'width' => true, |
| 845 | 855 | 'height' => true, |
| @@ -869,37 +879,47 @@ | ||
| 869 | 879 | ]; |
| 870 | 880 | |
| 871 | 881 | if ($allow_forms) { |
| 872 | 882 | $form_attributes = [ |
| 873 | - 'id' => true, | |
| 874 | - 'class' => true, | |
| 875 | - 'style' => true, | |
| 876 | - 'name' => true, | |
| 877 | - 'value' => true, | |
| 878 | - 'type' => true, | |
| 879 | - 'placeholder' => true, | |
| 880 | - 'action' => true, | |
| 881 | - 'method' => true, | |
| 882 | - 'target' => true, | |
| 883 | - 'enctype' => true, | |
| 884 | - 'disabled' => true, | |
| 885 | - 'readonly' => true, | |
| 886 | - 'required' => true, | |
| 887 | - 'checked' => true, | |
| 888 | - 'selected' => true, | |
| 889 | - 'multiple' => true, | |
| 890 | - 'size' => true, | |
| 891 | - 'rows' => true, | |
| 892 | - 'cols' => true, | |
| 893 | - 'maxlength' => true, | |
| 894 | - 'minlength' => true, | |
| 895 | - 'min' => true, | |
| 896 | - 'max' => true, | |
| 897 | - 'step' => true, | |
| 898 | - 'pattern' => true, | |
| 899 | - 'autocomplete'=> true, | |
| 900 | - 'autofocus' => true, | |
| 901 | - 'for' => true, | |
| 883 | + 'id' => true, | |
| 884 | + 'class' => true, | |
| 885 | + 'style' => true, | |
| 886 | + 'name' => true, | |
| 887 | + 'value' => true, | |
| 888 | + 'type' => true, | |
| 889 | + 'placeholder' => true, | |
| 890 | + 'action' => true, | |
| 891 | + 'method' => true, | |
| 892 | + 'target' => true, | |
| 893 | + 'enctype' => true, | |
| 894 | + 'disabled' => true, | |
| 895 | + 'readonly' => true, | |
| 896 | + 'required' => true, | |
| 897 | + 'checked' => true, | |
| 898 | + 'selected' => true, | |
| 899 | + 'multiple' => true, | |
| 900 | + 'size' => true, | |
| 901 | + 'rows' => true, | |
| 902 | + 'cols' => true, | |
| 903 | + 'maxlength' => true, | |
| 904 | + 'minlength' => true, | |
| 905 | + 'min' => true, | |
| 906 | + 'max' => true, | |
| 907 | + 'step' => true, | |
| 908 | + 'pattern' => true, | |
| 909 | + 'autocomplete' => true, | |
| 910 | + 'autofocus' => true, | |
| 911 | + 'for' => true, | |
| 912 | + 'data-*' => true, | |
| 913 | + 'data-form_id' => true, | |
| 914 | + 'data-form_instance' => true, | |
| 915 | + 'data-name' => true, | |
| 916 | + 'data-type' => true, | |
| 917 | + 'aria-invalid' => true, | |
| 918 | + 'aria-required' => true, | |
| 919 | + 'aria-label' => true, | |
| 920 | + 'aria-describedby' => true, | |
| 921 | + 'aria-labelledby' => true, | |
| 902 | 922 | ]; |
| 903 | 923 | $allowed_tags['form'] = $form_attributes; |
| 904 | 924 | $allowed_tags['input'] = $form_attributes; |
| 905 | 925 | $allowed_tags['button'] = $form_attributes; |
| @@ -909,8 +929,18 @@ | ||
| 909 | 929 | $allowed_tags['optgroup'] = $form_attributes; |
| 910 | 930 | $allowed_tags['label'] = $form_attributes; |
| 911 | 931 | $allowed_tags['fieldset'] = $form_attributes; |
| 912 | 932 | $allowed_tags['legend'] = $form_attributes; |
| 933 | + if (!isset($allowed_tags['div'])) { | |
| 934 | + $allowed_tags['div'] = []; | |
| 935 | + } | |
| 936 | + $allowed_tags['div']['data-*'] = true; | |
| 937 | + $allowed_tags['div']['data-form_id'] = true; | |
| 938 | + $allowed_tags['div']['data-form_instance'] = true; | |
| 939 | + if (!isset($allowed_tags['span'])) { | |
| 940 | + $allowed_tags['span'] = []; | |
| 941 | + } | |
| 942 | + $allowed_tags['span']['data-*'] = true; | |
| 913 | 943 | } |
| 914 | 944 | |
| 915 | 945 | // Apply wp_kses() to keep only allowed tags/attributes |
| 916 | 946 | $content = wp_kses($content, $allowed_tags); |
| @@ -1027,15 +1057,22 @@ | ||
| 1027 | 1057 | } |
| 1028 | 1058 | |
| 1029 | 1059 | function wpvr_rest_route_permission() |
| 1030 | 1060 | { |
| 1031 | - return true; | |
| 1061 | + $post_type_obj = get_post_type_object( 'wpvr_item' ); | |
| 1062 | + $edit_cap = $post_type_obj ? $post_type_obj->cap->edit_posts : 'edit_wpvr_tours'; | |
| 1063 | + return current_user_can( $edit_cap ) || current_user_can( 'edit_posts' ); | |
| 1032 | 1064 | } |
| 1033 | 1065 | |
| 1034 | 1066 | function wpvr_rest_data_set() |
| 1035 | 1067 | { |
| 1068 | + $post_type_obj = get_post_type_object( 'wpvr_item' ); | |
| 1069 | + $edit_cap = $post_type_obj ? $post_type_obj->cap->edit_posts : 'edit_wpvr_tours'; | |
| 1070 | + $post_status = current_user_can( $edit_cap ) ? array( 'publish', 'draft', 'private' ) : 'publish'; | |
| 1071 | + | |
| 1036 | 1072 | $query = new WP_Query(array( |
| 1037 | - 'post_type' => 'wpvr_item', | |
| 1073 | + 'post_type' => 'wpvr_item', | |
| 1074 | + 'post_status' => $post_status, | |
| 1038 | 1075 | 'posts_per_page' => -1, |
| 1039 | 1076 | )); |
| 1040 | 1077 | |
| 1041 | 1078 | $wpvr_list = array(); |
| @@ -1048,8 +1085,9 @@ | ||
| 1048 | 1085 | $title = $post_id . ' : ' . $title; |
| 1049 | 1086 | $list_ob = array('value' => $post_id, 'label' => $title); |
| 1050 | 1087 | array_push($wpvr_list, $list_ob); |
| 1051 | 1088 | } |
| 1089 | + wp_reset_postdata(); | |
| 1052 | 1090 | |
| 1053 | 1091 | return $wpvr_list; |
| 1054 | 1092 | } |
| 1055 | 1093 | |
| @@ -1358,5 +1396,30 @@ | ||
| 1358 | 1396 | } |
| 1359 | 1397 | } |
| 1360 | 1398 | |
| 1361 | 1399 | return wp_kses( $content, $allowed_tags ); |
| 1400 | +} | |
| 1401 | + | |
| 1402 | +add_filter('fluentform/form_vars_for_JS', 'wpvr_fluent_form_register_inline_vars', 10, 2); | |
| 1403 | +/** | |
| 1404 | + * Register Fluent Forms JS vars safely via WordPress script API. | |
| 1405 | + * Prevents raw script tag concatenation in HTML while ensuring form handlers initialize. | |
| 1406 | + * | |
| 1407 | + * @param array $vars Form configuration variables from Fluent Forms. | |
| 1408 | + * @param object $form Fluent Form database record. | |
| 1409 | + * @return array | |
| 1410 | + */ | |
| 1411 | +function wpvr_fluent_form_register_inline_vars($vars, $form) { | |
| 1412 | + if (!empty($vars['form_instance'])) { | |
| 1413 | + $inline_js = 'window.fluent_form_' . esc_js($vars['form_instance']) . ' = ' . wp_json_encode($vars) . ';'; | |
| 1414 | + if (wp_script_is('fluent-form-submission', 'done') || wp_doing_ajax()) { | |
| 1415 | + if (function_exists('wp_print_inline_script_tag')) { | |
| 1416 | + wp_print_inline_script_tag($inline_js); | |
| 1417 | + } else { | |
| 1418 | + echo '<script type="text/javascript">' . $inline_js . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1419 | + } | |
| 1420 | + } else { | |
| 1421 | + wp_add_inline_script('fluent-form-submission', $inline_js, 'before'); | |
| 1422 | + } | |
| 1423 | + } | |
| 1424 | + return $vars; | |
| 1362 | 1425 | } |