Skip to content
Open
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function minify_all_js_files_except_already_bundled() {
'!js/src/cleantalk-admin.js',
'!js/src/common-decoder.js',
'js/src/public-3-trp.js',
'js/src/public-2-gathering-data.js',
])
.pipe(sourcemaps.init())
.pipe(uglify())
Expand Down
1 change: 1 addition & 0 deletions inc/cleantalk-common.php
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ function apbct_get_sender_info()
'bot_detector_prepared_form_exclusions' => apbct__bot_detector_get_prepared_exclusion(),
'bot_detector_frontend_data_log' => apbct__bot_detector_get_fd_log(),
'submit_time_calculation_enabled' => SubmitTimeHandler::isCalculationDisabled() ? 0 : 1,
'ct_gathering_loaded' => Cookie::getBool('ct_gathering_loaded'),
);

// Unset cookies_enabled from sender_info if cookies_type === none
Expand Down
2 changes: 1 addition & 1 deletion js/apbct-public-bundle.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_ext-protection.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_ext-protection_gathering.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_full-protection.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_full-protection_gathering.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_gathering.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_int-protection.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/apbct-public-bundle_int-protection_gathering.min.js

Large diffs are not rendered by default.

109 changes: 99 additions & 10 deletions js/prebuild/apbct-public-bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -1988,7 +1988,7 @@ class ApbctShadowRootProtection {
* Set init params
*/
// eslint-disable-next-line no-unused-vars,require-jsdoc
function initParams() {
function initParams(gatheringLoaded) {
const ctDate = new Date();
const headless = navigator.webdriver;
const screenInfo = (
Expand Down Expand Up @@ -2067,6 +2067,10 @@ function initParams() {
initCookies.push(['ct_checkjs', 0]);
}

if (gatheringLoaded) {
initCookies.push(['ct_gathering_loaded', gatheringLoaded]);
}

ctSetCookie(initCookies);
}

Expand Down Expand Up @@ -2605,13 +2609,14 @@ class ApbctEventTokenTransport {
class ApbctAttachData {
/**
* Attach hidden fields to forms
* @param {bool} gatheringLoaded
* @return {void}
*/
attachHiddenFieldsToForms() {
attachHiddenFieldsToForms(gatheringLoaded) {
if (typeof ctPublic.force_alt_cookies == 'undefined' ||
(ctPublic.force_alt_cookies !== 'undefined' && !ctPublic.force_alt_cookies)
) {
if (!+ctPublic.settings__data__bot_detector_enabled) {
if (!+ctPublic.settings__data__bot_detector_enabled || gatheringLoaded) {
ctNoCookieAttachHiddenFieldsToForms();
document.addEventListener('gform_page_loaded', ctNoCookieAttachHiddenFieldsToForms);
}
Expand Down Expand Up @@ -3968,18 +3973,100 @@ class ApbctMailpoetVisibleFields extends ApbctVisibleFieldsExtractor {
}
}

/**
* Additional function to calculate realpath of cleantalk's scripts
* @return {*|null}
*/
function getApbctBasePath() {
// Find apbct-public-bundle in scripts names
const scripts = document.getElementsByTagName('script');

for (let script of scripts) {
if (script.src && script.src.includes('apbct-public-bundle')) {
// Get path from `src` js
const match = script.src.match(/^(.*\/js\/)/);
if (match && match[1]) {
return match[1]; // Path exists, return this
}
}
}

return null; // cleantalk's scripts not found :(
}

/**
* Load any script into the DOM (i.e. `import()`)
* @param {string} scriptAbsolutePath
* @return {Promise<*|boolean>}
*/
async function apbctImportScript(scriptAbsolutePath) {
// Check it this scripti already is in DOM
const normalizedPath = scriptAbsolutePath.replace(/\/$/, ''); // Replace ending slashes
const scripts = document.querySelectorAll('script[src]');
for (const script of scripts) {
const scriptSrc = script.src.replace(/\/$/, '');
if (scriptSrc === normalizedPath) {
// Script already loaded, skipping
return true;
}
}
return new Promise((resolve, reject) => {
const script = document.createElement('script');

script.src = scriptAbsolutePath;
script.async = true;

script.onload = function() {
// Gathering data script loaded successfully
resolve(true);
};

script.onerror = function() {
// Failed to load Gathering data script from `scriptAbsolutePath`
reject(new Error('Script loading failed: ' + scriptAbsolutePath));
};

document.head.appendChild(script);
}).catch((error) => {
// Gathering data script loading failed, continuing without it
return false;
});
}

/**
* Ready function
*/
// eslint-disable-next-line camelcase,require-jsdoc
function apbct_ready() {
async function apbct_ready() {
new ApbctShowForbidden().prepareBlockForAjaxForms();

// Try to get gathering if no worked bot-detector
let gatheringLoaded = false;

if (
apbctLocalStorage.get('apbct_existing_visitor') && // Not for the first hit
+ctPublic.settings__data__bot_detector_enabled && // If Bot-Detector is active
!apbctLocalStorage.get('bot_detector_event_token') && // and no `event_token` generated
typeof ApbctGatheringData === 'undefined' // and no `gathering` loaded yet
) {
const basePath = getApbctBasePath();
if ( ! basePath ) {
// We are here because NO any cleantalk bundle script are in frontend: Todo nothing
} else {
const gatheringScriptName = 'public-2-gathering-data.min.js';
const gatheringFullPath = basePath + gatheringScriptName;
gatheringLoaded = await apbctImportScript(gatheringFullPath);
}
}

const handler = new ApbctHandler();
handler.detectForcedAltCookiesForms();

// Gathering data when bot detector is disabled
if (!+ctPublic.settings__data__bot_detector_enabled && typeof ApbctGatheringData !== 'undefined') {
if (
( ! +ctPublic.settings__data__bot_detector_enabled || gatheringLoaded ) &&
typeof ApbctGatheringData !== 'undefined'
) {
const gatheringData = new ApbctGatheringData();
gatheringData.setSessionId();
gatheringData.writeReferrersToSessionStorage();
Expand All @@ -3991,7 +4078,7 @@ function apbct_ready() {
// Always call initParams to set cookies and parameters
if (typeof initParams === 'function') {
try {
initParams();
initParams(gatheringLoaded);
} catch (e) {
console.log('initParams error:', e);
}
Expand All @@ -4007,9 +4094,9 @@ function apbct_ready() {

const attachData = new ApbctAttachData();

// Attach data when bot detector is disabled
if (!+ctPublic.settings__data__bot_detector_enabled) {
attachData.attachHiddenFieldsToForms();
// Attach data when bot detector is disabled or blocked
if (!+ctPublic.settings__data__bot_detector_enabled || gatheringLoaded) {
attachData.attachHiddenFieldsToForms(gatheringLoaded);
}

for (let i = 0; i < document.forms.length; i++) {
Expand Down Expand Up @@ -4039,7 +4126,7 @@ function apbct_ready() {
let botDetectorEventTokenStored = false;
window.addEventListener('botDetectorEventTokenUpdated', (event) => {
const botDetectorEventToken = event.detail?.eventToken;
if ( botDetectorEventToken && ! botDetectorEventTokenStored ) {
if (botDetectorEventToken && !botDetectorEventTokenStored) {
ctSetCookie([
['ct_bot_detector_event_token', botDetectorEventToken],
]);
Expand All @@ -4058,6 +4145,8 @@ function apbct_ready() {
if (ctPublic.settings__sfw__anti_crawler && +ctPublic.settings__data__bot_detector_enabled) {
handler.toolForAntiCrawlerCheckDuringBotDetector();
}

apbctLocalStorage.set('apbct_existing_visitor', 1);
}

if (ctPublic.data__key_is_ok) {
Expand Down
109 changes: 99 additions & 10 deletions js/prebuild/apbct-public-bundle_ext-protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -1988,7 +1988,7 @@ class ApbctShadowRootProtection {
* Set init params
*/
// eslint-disable-next-line no-unused-vars,require-jsdoc
function initParams() {
function initParams(gatheringLoaded) {
const ctDate = new Date();
const headless = navigator.webdriver;
const screenInfo = (
Expand Down Expand Up @@ -2067,6 +2067,10 @@ function initParams() {
initCookies.push(['ct_checkjs', 0]);
}

if (gatheringLoaded) {
initCookies.push(['ct_gathering_loaded', gatheringLoaded]);
}

ctSetCookie(initCookies);
}

Expand Down Expand Up @@ -2605,13 +2609,14 @@ class ApbctEventTokenTransport {
class ApbctAttachData {
/**
* Attach hidden fields to forms
* @param {bool} gatheringLoaded
* @return {void}
*/
attachHiddenFieldsToForms() {
attachHiddenFieldsToForms(gatheringLoaded) {
if (typeof ctPublic.force_alt_cookies == 'undefined' ||
(ctPublic.force_alt_cookies !== 'undefined' && !ctPublic.force_alt_cookies)
) {
if (!+ctPublic.settings__data__bot_detector_enabled) {
if (!+ctPublic.settings__data__bot_detector_enabled || gatheringLoaded) {
ctNoCookieAttachHiddenFieldsToForms();
document.addEventListener('gform_page_loaded', ctNoCookieAttachHiddenFieldsToForms);
}
Expand Down Expand Up @@ -3968,18 +3973,100 @@ class ApbctMailpoetVisibleFields extends ApbctVisibleFieldsExtractor {
}
}

/**
* Additional function to calculate realpath of cleantalk's scripts
* @return {*|null}
*/
function getApbctBasePath() {
// Find apbct-public-bundle in scripts names
const scripts = document.getElementsByTagName('script');

for (let script of scripts) {
if (script.src && script.src.includes('apbct-public-bundle')) {
// Get path from `src` js
const match = script.src.match(/^(.*\/js\/)/);
if (match && match[1]) {
return match[1]; // Path exists, return this
}
}
}

return null; // cleantalk's scripts not found :(
}

/**
* Load any script into the DOM (i.e. `import()`)
* @param {string} scriptAbsolutePath
* @return {Promise<*|boolean>}
*/
async function apbctImportScript(scriptAbsolutePath) {
// Check it this scripti already is in DOM
const normalizedPath = scriptAbsolutePath.replace(/\/$/, ''); // Replace ending slashes
const scripts = document.querySelectorAll('script[src]');
for (const script of scripts) {
const scriptSrc = script.src.replace(/\/$/, '');
if (scriptSrc === normalizedPath) {
// Script already loaded, skipping
return true;
}
}
return new Promise((resolve, reject) => {
const script = document.createElement('script');

script.src = scriptAbsolutePath;
script.async = true;

script.onload = function() {
// Gathering data script loaded successfully
resolve(true);
};

script.onerror = function() {
// Failed to load Gathering data script from `scriptAbsolutePath`
reject(new Error('Script loading failed: ' + scriptAbsolutePath));
};

document.head.appendChild(script);
}).catch((error) => {
// Gathering data script loading failed, continuing without it
return false;
});
}

/**
* Ready function
*/
// eslint-disable-next-line camelcase,require-jsdoc
function apbct_ready() {
async function apbct_ready() {
new ApbctShowForbidden().prepareBlockForAjaxForms();

// Try to get gathering if no worked bot-detector
let gatheringLoaded = false;

if (
apbctLocalStorage.get('apbct_existing_visitor') && // Not for the first hit
+ctPublic.settings__data__bot_detector_enabled && // If Bot-Detector is active
!apbctLocalStorage.get('bot_detector_event_token') && // and no `event_token` generated
typeof ApbctGatheringData === 'undefined' // and no `gathering` loaded yet
) {
const basePath = getApbctBasePath();
if ( ! basePath ) {
// We are here because NO any cleantalk bundle script are in frontend: Todo nothing
} else {
const gatheringScriptName = 'public-2-gathering-data.min.js';
const gatheringFullPath = basePath + gatheringScriptName;
gatheringLoaded = await apbctImportScript(gatheringFullPath);
}
}

const handler = new ApbctHandler();
handler.detectForcedAltCookiesForms();

// Gathering data when bot detector is disabled
if (!+ctPublic.settings__data__bot_detector_enabled && typeof ApbctGatheringData !== 'undefined') {
if (
( ! +ctPublic.settings__data__bot_detector_enabled || gatheringLoaded ) &&
typeof ApbctGatheringData !== 'undefined'
) {
const gatheringData = new ApbctGatheringData();
gatheringData.setSessionId();
gatheringData.writeReferrersToSessionStorage();
Expand All @@ -3991,7 +4078,7 @@ function apbct_ready() {
// Always call initParams to set cookies and parameters
if (typeof initParams === 'function') {
try {
initParams();
initParams(gatheringLoaded);
} catch (e) {
console.log('initParams error:', e);
}
Expand All @@ -4007,9 +4094,9 @@ function apbct_ready() {

const attachData = new ApbctAttachData();

// Attach data when bot detector is disabled
if (!+ctPublic.settings__data__bot_detector_enabled) {
attachData.attachHiddenFieldsToForms();
// Attach data when bot detector is disabled or blocked
if (!+ctPublic.settings__data__bot_detector_enabled || gatheringLoaded) {
attachData.attachHiddenFieldsToForms(gatheringLoaded);
}

for (let i = 0; i < document.forms.length; i++) {
Expand Down Expand Up @@ -4039,7 +4126,7 @@ function apbct_ready() {
let botDetectorEventTokenStored = false;
window.addEventListener('botDetectorEventTokenUpdated', (event) => {
const botDetectorEventToken = event.detail?.eventToken;
if ( botDetectorEventToken && ! botDetectorEventTokenStored ) {
if (botDetectorEventToken && !botDetectorEventTokenStored) {
ctSetCookie([
['ct_bot_detector_event_token', botDetectorEventToken],
]);
Expand All @@ -4058,6 +4145,8 @@ function apbct_ready() {
if (ctPublic.settings__sfw__anti_crawler && +ctPublic.settings__data__bot_detector_enabled) {
handler.toolForAntiCrawlerCheckDuringBotDetector();
}

apbctLocalStorage.set('apbct_existing_visitor', 1);
}

if (ctPublic.data__key_is_ok) {
Expand Down
Loading