PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.1.3
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.1.3
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
← All changes | legacy/wpvr.php +99 -36 9.1.19.1.3 View file →
@@ -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 }