1(function () { 2 'use strict'; 3 4 var initialized = {}; 5 var pending = {}; 6 7 function sha256(value) { 8 return crypto.subtle.digest('SHA-256', new TextEncoder().encode(value)).then(function (buffer) { 9 return Array.prototype.map.call(new Uint8Array(buffer), function (byte) { 10 return byte.toString(16).padStart(2, '0'); 11 }).join(''); 12 }); 13 } 14 15 async function createProof(token, difficulty) { 16 if (!difficulty) { 17 return 0; 18 } 19 20 var prefix = '0'.repeat(difficulty); 21 var nonce = 0; 22 while (nonce < 2000000) { 23 var hash = await sha256(token + '|' + nonce); 24 if (hash.indexOf(prefix) === 0) { 25 return nonce; 26 } 27 nonce++; 28 } 29 throw new Error('Proof generation failed.'); 30 } 31 32 async function prepare(formId, force) { 33 var form = document.getElementById('gform_' + formId); 34 if (!form || (!force && initialized[formId] === form)) { 35 return; 36 } 37 if (pending[formId]) { 38 return pending[formId]; 39 } 40 initialized[formId] = form; 41 42 var tokenField = form.querySelector('[name="gflg_token"]'); 43 var proofField = form.querySelector('[name="gflg_proof"]'); 44 var readyField = form.querySelector('[name="gflg_ready"]'); 45 if (!tokenField || !proofField || !readyField || !window.crypto || !window.crypto.subtle) { 46 return; 47 } 48 49 readyField.value = '0'; 50 pending[formId] = (async function () { 51 try { 52 var body = new URLSearchParams({action: GFLocalGuard.action, form_id: String(formId)}); 53 var response = await fetch(GFLocalGuard.ajaxUrl, { 54 method: 'POST', 55 credentials: 'same-origin', 56 headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, 57 body: body.toString() 58 }); 59 var result = await response.json(); 60 if (!result.success) { 61 return; 62 } 63 tokenField.value = result.data.token; 64 proofField.value = await createProof(result.data.token, Number(result.data.difficulty || 0)); 65 readyField.value = '1'; 66 } catch (error) { 67 readyField.value = '0'; 68 } finally { 69 delete pending[formId]; 70 } 71 }()); 72 73 return pending[formId]; 74 } 75 76 function guardEarlySubmit(formId, form) { 77 if (form.dataset.gflgSubmitGuard === '1') { 78 return; 79 } 80 form.dataset.gflgSubmitGuard = '1'; 81 var submitter = null; 82 form.addEventListener('click', function (event) { 83 var candidate = event.target.closest('button[type="submit"], input[type="submit"]'); 84 if (candidate) { 85 submitter = candidate; 86 } 87 }, true); 88 form.addEventListener('submit', function (event) { 89 var readyField = form.querySelector('[name="gflg_ready"]'); 90 if (!readyField || readyField.value === '1') { 91 return; 92 } 93 event.preventDefault(); 94 event.stopImmediatePropagation(); 95 Promise.resolve(pending[formId] || prepare(formId, true)).then(function () { 96 if (readyField.value === '1') { 97 if (form.requestSubmit) { 98 form.requestSubmit(submitter || undefined); 99 } else if (submitter) { 100 submitter.click(); 101 } 102 } 103 }); 104 }, true); 105 } 106 107 function boot() { 108 (window.GFLocalGuardForms || []).forEach(function (formId) { 109 var form = document.getElementById('gform_' + formId); 110 if (form) { 111 guardEarlySubmit(formId, form); 112 } 113 prepare(formId); 114 }); 115 } 116 117 document.addEventListener('DOMContentLoaded', boot); 118 document.addEventListener('gform/postRender', function (event) { 119 if (event.detail && event.detail.formId) { 120 delete initialized[event.detail.formId]; 121 } 122 boot(); 123 }); 124 document.addEventListener('gform_page_loaded', function (event) { 125 var formId = event.detail && event.detail.form_id; 126 if (formId) { 127 delete initialized[formId]; 128 } 129 boot(); 130 }); 131 132 if (window.jQuery) { 133 window.jQuery(document).on('gform_post_render gform_page_loaded', function (event, formId) { 134 if (formId) { 135 delete initialized[formId]; 136 } 137 boot(); 138 }); 139 } 140 141 if (document.readyState !== 'loading') { 142 boot(); 143 } 144 145 // Refresh long-lived forms before their server token expires. 146 window.setInterval(function () {
147 (window.GFLocalGuardForms || []).forEach(function (formId) { 148 prepare(formId, true); 149 }); 150 }, 25 * 60 * 1000); 151}());
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.