1(function() { 2 // Use the dynamically set language object from PHP 3 var sidebarLang = window.sidebarLang || { 4 please_complete_verification_above: "Please complete the verification above", 5 completing_verification: "Completing verification...", 6 token_received_submitting: "Token received, submitting...", 7 captcha_initialization_failed: "Captcha initialization failed. Please refresh the page.", 8 captcha_widget_error: "Captcha widget error. Please refresh the page.", 9 captcha_not_ready: "Captcha not ready. Please refresh the page.", 10 captcha_error_occurred: "A captcha error occurred. Please refresh and try again.", 11 captcha_verification_timeout: "Please complete the verification above. If you don't see it, refresh the page.", 12 captcha_error: "Captcha error. Please refresh and try again.", 13 please_wait: "Please wait...", 14 validating_captcha: "Validating verification...", 15 please_enter_email: ({ar: "ÙØ±Ø¬Ù Ø¥Ø¯Ø®Ø§Ù Ø¨Ø±ÙØ¯Ù Ø§ÙØ¥ÙÙØªØ±ÙÙÙ.", zh: "è«è¼¸å ¥ä½ çé»åéµä»¶ã", es: "Por favor, introduce tu dirección de correo electrónico.", fr: "Veuillez entrer votre adresse e-mail."}[(document.documentElement.lang || "").slice(0, 2)] || "Please enter your email address.") 16 }; 17 18 var sidebarTurnstileToken = null; 19 var sidebarTurnstileWidgetId = null; 20 var sidebarTurnstileReady = false; 21 var sidebarSubscriptionInitiated = false; // Track if user has clicked sidebar subscribe button 22 23 function initSidebarTurnstile() { 24 var widgetElement = document.getElementById('sidebar-turnstile-widget'); 25 if (!widgetElement || typeof turnstile === 'undefined') { 26 return false; 27 } 28 if (sidebarTurnstileReady) { 29 return true; 30 } 31 32 // Initialize Turnstile widget when needed 33 try { 34 // Add cf-turnstile class only when we're actually rendering 35 widgetElement.className = 'cf-turnstile'; 36 37 sidebarTurnstileWidgetId = turnstile.render(widgetElement, { 38 sitekey: '0x4AAAAAAB_JWwJHidndT13X', 39 size: 'normal', // Normal size for visible widget when VPN detected 40 callback: function(token) { 41 if (token && token.length > 10) { 42 sidebarTurnstileToken = token; 43 44 // Show token received message 45 // Only update UI if user has actually initiated subscription 46 var $result = jQuery("#sidebar-newsletter-result"); 47 if ($result.length && !$result.text().includes('Completing') && !$result.text().includes('Token received')) { 48 $result.html("" + sidebarLang.token_received_submitting + ""); 49 } 50 51 // Don't auto-submit - wait for polling to detect token and submit 52 // This prevents double submissions 53 } else { 54 sidebarTurnstileToken = null; 55 } 56 }, 57 'error-callback': function(error) { 58 var $result = jQuery("#sidebar-newsletter-result"); 59 if ($result.length) { 60 $result.html("" + sidebarLang.captcha_error_occurred + ""); 61 } 62 }, 63 'expired-callback': function() { 64 sidebarTurnstileToken = null; 65 }, 66 theme: 'dark' 67 }); 68 69 sidebarTurnstileReady = true; 70 return true; 71 } catch(e) { 72 return false; 73 } 74 } 75 76 function submitSidebarForm(cfToken) { 77 if (typeof jQuery === 'undefined') { 78 return; 79 } 80 var $ = jQuery; 81 var $btn = jQuery("#sidebar-newsletter-submit"); 82 var email = jQuery("#sidebar-newsletter-email").val(); 83 var AJAX_url = '/newsletter/subscribe/ajax_subscribe.php?ModPageSpeed=off'; 84 85 // Button is already disabled when clicked, but ensure it stays disabled 86 if (!$btn.prop("disabled")) { 87 $btn.prop("disabled", true).css("opacity", "0.6"); 88 } 89 90 // Security tokens removed from client-side code - validation is server-side only 91 var postData = { 92 emailSubscriber: email 93 }; 94 95 if (cfToken && cfToken !== null && cfToken !== '' && cfToken !== undefined) { 96 postData['cf-turnstile-response'] = cfToken; 97 } 98 99 // Store jQuery reference for use in callbacks 100 var jQueryRef = jQuery; 101 102 jQuery.ajax({ 103 url: AJAX_url, 104 type: "POST", 105 method: "POST", 106 dataType: "json", 107 timeout: 10000, 108 data: postData, 109 success: function (data) { 110 if (typeof data === 'string') { 111 try { 112 data = JSON.parse(data); 113 } catch(e) { 114 jQueryRef("#sidebar-newsletter-result").html("Subscription failed. Please try again.").addClass('error'); 115 $btn.prop("disabled", false).css("opacity", "1"); 116 return; 117 } 118 } 119 120 if(data.status == 'REQUIRES_CAPTCHA' || data.requires_captcha == true) { 121 console.log('Sidebar Newsletter: VPN/captcha required - initializing Turnstile widget'); 122 123 // Show the captcha container first 124 jQueryRef("#sidebar-turnstile-container").slideDown(300); 125 126 // Show message below captcha after a brief delay 127 setTimeout(function() { 128 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.please_complete_verification_above + ":").removeClass('error'); 129 }, 350); 130 131 // Ensure widget is initialized 132 if (!sidebarTurnstileReady) { 133 if (!initSidebarTurnstile()) { 134 $btn.prop("disabled", false).css("opacity", "1"); 135 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.captcha_initialization_failed + "").addClass('error'); 136 return; 137 } 138 // Wait a moment for widget to render 139 setTimeout(function() { 140 executeSidebarTurnstile(); 141 }, 500); 142 } else {
143 // Widget already initialized, just execute it 144 executeSidebarTurnstile(); 145 } 146 147 function executeSidebarTurnstile() { 148 if (sidebarTurnstileWidgetId && typeof turnstile !== 'undefined') { 149 try { 150 // Clear any existing token before starting 151 sidebarTurnstileToken = null; 152 153 // For visible compact widget, we don't need to call execute() - it runs automatically 154 // Just reset and wait for the callback to fire 155 if (typeof sidebarTurnstileWidgetId === 'string') { 156 try { 157 turnstile.reset(sidebarTurnstileWidgetId); 158 } catch(resetErr) { 159 // Ignore reset errors 160 } 161 // Start polling for token (callback will fire when user completes challenge) 162 startTokenPolling(); 163 } else { 164 $btn.prop("disabled", false).css("opacity", "1"); 165 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.captcha_widget_error + "").addClass('error'); 166 return; 167 } 168 169 function startTokenPolling() { 170 var attempts = 0; 171 var maxAttempts = 240; // 60 seconds for visible widget (user needs time to interact) 172 173 var checkToken = setInterval(function() { 174 attempts++; 175 var token = sidebarTurnstileToken; 176 177 // Try to get token directly from Turnstile 178 if (!token && sidebarTurnstileWidgetId) { 179 try { 180 if (typeof sidebarTurnstileWidgetId === 'string') { 181 token = turnstile.getResponse(sidebarTurnstileWidgetId); 182 if (token && token.length > 10) { 183 sidebarTurnstileToken = token; 184 } 185 } 186 } catch(e) { 187 // Ignore errors 188 } 189 } 190 191 // Also check the widget element directly for the token attribute 192 if (!token) { 193 try { 194 var widgetEl = document.getElementById('sidebar-turnstile-widget'); 195 if (widgetEl) { 196 var responseInput = widgetEl.querySelector('input[name="cf-turnstile-response"]'); 197 if (responseInput && responseInput.value) { 198 token = responseInput.value; 199 if (token.length > 10) { 200 sidebarTurnstileToken = token; 201 } 202 } 203 } 204 } catch(e) { 205 // Ignore errors 206 } 207 } 208 209 if (token && token.length > 10) { 210 clearInterval(checkToken); 211 sidebarTurnstileToken = token; 212 // Show validating message before submitting 213 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.validating_captcha + "").removeClass('error'); 214 submitSidebarForm(token); 215 } else if (attempts >= maxAttempts) { 216 clearInterval(checkToken); 217 $btn.prop("disabled", false).css("opacity", "1"); 218 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.captcha_verification_timeout + "").addClass('error'); 219 } 220 }, 250); 221 } 222 // Don't start polling here - it's now in startTokenPolling() 223 return; 224 } catch(e) { 225 $btn.prop("disabled", false).css("opacity", "1"); 226 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.captcha_error + "").addClass('error'); 227 } 228 } else { 229 $btn.prop("disabled", false).css("opacity", "1"); 230 jQueryRef("#sidebar-newsletter-result").html("" + sidebarLang.captcha_not_ready + "").addClass('error'); 231 } 232 } 233 return; // Don't continue processing - wait for captcha 234 } 235 236 if (data && data.message) { 237 jQueryRef("#sidebar-newsletter-result").html(data.message).removeClass('error'); 238 } else { 239 jQueryRef("#sidebar-newsletter-result").html("Subscription failed. Please try again.").addClass('error'); 240 } 241 242 if (data.status === "SUCCESS") { 243 setTimeout(function(){ 244 if (typeof closeNewsletterBar === "function") { 245 closeNewsletterBar(); 246 } else { 247 jQueryRef("#newsletter-bar").fadeOut(300); 248 } 249 var expires = new Date(); 250 expires.setTime(expires.getTime() + (3650*24*60*60*1000)); 251 document.cookie = "is_subscribed=1; expires=" + expires.toUTCString() + "; path=/"; 252 }, 6000); 253 } else { 254 $btn.prop("disabled", false).css("opacity", "1"); 255 } 256 }, 257 error: function(xhr, status, error) { 258 var errorMessage = "Error: " + error + ""; 259 try { 260 if (xhr.responseText) { 261 var errorData = JSON.parse(xhr.responseText); 262 if (errorData && errorData.message) { 263 errorMessage = errorData.message; 264 } 265 } 266 } catch(e) { 267 // Use default error message 268 } 269 jQueryRef("#sidebar-newsletter-result").html(errorMessage).addClass('error'); 270 $btn.prop("disabled", false).css("opacity", "1"); 271 } 272 }); 273 } 274 275 function initSidebarNewsletter() { 276 if (typeof jQuery === 'undefined') { 277 setTimeout(initSidebarNewsletter, 100); 278 return; 279 } 280 var $ = jQuery; 281 282 // Don't auto-initialize Turnstile widget on page load 283 // Only initialize when VPN is detected and user clicks subscribe 284 // This prevents auto-completion and premature callback firing 285 286 // Attach click handler 287 var $submitBtn = $("#sidebar-newsletter-submit"); 288 if ($submitBtn.length === 0) { 289 setTimeout(initSidebarNewsletter, 1000); 290 return; 291 } 292 293 $submitBtn.off('click').on("click", function(event) { 294 event.preventDefault(); 295 event.stopPropagation(); 296 var email = jQuery("#sidebar-newsletter-email").val(); 297 if (!email || email.trim() === '') { 298 $("#sidebar-newsletter-result").html("" + sidebarLang.please_enter_email + "").addClass('error'); 299 return; 300 } 301 // Mark that user has initiated subscription 302 sidebarSubscriptionInitiated = true; 303 // Show loading message immediately 304 $("#sidebar-newsletter-result").html("" + sidebarLang.please_wait + "").removeClass('error'); 305 $submitBtn.prop("disabled", true).css("opacity", "0.6"); 306 submitSidebarForm(null); 307 }); 308 309 // ENTER key 310 $("#sidebar-newsletter-email").off("keypress").on("keypress", function(e) { 311 if (e.which == 13) { 312 e.preventDefault(); 313 $("#sidebar-newsletter-submit").click(); 314 } 315 }); 316 } 317 318 // Start initialization 319 if (document.readyState === 'loading') { 320 document.addEventListener('DOMContentLoaded', initSidebarNewsletter); 321 } else { 322 initSidebarNewsletter(); 323 } 324})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.