1(function () { 2 var captchaPath = '/bitrix/tools/captcha.php'; 3 var captchaSelector = 'img[src*="' + captchaPath + '"]'; 4 var counter = 0; 5 6 function escapeHtml(value) { 7 return String(value).replace(/[&<>"']/g, function (symbol) { 8 return { 9 '&': '&', 10 '<': '<', 11 '>': '>', 12 '"': '"', 13 "'": ''' 14 }[symbol]; 15 }); 16 } 17 18 function sidFromUrl(url) { 19 var match = String(url || '').match(/[?&]captcha_sid=([^&#]+)/); 20 return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : ''; 21 } 22 23 function blockId(sid) { 24 counter += 1; 25 if (sid) { 26 return 'bx365-captcha-sid-' + sid.replace(/[^a-z0-9_-]/gi, '-') + '-' + counter; 27 } 28 29 return 'bx365-captcha-' + counter; 30 } 31 32 function ensureBlock(img, sid) { 33 var block = img.nextElementSibling; 34 if (block && block.classList && block.classList.contains('bx365-captcha')) { 35 if (sid) { 36 block.setAttribute('data-bx365-captcha-sid', sid); 37 } 38 return block; 39 } 40 41 var options = window.bx365CaptchaOptions || {}; 42 var width = parseInt(options.canvasWidth, 10) || 180; 43 var height = parseInt(options.canvasHeight, 10) || 50; 44 var placeholder = options.placeholderText || ''; 45 var refreshLabel = options.refreshLabel || placeholder; 46 var errorText = options.errorText || ''; 47 48 block = document.createElement('div'); 49 block.id = blockId(sid); 50 block.className = 'bx365-captcha'; 51 if (sid) { 52 block.setAttribute('data-bx365-captcha-sid', sid); 53 } 54 block.innerHTML = '<canvas class="bx365-captcha__canvas" width="' + width + '" height="' + height + '"></canvas><span class="bx365-captcha__placeholder">' + escapeHtml(placeholder) + '</span><span class="bx365-captcha__error" role="alert">' + escapeHtml(errorText) + '</span><span class="bx365-captcha__overlay"><button class="bx365-captcha__refresh" type="button" aria-label="' + escapeHtml(refreshLabel) + '"><span class="bx365-captcha__refresh-icon" aria-hidden="true"></span></button></span><span class="bx365-captcha__progress-bar"></span>'; 55 img.parentNode.insertBefore(block, img.nextSibling); 56 57 return block; 58 } 59 60 function processImage(img, refreshExisting) { 61 if (img.bx365CaptchaInternalUpdate) { 62 img.bx365CaptchaInternalUpdate = false; 63 return; 64 } 65 66 var sid = sidFromUrl(img.getAttribute('src')); 67 var block = img.nextElementSibling; 68 var hasBlock = block && block.classList && block.classList.contains('bx365-captcha'); 69 70 img.setAttribute('bx365-captcha-source', img.getAttribute('bx365-captcha-source') || (hasBlock ? 'backend' : 'front')); 71 block = ensureBlock(img, sid); 72 73 if (refreshExisting && hasBlock && window.BX365Captcha && typeof window.BX365Captcha.load === 'function') { 74 window.BX365Captcha.load(block); 75 } 76 } 77 78 function scan(root) { 79 if (root.matches && root.matches(captchaSelector)) { 80 processImage(root, false); 81 } 82 if (root.querySelectorAll) { 83 Array.prototype.forEach.call(root.querySelectorAll(captchaSelector), function (img) { 84 processImage(img, false); 85 }); 86 } 87 } 88 89 function preventCaptchaCopy(event) { 90 var target = event.target; 91 if (target && target.closest && target.closest('.bx365-captcha')) { 92 event.preventDefault(); 93 } 94 } 95 96 var observer = new MutationObserver(function (mutations) { 97 mutations.forEach(function (mutation) { 98 if (mutation.type === 'attributes' && mutation.target.matches && mutation.target.matches(captchaSelector)) { 99 processImage(mutation.target, true); 100 } 101 102 Array.prototype.forEach.call(mutation.addedNodes || [], function (node) { 103 if (node.nodeType === 1) { 104 scan(node); 105 } 106 }); 107 }); 108 }); 109 110 if (document.readyState === 'loading') { 111 document.addEventListener('DOMContentLoaded', function () { 112 scan(document); 113 }); 114 } else { 115 scan(document); 116 } 117 118 document.addEventListener('contextmenu', preventCaptchaCopy, true); 119 document.addEventListener('dragstart', preventCaptchaCopy, true); 120 document.addEventListener('selectstart', preventCaptchaCopy, true); 121 122 observer.observe(document.documentElement, { 123 childList: true, 124 subtree: true, 125 attributes: true, 126 attributeFilter: ['src'] 127 }); 128})();
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.