| @@ -1051,10 +1051,18 @@ | ||
| 1051 | 1051 | ob_start(); |
| 1052 | 1052 | do_action('wpvr_hotspot_content', $hotspot_data); |
| 1053 | 1053 | $hotspot_content = ob_get_clean(); |
| 1054 | 1054 | |
| 1055 | - if (!$hotspot_content) { | |
| 1056 | - $hotspot_content = $hotspot_data["hotspot-content"]; | |
| 1055 | + $is_fluent_form = isset($hotspot_data["hotspot-type"]) && 'fluent_form' === $hotspot_data["hotspot-type"]; | |
| 1056 | + | |
| 1057 | + if ($is_fluent_form) { | |
| 1058 | + if (!empty($hotspot_content)) { | |
| 1059 | + $hotspot_content = preg_replace('/<script\b[^>]*>[\s\S]*?<\/script>/i', '', $hotspot_content); | |
| 1060 | + } | |
| 1061 | + } else { | |
| 1062 | + if (!$hotspot_content) { | |
| 1063 | + $hotspot_content = $hotspot_data["hotspot-content"] ?? ''; | |
| 1064 | + } | |
| 1057 | 1065 | } |
| 1058 | 1066 | |
| 1059 | 1067 | $hotspot_url = $this->normalize_hotspot_external_url($hotspot_data["hotspot-url"] ?? ''); |
| 1060 | 1068 | |
| @@ -1074,9 +1082,8 @@ | ||
| 1074 | 1082 | $hotspot_data['hotspot-hover'] ?? '' |
| 1075 | 1083 | ); |
| 1076 | 1084 | |
| 1077 | 1085 | |
| 1078 | - $is_fluent_form = isset($hotspot_data["hotspot-type"]) && 'fluent_form' === $hotspot_data["hotspot-type"]; | |
| 1079 | 1086 | $on_hover_content = $this->sanitize_content_preserve_styles($on_hover_content ?? '', false); |
| 1080 | 1087 | $on_click_content = preg_replace_callback('/<img[^>]*>/', "replace_callback", $hotspot_content ?? ''); |
| 1081 | 1088 | $on_click_content = $this->sanitize_content_preserve_styles($on_click_content ?? '', $is_fluent_form); |
| 1082 | 1089 | |
| @@ -1515,16 +1522,24 @@ | ||
| 1515 | 1522 | $animation_css = apply_filters('wpvr_tour_scene_animation',$animation_type,$animationDuration,$animationDelay,$postdata,$id); |
| 1516 | 1523 | $html .= $animation_css; |
| 1517 | 1524 | } |
| 1518 | 1525 | |
| 1526 | + $container_width = $width; | |
| 1527 | + $container_height = $height; | |
| 1528 | + $container_mobile_height = $mobile_height; | |
| 1529 | + | |
| 1519 | 1530 | if ($width == 'fullwidth') { |
| 1520 | - $width = "100%"; | |
| 1531 | + $container_width = "100%"; | |
| 1532 | + } elseif ($width == 'embed') { | |
| 1533 | + $container_width = "100%"; | |
| 1534 | + $container_height = "100%"; | |
| 1535 | + $container_mobile_height = "100%"; | |
| 1521 | 1536 | } |
| 1522 | 1537 | |
| 1523 | 1538 | if (wpvr_isMobileDevice()) { |
| 1524 | - $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $width . '; width: 100%; height: ' . $mobile_height . '; border-radius:' . $radius . '; direction:ltr; ">'; | |
| 1539 | + $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $container_width . '; width: 100%; height: ' . $container_mobile_height . '; border-radius:' . $radius . '; direction:ltr; ">'; | |
| 1525 | 1540 | } else { |
| 1526 | - $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $width . '; width: 100%; height: ' . $height . '; border-radius:' . $radius . '; direction:ltr; ">'; | |
| 1541 | + $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $container_width . '; width: 100%; height: ' . $container_height . '; border-radius:' . $radius . '; direction:ltr; ">'; | |
| 1527 | 1542 | } |
| 1528 | 1543 | $is_pro = apply_filters('is_wpvr_pro_active',false); |
| 1529 | 1544 | $status = get_option('wpvr_edd_license_status'); |
| 1530 | 1545 | $is_cardboard = get_option('wpvr_cardboard_disable'); |
| @@ -1569,9 +1584,9 @@ | ||
| 1569 | 1584 | } |
| 1570 | 1585 | } elseif ($width == 'embed') { |
| 1571 | 1586 | $html .= '<div class="cardboard-vrembed vrembed">'; |
| 1572 | 1587 | $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left pano2' . $id . '" style=" width: 49%!important; text-align:center; direction:ltr;" ><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>'; |
| 1573 | - $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" text-align:center; direction:ltr;" >'; | |
| 1588 | + $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; height: 100%; text-align:center; direction:ltr;" >'; | |
| 1574 | 1589 | } else { |
| 1575 | 1590 | if (wpvr_isMobileDevice()) { |
| 1576 | 1591 | $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left cardboard-half pano2' . $id . '" style="width: 49%; border-radius:' . $radius . '"><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>'; |
| 1577 | 1592 | if ($radius) { |
| @@ -2011,9 +2026,10 @@ | ||
| 2011 | 2026 | border: '.$border_width.'px '.$border_style.' '.$border_color.'; |
| 2012 | 2027 | border-radius: '.$border_radius.'px; |
| 2013 | 2028 | padding: '.$button_pt.'px '.$button_pr.'px '.$button_pb.'px '.$button_pl.'px; |
| 2014 | 2029 | '; |
| 2015 | - $html .= '<div class="wpvr-call-to-action-button position-'.$text_align.'" style="max-width:' . $width.'"> | |
| 2030 | + $cta_width = ( $width === 'fullwidth' || $width === 'embed' ) ? '100%' : $width; | |
| 2031 | + $html .= '<div class="wpvr-call-to-action-button position-'.$text_align.'" style="max-width:' . $cta_width . '"> | |
| 2016 | 2032 | <a href="'.$buttonurl.'" style="'.$style.'" target="'.$target.'">'.$buttontext.'</a> |
| 2017 | 2033 | </div>'; |
| 2018 | 2034 | |
| 2019 | 2035 | } |
| @@ -2867,9 +2883,9 @@ | ||
| 2867 | 2883 | $scene_key = $panoscenes['scene-id']; |
| 2868 | 2884 | $gallery_scene_ids[] = (string) $scene_key; |
| 2869 | 2885 | $scene_key_gallery = $panoscenes['scene-id'] . '_gallery_' . $pano_suffix; |
| 2870 | 2886 | $html .= 'jQuery(document).on("click","#' . $scene_key_gallery . '",function() { |
| 2871 | - panoshow' . $pano_suffix . '.loadScene("' . $scene_key . '"); | |
| 2887 | + panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $scene_key ) . '); | |
| 2872 | 2888 | });'; |
| 2873 | 2889 | } |
| 2874 | 2890 | } |
| 2875 | 2891 | |
| @@ -3094,9 +3110,9 @@ | ||
| 3094 | 3110 | $html .= '})();'; |
| 3095 | 3111 | } |
| 3096 | 3112 | if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) { |
| 3097 | 3113 | $html .= 'document.getElementById("backToHome' . $pano_suffix . '").addEventListener("click", function(e) {'; |
| 3098 | - $html .= 'panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '");'; | |
| 3114 | + $html .= 'panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $default_scene ) . ');'; | |
| 3099 | 3115 | $html .= '});'; |
| 3100 | 3116 | } |
| 3101 | 3117 | if ($gyro_button_enabled && 'valid' == $status && $is_pro) { |
| 3102 | 3118 | $html .= ' |
| @@ -3205,11 +3221,15 @@ | ||
| 3205 | 3221 | } |
| 3206 | 3222 | |
| 3207 | 3223 | $html .= ' |
| 3208 | 3224 | jQuery(document).on("click","#' . $panoid . '",function(event) { |
| 3225 | + var isCross = event.target.closest(".cross"); | |
| 3209 | 3226 | var isActiveModal = event.target.closest(".custom-ifram-wrapper"); |
| 3210 | - var isForm = event.target.closest(".wpvr-hotspot-tweak-contents"); | |
| 3227 | + var isForm = event.target.closest(".wpvr-hotspot-tweak-contents-wrapper"); | |
| 3211 | 3228 | var isHotspot = event.target.closest(".pnlm-hotspot-base"); |
| 3229 | + if(isCross != null){ | |
| 3230 | + return; | |
| 3231 | + } | |
| 3212 | 3232 | if(isForm != null){ |
| 3213 | 3233 | jQuery(this).addClass("show-modal"); |
| 3214 | 3234 | }else if(isActiveModal == null){ |
| 3215 | 3235 | if(isHotspot == null){ |
| @@ -3215,9 +3235,9 @@ | ||
| 3215 | 3235 | if(isHotspot == null){ |
| 3216 | 3236 | jQuery(".custom-ifram-wrapper .custom-ifram").empty(); |
| 3217 | 3237 | jQuery(".custom-ifram-wrapper").hide(); |
| 3218 | 3238 | jQuery(this).removeClass("show-modal"); |
| 3219 | - jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide("show-modal"); | |
| 3239 | + jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide(); | |
| 3220 | 3240 | } |
| 3221 | 3241 | } |
| 3222 | 3242 | });'; |
| 3223 | 3243 | |
| @@ -3477,9 +3497,9 @@ | ||
| 3477 | 3497 | window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . '; |
| 3478 | 3498 | document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", { |
| 3479 | 3499 | detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' } |
| 3480 | 3500 | })); |
| 3481 | - jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previeword . '") | |
| 3501 | + jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text(' . wp_json_encode( (string) $previeword ) . ') | |
| 3482 | 3502 | setTimeout(function() { |
| 3483 | 3503 | // panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '"); |
| 3484 | 3504 | window.dispatchEvent(new Event("resize")); |
| 3485 | 3505 | if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) { |
| @@ -3500,9 +3520,9 @@ | ||
| 3500 | 3520 | document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", { |
| 3501 | 3521 | detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' } |
| 3502 | 3522 | })); |
| 3503 | 3523 | setTimeout(function() { |
| 3504 | - panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '"); | |
| 3524 | + panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $default_scene ) . '); | |
| 3505 | 3525 | window.dispatchEvent(new Event("resize")); |
| 3506 | 3526 | if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) { |
| 3507 | 3527 | jQuery("#controls' . $pano_suffix . '").css("bottom", "55px"); |
| 3508 | 3528 | } |
| @@ -3512,9 +3532,9 @@ | ||
| 3512 | 3532 | }, 200); |
| 3513 | 3533 | });'; |
| 3514 | 3534 | if (isset($previeword) && $previeword != '') { |
| 3515 | 3535 | $html .= ' |
| 3516 | - jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previeword . '") | |
| 3536 | + jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text(' . wp_json_encode( (string) $previeword ) . ') | |
| 3517 | 3537 | '; |
| 3518 | 3538 | } |
| 3519 | 3539 | if ($default_global_zoom != '' || $max_global_zoom != '' || $min_global_zoom != '') { |
| 3520 | 3540 | $html .= 'jQuery(".globalzoom").val("on").change();'; |
| @@ -3558,12 +3578,16 @@ | ||
| 3558 | 3578 | private function sanitize_content_preserve_styles($content, $allow_forms = false) { |
| 3559 | 3579 | // Decode HTML entities first (in case content was encoded in database) |
| 3560 | 3580 | $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8'); |
| 3561 | 3581 | |
| 3562 | - // Escape <script> blocks to display as text instead of removing them | |
| 3563 | - $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) { | |
| 3564 | - return esc_html($matches[0]); // Convert to plain text | |
| 3565 | - }, $content); | |
| 3582 | + // Escape or strip <script> blocks | |
| 3583 | + if ($allow_forms) { | |
| 3584 | + $content = preg_replace('/<script\b[^>]*>[\s\S]*?<\/script>/i', '', $content); | |
| 3585 | + } else { | |
| 3586 | + $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) { | |
| 3587 | + return esc_html($matches[0]); // Convert to plain text | |
| 3588 | + }, $content); | |
| 3589 | + } | |
| 3566 | 3590 | |
| 3567 | 3591 | // Strip dangerous URL-based attributes |
| 3568 | 3592 | $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content); |
| 3569 | 3593 | |
| @@ -3606,10 +3630,16 @@ | ||
| 3606 | 3630 | $css = preg_replace('/-moz-binding\s*:/i', '', $css); |
| 3607 | 3631 | return '<style>' . esc_html($css) . '</style>'; |
| 3608 | 3632 | }, $content); |
| 3609 | 3633 | |
| 3610 | - // Allow iframes from safe sources only (e.g., YouTube, Vimeo) | |
| 3634 | + // Allow iframes and styles from safe sources only | |
| 3611 | 3635 | $allowed_tags = wp_kses_allowed_html('post'); |
| 3636 | + $allowed_tags['style'] = [ | |
| 3637 | + 'type' => true, | |
| 3638 | + 'id' => true, | |
| 3639 | + 'class' => true, | |
| 3640 | + 'media' => true, | |
| 3641 | + ]; | |
| 3612 | 3642 | $allowed_tags['iframe'] = [ |
| 3613 | 3643 | 'src' => true, |
| 3614 | 3644 | 'width' => true, |
| 3615 | 3645 | 'height' => true, |
| @@ -3639,37 +3669,47 @@ | ||
| 3639 | 3669 | ]; |
| 3640 | 3670 | |
| 3641 | 3671 | if ($allow_forms) { |
| 3642 | 3672 | $form_attributes = [ |
| 3643 | - 'id' => true, | |
| 3644 | - 'class' => true, | |
| 3645 | - 'style' => true, | |
| 3646 | - 'name' => true, | |
| 3647 | - 'value' => true, | |
| 3648 | - 'type' => true, | |
| 3649 | - 'placeholder' => true, | |
| 3650 | - 'action' => true, | |
| 3651 | - 'method' => true, | |
| 3652 | - 'target' => true, | |
| 3653 | - 'enctype' => true, | |
| 3654 | - 'disabled' => true, | |
| 3655 | - 'readonly' => true, | |
| 3656 | - 'required' => true, | |
| 3657 | - 'checked' => true, | |
| 3658 | - 'selected' => true, | |
| 3659 | - 'multiple' => true, | |
| 3660 | - 'size' => true, | |
| 3661 | - 'rows' => true, | |
| 3662 | - 'cols' => true, | |
| 3663 | - 'maxlength' => true, | |
| 3664 | - 'minlength' => true, | |
| 3665 | - 'min' => true, | |
| 3666 | - 'max' => true, | |
| 3667 | - 'step' => true, | |
| 3668 | - 'pattern' => true, | |
| 3669 | - 'autocomplete'=> true, | |
| 3670 | - 'autofocus' => true, | |
| 3671 | - 'for' => true, | |
| 3673 | + 'id' => true, | |
| 3674 | + 'class' => true, | |
| 3675 | + 'style' => true, | |
| 3676 | + 'name' => true, | |
| 3677 | + 'value' => true, | |
| 3678 | + 'type' => true, | |
| 3679 | + 'placeholder' => true, | |
| 3680 | + 'action' => true, | |
| 3681 | + 'method' => true, | |
| 3682 | + 'target' => true, | |
| 3683 | + 'enctype' => true, | |
| 3684 | + 'disabled' => true, | |
| 3685 | + 'readonly' => true, | |
| 3686 | + 'required' => true, | |
| 3687 | + 'checked' => true, | |
| 3688 | + 'selected' => true, | |
| 3689 | + 'multiple' => true, | |
| 3690 | + 'size' => true, | |
| 3691 | + 'rows' => true, | |
| 3692 | + 'cols' => true, | |
| 3693 | + 'maxlength' => true, | |
| 3694 | + 'minlength' => true, | |
| 3695 | + 'min' => true, | |
| 3696 | + 'max' => true, | |
| 3697 | + 'step' => true, | |
| 3698 | + 'pattern' => true, | |
| 3699 | + 'autocomplete' => true, | |
| 3700 | + 'autofocus' => true, | |
| 3701 | + 'for' => true, | |
| 3702 | + 'data-*' => true, | |
| 3703 | + 'data-form_id' => true, | |
| 3704 | + 'data-form_instance' => true, | |
| 3705 | + 'data-name' => true, | |
| 3706 | + 'data-type' => true, | |
| 3707 | + 'aria-invalid' => true, | |
| 3708 | + 'aria-required' => true, | |
| 3709 | + 'aria-label' => true, | |
| 3710 | + 'aria-describedby' => true, | |
| 3711 | + 'aria-labelledby' => true, | |
| 3672 | 3712 | ]; |
| 3673 | 3713 | $allowed_tags['form'] = $form_attributes; |
| 3674 | 3714 | $allowed_tags['input'] = $form_attributes; |
| 3675 | 3715 | $allowed_tags['button'] = $form_attributes; |
| @@ -3679,8 +3719,18 @@ | ||
| 3679 | 3719 | $allowed_tags['optgroup'] = $form_attributes; |
| 3680 | 3720 | $allowed_tags['label'] = $form_attributes; |
| 3681 | 3721 | $allowed_tags['fieldset'] = $form_attributes; |
| 3682 | 3722 | $allowed_tags['legend'] = $form_attributes; |
| 3723 | + if (!isset($allowed_tags['div'])) { | |
| 3724 | + $allowed_tags['div'] = []; | |
| 3725 | + } | |
| 3726 | + $allowed_tags['div']['data-*'] = true; | |
| 3727 | + $allowed_tags['div']['data-form_id'] = true; | |
| 3728 | + $allowed_tags['div']['data-form_instance'] = true; | |
| 3729 | + if (!isset($allowed_tags['span'])) { | |
| 3730 | + $allowed_tags['span'] = []; | |
| 3731 | + } | |
| 3732 | + $allowed_tags['span']['data-*'] = true; | |
| 3683 | 3733 | } |
| 3684 | 3734 | |
| 3685 | 3735 | // Apply wp_kses() to keep only allowed tags/attributes |
| 3686 | 3736 | $content = wp_kses($content, $allowed_tags); |