PageSourceSearch

https://laverstockford-pc.gov.uk/wp-content/plugins/altcha-wordpre…/public/interceptor-wp.js?ver=3.0.4

js laverstockford-pc.gov.uk collected 2026-10-10 00:32:59 UTC 11,880 bytes, 406 lines download raw bytes

1/**
2 * Copyright (c) 2025 BAU Software s.r.o., Czechia. All rights reserved.
3 *
4 * This file is part of the Software licensed under the
5 * END-USER LICENSE AGREEMENT (EULA)
6 *
7 * License Summary:
8 * - Source is available for review, testing, debugging, and evaluation.
9 * - Distribution of the Software or source code is prohibited.
10 * - Modifications are allowed only for internal testing/debugging,
11 *   not for production or deployment.
12 *
13 * The full license text can be found in the LICENSE file
14 * distributed with this source code.
15 *
16 * Unauthorized distribution, modification, or production use of
17 * this Software is strictly prohibited.
18 */
19
20(() => {
21  const debug =
22    /^localhost|.*\.localhost|.*\.test$/.test(location.hostname) ||
23    /:\d+$/.test(location.host) ||
24    localStorage.getItem("altcha_debug") === "1";
25  const defaultActionName = "action";
26  const config = pluginData?.altcha || {};
27  const actions = config.actions || [];
28  const paths = config.paths || [];
29  const cookiePath = config.cookiePath || "/";
30  const sitePath = config.sitePath || "/";
31  const protectLogin = !!config.protectLogin;
32  const protectRegistration = !!config.protectRegistration;
33  const protectPasswordReset = !!config.protectPasswordReset;
34  const protectComments = !!config.protectComments;
35  const plugins = {
36    coblocks: {
37      actions: ["coblocks-form-submit"],
38      formIdField: "form-submit",
39    },
40    "contact-form-7": {
41      formIdField: "_wpcf7",
42      paths: ["/contact-form-7/", "#wpcf7-"],
43    },
44    divi: {
45      actions: ["et_pb_contact_form_submit"],
46      formIdField: "et_pb_contact_form_id"
47    },
48    "elementor-pro": {
49      actions: ["elementor_pro_forms_send_form"],
50      formIdField: "form_id"
51    },
52    eventprime: {
53      actions: ["ep_save_event_booking"],
54    },
55    "everest-forms": {
56      fields: ["everest_forms[id]"],
57      formIdField: "everest_forms[id]"
58    },
59    formidable: {
60      fields: ["frm_action"],
61      formIdField: "form_id",
62    },
63    forminator: {
64      fields: ["forminator_nonce"],
65      formIdField: "form_id",
66    },
67    fluentform: {
68      actions: ["fluentform_submit"],
69      fields: ["__fluent_form_embded_post_id"],
70      formIdField: "form_id",
71    },
72    gravityforms: {
73      fields: ["gform_submission_method"],
74      formIdField: "gform_submit",
75    },
76    "kali-forms": {
77      actions: ["kaliforms_form_process"],
78      formIdField: "data[formId]",
79    },
80    "html-forms": {
81      fields: ["_hf_form_id"],
82      formIdField: "_hf_form_id",
83    },
84    mailpoet: {
85      actions: ["mailpoet"],
86      formIdField: "data[form_id]"
87    },
88    metform: {
89      paths: ["/metform/"],
90      formIdField: (request) => request?.url?.pathname.match(/(\d+)$/)?.[1],
91    },
92    newsletter: {
93      actions: ["tnp"],
94    },
95    noptin: {
96      paths: ["/noptin/"],
97      formIdField: "noptin_form_id",
98    },
99    ninjaforms: {
100      actions: ["nf_ajax_submit"],
101      formIdField: (request) =>
102        request?.body?.formData.match(/"id":"(\d+)"/)?.[1],
103    },
104    sureforms: {
105      paths: ["/sureforms/v1/submit-form"],
106      formIdField: "form-id",
107    },
108    "user-registration": {
109      fields: [
110        "user-registration-login-nonce",
111        "ur_reset_password",
112        "ur_frontend_form_nonce"
113      ],
114    },
115    woocommerce: {
116      fields: [
117        "wc_reset_password",
118        "woocommerce-login-nonce"
119      ],
120      paths: ["/wc/store/v1/", "/wc-api/"],
121    },
122    "wp-members": {
123      fields: ["_wpmem_login_nonce", "_wpmem_register_nonce"],
124    },
125    wpdiscuz: {
126      fields: ["wpdiscuz_unique_id"],
127    },
128    wpforms: {
129      actions: ["wpforms_submit"],
130      fields: ["wpforms[id]"],
131      formIdField: "wpforms[id]",
132    },
133    "wp": {
134      match: (request) => {
135        if (request.url.pathname.endsWith("/wp-login.php")) {
136          const action = matchActions(request, [
137            "lostpassword",
138            "register",
139          ]);
140          return action || "login";
141        } else if (request.url.pathname.endsWith("/wp-register.php")) {
142          return "register";
143        } else if (request.url.pathname.endsWith("/wp-comments-post.php")) {
144          return "comments";
145        }
146      },
147    },
148  };
149  let interceptor;
150  let refreshUnderAttackPromise = null;
151
152  function createRegExp(pattern) {
153    return new RegExp(
154      "^" +
155        pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") +
156        "$",
157      "i"
158    );
159  }
160
161  function detectPlugin(request, action) {
162    for (const plugin in plugins) {
163      const opts = plugins[plugin];
164      if (opts.match) {
165        const pluginAction = opts.match(request, action);
166        if (pluginAction) {
167          return {
168            pluginAction,
169            plugin,
170          };
171        }
172      }
173      if (opts.fields && opts.fields.some((field) => request.body?.[field] !== undefined)) {
174        return {
175          pluginAction: null,
176          plugin,
177        };
178      }
179      if (opts.actions?.length) {
180        const pluginAction = matchActions(request, opts.actions);
181        if (pluginAction) {
182          return {
183            pluginAction,
184            plugin,
185          };
186        }
187      }
188      if (
189        opts.paths?.length &&
190        opts.paths.some((path) => request.url.href.includes(path))
191      ) {
192        return {
193          pluginAction: null,
194          plugin,
195        };
196      }
197    }
198    return {
199      pluginAction: null,
200      plugin: null,
201    };
202  }
203
204  function getTimeZone() {
205    try {
206      return Intl.DateTimeFormat().resolvedOptions().timeZone;
207    } catch {
208      // noop
209    }
210  }
211
212  function getCookie(name) {
213    const nameEQ = name + "=";
214    const cookies = document.cookie.split(";");
215    for (let i = 0; i < cookies.length; i++) {
216      let c = cookies[i];
217      while (c.charAt(0) === " ") {
218        c = c.substring(1, c.length);
219      }
220      if (c.indexOf(nameEQ) === 0) {
221        return decodeURIComponent(c.substring(nameEQ.length, c.length));
222      }
223    }
224    return null;
225  }
226
227  function setCookie(name, value, props = "") {
228    document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(
229      value
230    )}; SameSite=strict; ${props}`.trim();
231  }
232
233  function matchActions(request, patterns) {
234    let matched = false;
235    let rx = null;
236    for (let pattern of patterns) {
237      const isNegation = pattern.startsWith("!");
238      const cleanPattern = isNegation ? pattern.slice(1) : pattern;
239      let name = defaultActionName;
240      let value = null;
241      if (cleanPattern.includes("=")) {
242        const parts = cleanPattern.split("=");
243        name = parts[0];
244        rx = createRegExp(parts[1]);
245      } else if (cleanPattern === "*") {
246        matched = String(
247          request.body?.[name] || request.url.searchParams.get(name) || ""
248        );
249        continue;
250      } else {
251        rx = createRegExp(cleanPattern);
252      }
253      value = String(
254        request.body?.[name] || request.url.searchParams.get(name) || ""
255      );
256      if (rx) {
257        if ((name === defaultActionName || !!value) && rx.test(value)) {
258          if (isNegation) {
259            return false;
260          }
261          if (cleanPattern.includes('=')) {
262            return `${name}=`;
263          }
264          return name === defaultActionName ? value : `${name}=`;
265        }
266      }
267    }
268    return matched;
269  }
270
271  function matchPattern(str, patterns) {
272    let matched = false;
273    for (let pattern of patterns) {
274      const isNegation = pattern.startsWith("!");
275      const cleanPattern = isNegation ? pattern.slice(1) : pattern;
276      if (cleanPattern === "*") {
277        matched = true;
278      } else if (createRegExp(cleanPattern).test(str)) {
279        if (isNegation) {
280          return false;
281        }
282        return true;
283      }
284    }
285    return matched;
286  }
287
288  function normalizePath(path) {
289    if (sitePath !== "/" && path.startsWith(sitePath)) {
290      path = "/" + path.slice(sitePath.length).replace(/^\/+/, "");
291    }
292    return path.replace(/^\/index.php\//, "/");
293  }
294
295  async function refreshUnderAttackCookie() {
296    const underAttackCookie = getCookie("altcha_under_attack");
297    const expires = parseInt(
298      getCookie("altcha_under_attack_expires") || "0",
299      10
300    );
301    const ttl = parseInt(getCookie("altcha_under_attack_ttl") || "0", 10);
302    if (
303      !refreshUnderAttackPromise &&
304      (!underAttackCookie || expires < Date.now() + 15_000)
305    ) {
306      refreshUnderAttackPromise = interceptor.requestAltchaVerification(
307        {
308          "params.under_attack": "1",
309        },
310        config.underAttackChallengeUrl || config.widget.challenge
311      );
312      try {
313        const payload = await refreshUnderAttackPromise;
314        if (payload) {
315          setCookie(
316            "altcha_under_attack",
317            payload,
318            "path=" +
319              cookiePath +
320              "; expires=" +
321              new Date(Date.now() + (ttl || 30_000)).toUTCString()
322          );
323        }
324      } finally {
325        refreshUnderAttackPromise = null;
326      }
327    }
328  }
329
330  interceptor = altchaInterceptor({
331    filter: async (request) => {
332      const isLogin = request.method === "POST" && !!request.body?.log && !!request.body?.pwd;
333      const isRegistration = request.method === "POST" && (request.url.pathname.endsWith("/wp-register.php") || request.url.searchParams.get("action") === "register");
334      const isPasswordReset = request.method === "POST" && request.url.searchParams.get("action") === "lostpassword";
335      const isComment = request.method === "POST" && !!request.url.pathname.endsWith("/wp-comments-post.php");
336      if (request.url.origin !== location.origin) {
337        return false;
338      }
339      if (getCookie("altcha")) {
340        return false;
341      }
342      if (request.body?.altcha) {
343        return false;
344      }
345      if (
346        request.method !== "POST" &&
347        !request.url.pathname.endsWith("admin-ajax.php")
348      ) {
349        return false;
350      }
351      if (isLogin && !protectLogin) {
352        return false;
353      } else if (isRegistration && !protectRegistration) {
354        return false;
355      } else if (isPasswordReset && !protectPasswordReset) {
356        return false;
357      } else if (isComment && !protectComments) {
358        return false;
359      }
360      const pathMatched = matchPattern(normalizePath(request.url.pathname), paths);
361      const action = matchActions(request, actions);
362      if (!isLogin && !isRegistration && !isPasswordReset && !isComment && action === false && !pathMatched) {
363        return false;
364      }
365      const { plugin, pluginAction } = detectPlugin(request, action);
366      if (config.underAttack) {
367        await refreshUnderAttackCookie();
368      }
369      const formIdField = plugins[plugin]?.formIdField;
370      return {
371        action: typeof action === "string" ? action : (pluginAction || null),
372        form_id:
373          (formIdField && typeof formIdField === "function"
374            ? formIdField(request)
375            : request.body?.[formIdField]) || null,
376        interceptor: "1",
377        plugin,
378        tz: getTimeZone(),
379      };
380    },
381    onVerified: (payload) => {
382      setCookie("altcha", payload, "path=" + cookiePath);
383    },
384    debug,
385    ...config,
386    widget: {
387      debug,
388      ...config.widget,
389    },
390  });
391
392  if (config.widget.powAlgorithm === "ARGON2ID") {
393    try {
394      $altcha.algorithms.set("ARGON2ID", () => new Worker(config.workerArgon2idPath));
395    } catch (err) {
396      console.error(err);
397      console.error('ALTCHA failed to register ARGON2ID worker.');
398    }
399  }
400
401  if (!window.isSecureContext) {
402    console.warn(
403      "Secure Context (HTTPS) Required! ALTCHA requires a secure connection (HTTPS), also known as a Secure Context [https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts]. Please access this page over HTTPS or use whitelisted localhost domains for development."
404    );
405  }
406})();

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.