1((window, document) => 2{ 3 'use strict' 4 5 XF.KeyCaptcha = XF.Element.newHandler({ 6 options: { 7 user: null, 8 session: null, 9 sign: null, 10 sign2: null, 11 }, 12 13 form: null, 14 code: null, 15 16 init () 17 { 18 this.form = this.target.closest('form') 19 XF.uniqueId(this.form) 20 21 this.code = this.form.querySelector('input[name=keycaptcha_code]') 22 XF.uniqueId(this.code) 23 24 this.load() 25 XF.on(this.form, 'ajax-submit:error', this.reload.bind(this)) 26 XF.on(this.form, 'ajax-submit:always', this.reload.bind(this)) 27 }, 28 29 load () 30 { 31 if (window.s_s_c_onload) 32 { 33 this.create() 34 } 35 else 36 { 37 window.s_s_c_user_id = this.options.user 38 window.s_s_c_session_id = this.options.session 39 window.s_s_c_captcha_field_id = this.code.getAttribute('id') 40 window.s_s_c_submit_button_id = 'sbutton-#-r' 41 window.s_s_c_web_server_sign = this.options.sign 42 window.s_s_c_web_server_sign2 = this.options.sign2 43 document.s_s_c_element = this.form 44 document.s_s_c_debugmode = 1 45 46 const div = document.querySelector('#div_for_keycaptcha') 47 if (!div) 48 { 49 document.body.append(XF.createElementFromString('<div id="div_for_keycaptcha"></div>')) 50 } 51 52 XF.loadScript('https://backs.keycaptcha.com/swfs/cap.js') 53 } 54 }, 55 56 create () 57 { 58 window.s_s_c_onload(this.form.getAttribute('id'), this.code.getAttribute('id'), 'sbutton-#-r') 59 }, 60 61 reload (e) 62 { 63 if (!window.s_s_c_onload) 64 { 65 return 66 } 67 68 if (!e.target.matches('form')) 69 { 70 e.preventDefault() 71 } 72 this.load() 73 }, 74 }) 75 76 XF.ReCaptcha = XF.Element.newHandler({ 77 78 options: { 79 sitekey: null, 80 invisible: null, 81 }, 82 83 reCaptchaTarget: null, 84 85 reCaptchaId: null, 86 invisibleValidated: false, 87 reloading: false, 88 89 init () 90 { 91 if (!this.options.sitekey) 92 { 93 return 94 } 95 96 const form = this.target.closest('form') 97 98 if (this.options.invisible) 99 { 100 const reCaptchaTarget = document.createElement('div') 101 const formRow = this.target.closest('.formRow') 102 103 XF.display(formRow, 'none') 104 formRow.insertAdjacentElement('afterend', reCaptchaTarget) 105 106 this.reCaptchaTarget = reCaptchaTarget 107 108 XF.on(form, 'ajax-submit:before', this.beforeSubmit.bind(this)) 109 } 110 else 111 { 112 this.reCaptchaTarget = this.target 113 } 114 115 XF.on(form, 'ajax-submit:error', this.reload.bind(this)) 116 XF.on(form, 'ajax-submit:always', this.reload.bind(this)) 117 118 if (window.grecaptcha) 119 { 120 this.create() 121 } 122 else 123 { 124 XF.ReCaptcha.Callbacks.push(this.create.bind(this)) 125 126 XF.loadScript('https://www.recaptcha.net/recaptcha/api.js?onload=XFReCaptchaCallback&render=explicit') 127 } 128 }, 129 130 create () 131 { 132 if (!window.grecaptcha) 133 { 134 return 135 } 136 137 const options = { 138 sitekey: this.options.sitekey, 139 theme: XF.StyleVariation.getColorScheme(), 140 } 141 if (this.options.invisible) 142 { 143 options.size = 'invisible' 144 options.callback = this.complete.bind(this) 145 } 146 this.reCaptchaId = grecaptcha.render(this.reCaptchaTarget, options) 147 }, 148 149 beforeSubmit (e) 150 { 151 if (!this.invisibleValidated) 152 { 153 e.preventDefault() 154 e.preventSubmit = true 155 156 grecaptcha.execute() 157 } 158 }, 159 160 complete () 161 { 162 this.invisibleValidated = true 163 const form = this.target.closest('form') 164 XF.trigger(form, 'submit') 165 }, 166 167 reload () 168 { 169 if (!window.grecaptcha || this.reCaptchaId === null || this.reloading) 170 { 171 return 172 } 173 174 this.reloading = true 175 176 setTimeout(() => 177 { 178 grecaptcha.reset(this.reCaptchaId) 179 this.reloading = false 180 this.invisibleValidated = false 181 }, 50) 182 }, 183 }) 184 XF.ReCaptcha.Callbacks = [] 185 window.XFReCaptchaCallback = () => 186 { 187 for (const callback of XF.ReCaptcha.Callbacks) 188 { 189 callback() 190 } 191 } 192 193 XF.Turnstile = XF.Element.newHandler({ 194 195 options: { 196 sitekey: null, 197 action: '', 198 }, 199 200 turnstileTarget: null, 201 202 turnstileId: null, 203 reloading: false, 204 205 init () 206 { 207 if (!this.options.sitekey) 208 { 209 return 210 } 211 212 const form = this.target.closest('form') 213 214 this.turnstileTarget = this.target 215 216 XF.on(form, 'ajax-submit:error', this.reload.bind(this)) 217 XF.on(form, 'ajax-submit:always', this.reload.bind(this)) 218 219 if (window.turnstile) 220 { 221 this.create() 222 } 223 else 224 {
225 XF.Turnstile.Callbacks.push(this.create.bind(this)) 226 227 XF.loadScript('https://challenges.cloudflare.com/turnstile/v0/api.js?onload=XFTurnstileCaptchaCallback') 228 } 229 }, 230 231 create () 232 { 233 if (!window.turnstile) 234 { 235 return 236 } 237 238 const options = { 239 sitekey: this.options.sitekey, 240 theme: XF.StyleVariation.getColorScheme(), 241 action: this.options.action, 242 } 243 this.turnstileId = window.turnstile.render(this.turnstileTarget, options) 244 }, 245 246 complete () 247 { 248 const form = this.target.closest('form') 249 XF.trigger(form, 'submit') 250 }, 251 252 reload () 253 { 254 if (!window.turnstile || this.turnstileId === null || this.reloading) 255 { 256 return 257 } 258 259 this.reloading = true 260 261 setTimeout(() => 262 { 263 window.turnstile.reset(this.turnstileId) 264 this.reloading = false 265 }, 50) 266 }, 267 }) 268 XF.Turnstile.Callbacks = [] 269 window.XFTurnstileCaptchaCallback = () => 270 { 271 for (const callback of XF.Turnstile.Callbacks) 272 { 273 callback() 274 } 275 } 276 277 XF.HCaptcha = XF.Element.newHandler({ 278 options: { 279 sitekey: null, 280 invisible: null, 281 }, 282 283 hCaptchaTarget: null, 284 285 hCaptchaId: null, 286 invisibleValidated: false, 287 reloading: false, 288 289 init () 290 { 291 if (!this.options.sitekey) 292 { 293 return 294 } 295 296 const form = this.target.closest('form') 297 298 XF.on(form, 'ajax-submit:error', this.reload.bind(this)) 299 XF.on(form, 'ajax-submit:always', this.reload.bind(this)) 300 301 if (this.options.invisible) 302 { 303 const hCaptchaTarget = document.createElement('div') 304 const formRow = this.target.closest('.formRow') 305 306 XF.display(formRow, 'none') 307 formRow.insertAdjacentElement('afterend', hCaptchaTarget) 308 309 this.hCaptchaTarget = hCaptchaTarget 310 311 XF.on(form, 'ajax-submit:before', this.beforeSubmit.bind(this)) 312 } 313 else 314 { 315 this.hCaptchaTarget = this.target 316 } 317 318 if (window.hcaptcha) 319 { 320 this.create() 321 } 322 else 323 { 324 XF.HCaptcha.Callbacks.push(this.create.bind(this)) 325 326 XF.loadScript('https://hcaptcha.com/1/api.js?onload=XFHCaptchaCallback&render=explicit') 327 } 328 }, 329 330 create () 331 { 332 if (!window.hcaptcha) 333 { 334 return 335 } 336 337 const options = { 338 sitekey: this.options.sitekey, 339 theme: XF.StyleVariation.getColorScheme(), 340 } 341 if (this.options.invisible) 342 { 343 options.size = 'invisible' 344 options.callback = this.complete.bind(this) 345 } 346 this.hCaptchaId = window.hcaptcha.render(this.hCaptchaTarget, options) 347 }, 348 349 beforeSubmit (e) 350 { 351 if (!this.invisibleValidated) 352 { 353 e.preventDefault() 354 e.preventSubmit = true 355 356 window.hcaptcha.execute(this.hCaptchaId) 357 } 358 }, 359 360 complete () 361 { 362 this.invisibleValidated = true 363 const form = this.target.closest('form') 364 XF.trigger(form, 'submit') 365 }, 366 367 reload () 368 { 369 if (!window.hcaptcha || this.hCaptchaId === null || this.reloading) 370 { 371 return 372 } 373 374 this.reloading = true 375 376 setTimeout(() => 377 { 378 window.hcaptcha.reset(this.hCaptchaId) 379 this.reloading = false 380 this.invisibleValidated = false 381 }, 50) 382 }, 383 }) 384 XF.HCaptcha.Callbacks = [] 385 window.XFHCaptchaCallback = () => 386 { 387 for (const callback of XF.HCaptcha.Callbacks) 388 { 389 callback() 390 } 391 } 392 393 XF.QaCaptcha = XF.Element.newHandler({ 394 395 options: { 396 url: null, 397 }, 398 399 reloading: false, 400 401 init () 402 { 403 if (!this.options.url) 404 { 405 return 406 } 407 408 const form = this.target.closest('form') 409 410 XF.on(form, 'ajax-submit:error', this.reload.bind(this)) 411 XF.on(form, 'ajax-submit:always', this.reload.bind(this)) 412 }, 413 414 reload () 415 { 416 if (this.reloading) 417 { 418 return 419 } 420 421 this.reloading = true 422 423 XF.ajax('get', this.options.url, this.show.bind(this)) 424 }, 425 426 show (data) 427 { 428 const target = this.target 429 430 XF.setupHtmlInsert(data.html, (html, container, onComplete) => 431 { 432 XF.display(html, 'none') 433 target.after(html) 434 435 XF.Animate.fadeUp(target, { 436 speed: XF.config.speed.fast, 437 complete () 438 { 439 XF.Animate.fadeDown(html, { 440 speed: XF.config.speed.fast, 441 }) 442 target.remove() 443 }, 444 }) 445 446 this.reloading = false 447 onComplete(false, html) 448 }) 449 }, 450 }) 451 452 // ################################## GUEST CAPTCHA HANDLER ########################################### 453 454 XF.GuestCaptcha = XF.Element.newHandler({ 455 456 options: { 457 url: 'index.php?misc/captcha&with_row=1', 458 captchaContext: '', 459 target: '.js-captchaContainer', 460 skip: '[name=more_options]', 461 }, 462 463 captchaContainer: null, 464 465 initialized: false, 466 467 init () 468 {
469 const form = this.target 470 this.captchaContainer = form.querySelector(this.options.target) 471 472 XF.on(form, 'focusin', this.initializeCaptcha.bind(this)) 473 XF.on(form, 'submit', this.submit.bind(this)) 474 XF.on(form, 'ajax-submit:before', this.submit.bind(this)) 475 }, 476 477 initializeCaptcha (e) 478 { 479 const activeElement = document.activeElement 480 481 if (this.initialized || activeElement.matches(this.options.skip)) 482 { 483 return 484 } 485 486 const rowType = this.captchaContainer.dataset.rowType || '' 487 488 XF.ajax( 489 'get', 490 XF.canonicalizeUrl(this.options.url), 491 { 492 row_type: rowType, 493 context: this.options.captchaContext, 494 }, 495 this.showCaptcha.bind(this), 496 ) 497 498 this.initialized = true 499 }, 500 501 showCaptcha (data) 502 { 503 XF.setupHtmlInsert(data.html, (html, container, onComplete) => 504 { 505 this.captchaContainer.replaceWith(html) 506 507 onComplete() 508 }) 509 }, 510 511 submit (e) 512 { 513 if (!this.initialized) 514 { 515 const activeElement = document.activeElement 516 517 if (!activeElement.matches(this.options.skip)) 518 { 519 e.preventDefault() 520 e.stopPropagation() 521 } 522 } 523 }, 524 }) 525 526 XF.Element.register('key-captcha', 'XF.KeyCaptcha') 527 XF.Element.register('re-captcha', 'XF.ReCaptcha') 528 XF.Element.register('turnstile', 'XF.Turnstile') 529 XF.Element.register('h-captcha', 'XF.HCaptcha') 530 XF.Element.register('qa-captcha', 'XF.QaCaptcha') 531 532 XF.Element.register('guest-captcha', 'XF.GuestCaptcha') 533})(window, document)
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.