PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.7.7
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.7.7
8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 8.5.4 8.5.3 8.5.2 All 533 releases
← All changes | functions.php +195 -7 8.5.28.7.7 View file →
@@ -58,8 +58,62 @@
58 58 });
59 59 </script>
60 60 <?php
61 61 }
62 +/**
63 + * Extract a YouTube video ID from common URL formats.
64 + *
65 + * @param string $url YouTube watch, embed, short, or youtu.be URL.
66 + * @return string Video ID or empty string.
67 + */
68 +if ( ! function_exists( 'qcld_wpbot_extract_youtube_id' ) ) {
69 + function qcld_wpbot_extract_youtube_id( $url ) {
70 + $url = trim( (string) $url );
71 + if ( $url === '' ) {
72 + return '';
73 + }
74 +
75 + if ( preg_match( '/(?:youtube\.com\/(?:embed\/|shorts\/|live\/|watch\?(?:.*&)?v=)|youtu\.be\/)([A-Za-z0-9_-]{11})/', $url, $matches ) ) {
76 + return $matches[1];
77 + }
78 +
79 + $path = (string) wp_parse_url( $url, PHP_URL_PATH );
80 + $base = basename( $path );
81 + if ( preg_match( '/^[A-Za-z0-9_-]{11}$/', $base ) ) {
82 + return $base;
83 + }
84 +
85 + return '';
86 + }
87 +}
88 +if ( ! function_exists( 'qcld_wpbot_youtube_icon_embed_src' ) ) {
89 + function qcld_wpbot_youtube_icon_embed_src( $url ) {
90 + $video_id = qcld_wpbot_extract_youtube_id( $url );
91 + if ( $video_id === '' ) {
92 + return '';
93 + }
94 +
95 + return add_query_arg(
96 + array(
97 + 'autoplay' => '1',
98 + 'mute' => '1',
99 + 'loop' => '1',
100 + 'playlist' => $video_id,
101 + 'controls' => '0',
102 + 'showinfo' => '0',
103 + 'rel' => '0',
104 + 'fs' => '0',
105 + 'iv_load_policy' => '3',
106 + 'cc_load_policy' => '0',
107 + 'disablekb' => '1',
108 + 'playsinline' => '1',
109 + 'modestbranding' => '1',
110 + 'color' => 'white',
111 + ),
112 + 'https://www.youtube.com/embed/' . rawurlencode( $video_id )
113 + );
114 + }
115 +}
62 116 function wp_chatbot_load_footer_html(){
63 117 if ( get_option('disable_wp_chatbot') != 1 && wp_chatbot_load_controlling() === true) {
64 118
65 119 ?>
@@ -79,10 +133,27 @@
79 133 }
80 134 ?>
81 135 <style>
82 136 .wp-chatbot-container {
137 + background-color: #eceef3 !important;
83 138 background-image: url(<?php echo esc_url($qcld_wb_chatbot_board_bg_path); ?>) !important;
139 + background-size: cover !important;
140 + background-position: center !important;
141 + background-repeat: no-repeat !important;
84 142 }
143 + .wp-chatbot-template-01 #wp-chatbot-board-container,
144 + .wp-chatbot-template-01 .wp-chatbot-board-container {
145 + background-color: #eceef3 !important;
146 + background-image: none !important;
147 + }
148 + .wp-chatbot-template-01 #wp-chatbot-board-container::before,
149 + .wp-chatbot-template-01 .wp-chatbot-board-container::before {
150 + background-color: #eceef3 !important;
151 + background-image: url(<?php echo esc_url($qcld_wb_chatbot_board_bg_path); ?>) !important;
152 + background-size: cover !important;
153 + background-position: center !important;
154 + background-repeat: no-repeat !important;
155 + }
85 156 </style>
86 157 <?php }
87 158 $wp_chatbot_enable_rtl = "";
88 159 if (get_option('enable_wp_chatbot_rtl') == '1') {
@@ -180,14 +251,72 @@
180 251 $wp_chatbot_custom_icon_path = QCLD_wpCHATBOT_IMG_URL . get_option('wp_chatbot_icon');
181 252 } else {
182 253 $wp_chatbot_custom_icon_path = QCLD_wpCHATBOT_IMG_URL . 'custom.png';
183 254 }
255 + $_wpbot_icon_video = get_option('wp_chatbot_icon_video', '');
256 + $_wpbot_video_is_youtube = ( strpos( $_wpbot_icon_video, 'youtube.com' ) !== false || strpos( $_wpbot_icon_video, 'youtu.be' ) !== false );
257 + $_wpbot_youtube_embed_src = $_wpbot_video_is_youtube ? qcld_wpbot_youtube_icon_embed_src( $_wpbot_icon_video ) : '';
258 + $_wpbot_video_delay_ms = absint( get_option( 'wp_chatbot_icon_video_delay', 0 ) ) * 1000;
259 +
260 + $wp_chatbot_ball_is_youtube = ($_wpbot_icon_video !== '' && (strpos($_wpbot_icon_video, 'youtube.com') !== false || strpos($_wpbot_icon_video, 'youtu.be') !== false));
261 + $wp_chatbot_ball_is_video = ($_wpbot_icon_video !== '' && !$wp_chatbot_ball_is_youtube);
262 + $wp_chatbot_ball_has_video = ($wp_chatbot_ball_is_youtube || $wp_chatbot_ball_is_video);
184 263 ?>
185 264 <img src="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>"
186 - alt="wpChatIcon" qcld_agent="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>" >
187 -
265 + alt="wpChatIcon" qcld_agent="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>"
266 + id="wp-chatbot-ball-icon-img"
267 + <?php if ($wp_chatbot_ball_has_video) { echo 'style="display:none;"'; } ?> >
268 + <?php if ( $_wpbot_icon_video !== '' ) : ?>
269 + <?php if ( $_wpbot_video_is_youtube && $_wpbot_youtube_embed_src !== '' ) : ?>
270 + <iframe class="wpbot-icon-video" src="<?php echo $_wpbot_video_delay_ms > 0 ? 'about:blank' : esc_url( $_wpbot_youtube_embed_src ); ?>" data-wpbot-yt-src="<?php echo esc_url( $_wpbot_youtube_embed_src ); ?>" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture"></iframe>
271 + <?php elseif ( ! $_wpbot_video_is_youtube ) : ?>
272 + <video class="wpbot-icon-video" src="<?php echo esc_url( $_wpbot_icon_video ); ?>" autoplay muted loop playsinline preload="auto"></video>
273 + <?php endif; ?>
274 + <?php endif; ?>
188 275 </div>
276 +
189 277 </div>
278 + <?php
279 + if ( $_wpbot_icon_video !== '' ) :
280 + ?>
281 + <script>
282 + (function(){
283 + var wpbotDelay = <?php echo (int) $_wpbot_video_delay_ms; ?>;
284 + function wpbotForcePlay(){
285 + var v = document.querySelector('#wp-chatbot-ball video.wpbot-icon-video');
286 + if( v ){
287 + v.muted = true;
288 + v.volume = 0;
289 + v.loop = true;
290 + var tries = 0, maxTries = 30;
291 + var timer = setInterval(function(){
292 + tries++;
293 + v.play().then(function(){ clearInterval(timer); }).catch(function(){});
294 + if( tries >= maxTries ) clearInterval(timer);
295 + }, 300);
296 + }
297 + var yt = document.querySelector('#wp-chatbot-ball iframe.wpbot-icon-video');
298 + if( yt ){
299 + var ytSrc = yt.getAttribute('data-wpbot-yt-src');
300 + if( ytSrc && ( !yt.getAttribute('src') || yt.getAttribute('src') === 'about:blank' || yt.getAttribute('src').indexOf('autoplay=1') === -1 ) ){
301 + yt.setAttribute('src', ytSrc);
302 + }
303 + }
304 + }
305 + function wpbotDelayedPlay(){
306 + setTimeout(wpbotForcePlay, wpbotDelay);
307 + }
308 + if( document.readyState === 'loading' ){
309 + document.addEventListener('DOMContentLoaded', wpbotDelayedPlay);
310 + } else {
311 + wpbotDelayedPlay();
312 + }
313 + window.addEventListener('load', function(){
314 + setTimeout(wpbotForcePlay, wpbotDelay);
315 + });
316 + })();
317 + </script>
318 + <?php endif; ?>
190 319 <?php
191 320 $fb_app_id = get_option('qlcd_wp_chatbot_fb_app_id');
192 321 $fb_page_id = get_option('qlcd_wp_chatbot_fb_page_id');
193 322 $fb_mgs_color = get_option('qlcd_wp_chatbot_fb_color') != '' ? get_option('qlcd_wp_chatbot_fb_color') : '#0084ff';
@@ -1747,9 +1876,12 @@
1747 1876 }
1748 1877 }
1749 1878
1750 1879 function qcld_choose_random($array){
1751 - return $array[array_rand($array)];
1880 + if (is_array($array) && !empty($array)) {
1881 + return $array[array_rand($array)];
1882 + }
1883 + return $array;
1752 1884 }
1753 1885
1754 1886 //User session count
1755 1887 add_action('wp_ajax_qcld_wb_chatbot_session_count', 'qcld_wb_chatbot_session_count');
@@ -1803,15 +1935,68 @@
1803 1935 }
1804 1936
1805 1937 }
1806 1938
1939 +/**
1940 + * Safely sanitize chatbot conversation input.
1941 + *
1942 + * SECURITY FIX (CVE WPBot Stored XSS ≤ 8.6.9):
1943 + * The previous order was: wp_kses() → html_entity_decode() → htmlspecialchars().
1944 + * An attacker could submit entity-encoded payloads (&lt;img onerror=...&gt;) that
1945 + * bypassed wp_kses (which saw inert text), were then decoded back into live markup
1946 + * by html_entity_decode(), and survived into storage and the admin UI.
1947 + *
1948 + * Correct order: html_entity_decode() FIRST → wp_kses() → htmlspecialchars().
1949 + * wp_kses() now sees the real decoded markup and strips forbidden tags/attributes.
1950 + *
1951 + * @param string $data Raw conversation string (already wp_unslash'd by caller).
1952 + * @return string Sanitized, entity-encoded string safe for DB storage.
1953 + */
1807 1954 function qcld_wpbot_input_validation( $data ) {
1808 - $data = html_entity_decode($data);
1809 - $data = trim($data);
1810 - $data = stripslashes($data);
1811 - $data = htmlspecialchars($data);
1955 + // 1. Decode any entity-encoded HTML so wp_kses sees the real markup.
1956 + $data = html_entity_decode( $data, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
1957 + $data = trim( $data );
1958 + $data = stripslashes( $data );
1959 + // 2. Sanitize with a strict allowlist — NOW operating on decoded markup.
1960 + $data = wp_kses( $data, wpbot_get_safe_conversation_tags() );
1961 + // 3. Re-encode for safe DB storage; admin.js decodes for rendering.
1962 + $data = htmlspecialchars( $data, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
1812 1963 return $data;
1813 1964 }
1965 +
1966 +/**
1967 + * Returns the strict HTML allowlist for chatbot conversation content.
1968 + *
1969 + * Critically: no event-handler attributes (onerror, onclick, onload, etc.) are
1970 + * allowed — wp_kses strips any attribute not explicitly listed here.
1971 + * 'img' is intentionally omitted; bot responses that include images should use
1972 + * safe URLs only and can be re-added with only 'src', 'alt', 'class' if needed.
1973 + *
1974 + * @return array<string, array<string, bool>>
1975 + */
1976 +function wpbot_get_safe_conversation_tags() {
1977 + return array(
1978 + 'ul' => array( 'class' => true ),
1979 + 'ol' => array( 'class' => true ),
1980 + 'li' => array( 'class' => true, 'id' => true ),
1981 + 'div' => array( 'class' => true, 'id' => true ),
1982 + 'span' => array( 'class' => true, 'id' => true ),
1983 + 'p' => array( 'class' => true ),
1984 + 'br' => array(),
1985 + 'strong' => array(),
1986 + 'em' => array(),
1987 + 'b' => array(),
1988 + 'i' => array(),
1989 + 'a' => array(
1990 + 'href' => true,
1991 + 'target' => true,
1992 + 'rel' => true,
1993 + 'class' => true,
1994 + ),
1995 + // 'img' intentionally excluded — prevents onerror/onload injection.
1996 + // Add back with only 'src','alt','class' if bot image responses are needed.
1997 + );
1998 +}
1814 1999 add_action('wp_ajax_qcld_small_talk_import', 'qcld_small_talk_import');
1815 2000 function qcld_small_talk_import(){
1816 2001 if ( ! current_user_can( 'manage_options' ) ) {
1817 2002 wp_die();
@@ -1889,4 +2074,7 @@
1889 2074
1890 2075 }
1891 2076 }
1892 2077 }
2078 +
2079 +// AI Actions Chat Preview
2080 +