PageSourceSearch

https://optplenka.com/wp-content/plugins/nocaptcha-spam-filter-for-contact-form-7/inc/main.js?ver=1.1.0

js optplenka.com collected 2026-10-08 10:18:37 UTC 9,370 bytes, 183 lines download raw bytes

1(function () {
2    'use strict';
3
4    /* ── Server-side data ────────────────────────────────────────────────────
5     * Injected by wp_add_inline_script() in the plugin PHP file.
6     * cf7ncspData = { embedded, endpoint, ttl, minTime, msgFail }
7     * ──────────────────────────────────────────────────────────────────────── */
8    var embedded = cf7ncspData.embedded;
9    var ENDPOINT = cf7ncspData.endpoint;
10    var TTL      = cf7ncspData.ttl;
11    var MIN_TIME = cf7ncspData.minTime;
12    var MSG_FAIL = cf7ncspData.msgFail;
13
14    /* ── Stale-token detection ───────────────────────────────────────────────
15     * A token is considered valid when:
16     * - Its timestamp is not in the future (guards against clock skew).
17     * - It will not expire before the user has time to submit the form.
18     * We subtract MIN_TIME from TTL to leave a safe submission window.
19     * ──────────────────────────────────────────────────────────────────────── */
20    function embeddedIsValid() {
21        var now = Math.floor( Date.now() / 1000 );
22        var age = now - parseInt( embedded.ts, 10 );
23        return age >= 0 && age < ( TTL - MIN_TIME );
24    }
25
26    /* ── Form field injection ────────────────────────────────────────────────
27     * Writes token, timestamp, and nonce into the three hidden fields.
28     * Safe to call multiple times; each call overwrites the previous value.
29     * ──────────────────────────────────────────────────────────────────────── */
30    function fillForm( form, payload ) {
31        var t = form.querySelector( '[name="form-token"]' );
32        var s = form.querySelector( '[name="form-ts"]' );
33        var n = form.querySelector( '[name="form-nonce"]' );
34        if ( t ) t.value = payload.token;
35        if ( s ) s.value = payload.ts;
36        if ( n ) n.value = payload.nonce;
37    }
38
39    /* ── REST fallback ───────────────────────────────────────────────────────
40     * Fetches a fresh token from the server. A 3-second timeout prevents
41     * the form from hanging indefinitely on slow connections.
42     * ──────────────────────────────────────────────────────────────────────── */
43    function fetchFreshToken() {
44        var fetchPromise = fetch( ENDPOINT, { credentials: 'same-origin' } )
45            .then( function ( r ) {
46                if ( ! r.ok ) throw new Error( 'cf7ncsp: token request failed (' + r.status + ')' );
47                return r.json();
48            } );
49
50        var timeout = new Promise( function ( _, reject ) {
51            setTimeout( function () {
52                reject( new Error( 'cf7ncsp: token request timed out' ) );
53            }, 3000 );
54        } );
55
56        return Promise.race( [ fetchPromise, timeout ] );
57    }
58
59    /* ── Per-form initialisation ─────────────────────────────────────────────
60     * Each form on the page gets its own token promise and submit guard.
61     * Forms are independent: a slow fetch on one does not block another.
62     * ──────────────────────────────────────────────────────────────────────── */
63    function initForm( form ) {
64
65        /*
66         * `ready` is a Promise that resolves to a valid payload object.
67         *
68         * - Embedded token is fresh → resolves immediately (no network call).
69         * - Embedded token is stale → resolves after the REST fetch completes.
70         *
71         * Either way the form fields are populated as soon as possible,
72         * before the user hits Submit.
73         */
74        var ready = embeddedIsValid()
75            ? Promise.resolve( embedded )
76            : fetchFreshToken();
77
78        ready.then( function ( payload ) { fillForm( form, payload ); } );
79
80        /*
81         * Submission guard.
82         * Prevents double-click races and ensures a token is always present
83         * before CF7 fires its AJAX request.
84         */
85        var locking = false;
86
87        /*
88         * Listen in the CAPTURE phase so this handler runs before CF7's own
89         * submit listener. If the token field is already populated we do
90         * nothing and let CF7 proceed normally.
91         *
92         * If the field is empty (token fetch still in flight or failed):
93         * 1. Prevent the default form submission.
94         * 2. Wait for (or retry) the token fetch.
95         * 3. Re-trigger via btn.click() to hand control back to CF7.
96         *
97         * Using btn.click() rather than form.submit() is critical — it
98         * preserves CF7's internal AJAX flow and validation pipeline.
99         */
100        form.addEventListener( 'submit', function ( e ) {
101
102            var tokenField = form.querySelector( '[name="form-token"]' );
103
104            // Token is present — CF7 can proceed uninterrupted.
105            if ( tokenField && tokenField.value ) return;
106
107            // Guard against re-entrant calls (e.g. rapid double-click).
108            if ( locking ) return;
109            locking = true;
110
111            e.preventDefault();
112            e.stopImmediatePropagation();
113
114            var btn = form.querySelector( 'button, input[type="submit"]' );
115            if ( btn ) btn.disabled = true;
116
117            // Chain onto the in-flight promise; retry once on failure.
118            ready = ready
119                .catch( function () { return fetchFreshToken(); } )
120                .then( function ( payload ) {
121                    fillForm( form, payload );
122                    locking = false;
123                    if ( btn ) btn.disabled = false;
124                    if ( btn ) btn.click(); // re-triggers CF7's submit handler
125                } )
126                .catch( function () {
127                    locking = false;
128                    if ( btn ) btn.disabled = false;
129                    alert( MSG_FAIL );
130                } );
131
132        }, true ); // true = capture phase — must run before CF7's listener
133
134        /*
135         * Re-arm the form after every submission outcome so the user can
136         * retry immediately without reloading the page.
137         *
138         * wpcf7mailsent — email delivered successfully
139         * wpcf7submit   — any submission (success or server-side failure)
140         * wpcf7invalid  — CF7 client-side validation failed
141         * wpcf7spam     — server flagged the submission as spam
142         */
143        function refreshToken() {
144            ready = fetchFreshToken().then( function ( payload ) {
145                fillForm( form, payload );
146                return payload;
147            } );
148        }
149
150        /*
151         * Re-arm only on genuine success or client-side validation failure.
152         *
153         * wpcf7submit and wpcf7spam are intentionally NOT listed here.
154         * Refreshing the token after a spam block would reset the server-side
155         * elapsed-time counter, allowing a bot to bypass CF7NCSP_MIN_TIME by
156         * re-submitting immediately after a rejection.
157         *
158         * wpcf7invalid fires when CF7's own field validation fails (e.g. a
159         * required field is empty). The anti-spam check never ran in that
160         * case, so issuing a fresh token is both safe and necessary so the
161         * user can correct and re-submit.
162         *
163         * wpcf7mailsent fires only when the email was actually delivered.
164         */
165        form.addEventListener( 'wpcf7mailsent', refreshToken );
166        form.addEventListener( 'wpcf7invalid',  refreshToken );
167    }
168
169    /* ── Bootstrap ───────────────────────────────────────────────────────────
170     * Attach initForm to every CF7 form found in the document.
171     * Works whether this script loads before or after DOMContentLoaded.
172     * ──────────────────────────────────────────────────────────────────────── */
173    function initAll() {
174        document.querySelectorAll( '.wpcf7 form, .wpcf7-form' ).forEach( initForm );
175    }
176
177    if ( document.readyState === 'loading' ) {
178        document.addEventListener( 'DOMContentLoaded', initAll );
179    } else {
180        initAll();
181    }
182
183}());

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.