Skip to content

Commit 32e316d

Browse files
Merge pull request #730 from CleanTalk/fix-fetch-attach-fields.ag
Fix. Integrations. Fixed fetch request fields assignment (NoCookie|EventToken)
2 parents 334f6ae + 7748f43 commit 32e316d

21 files changed

+1590
-482
lines changed

inc/cleantalk-common.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ function apbct_exclusions_check__url()
435435
*/
436436
// case for admin-ajax routes, may contain get params(!)
437437
$is_admin_ajax_like = stripos(Server::getString('REQUEST_URI'), '/wp-admin/admin-ajax.php') === 0;
438+
// case for woocommerce-ajax routes, may contain get params(!)
439+
$is_wc_ajax_like = stripos(Server::getString('REQUEST_URI'), '/?wc-ajax=') === 0;
438440
// case for wp-json paths
439441
$is_wp_json_like = stripos(Server::getString('REQUEST_URI'), '/wp-json/') === 0;
440442
// case for rest paths
@@ -446,6 +448,7 @@ function apbct_exclusions_check__url()
446448
Server::getString('HTTP_REFERER') &&
447449
(
448450
$is_admin_ajax_like ||
451+
$is_wc_ajax_like ||
449452
$is_wp_json_like ||
450453
$is_rest_only_path
451454
)

js/apbct-public-bundle.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_ext-protection.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_ext-protection_gathering.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection_gathering.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_gathering.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_int-protection.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_int-protection_gathering.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/prebuild/apbct-public-bundle.js

Lines changed: 147 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,7 +2818,7 @@ class ApbctHandler {
28182818
cronFormsHandler(cronStartTimeout = 2000) {
28192819
setTimeout(function() {
28202820
setInterval(function() {
2821-
if (!+ctPublic.settings__data__bot_detector_enabled) {
2821+
if (!+ctPublic.settings__data__bot_detector_enabled && typeof ApbctGatheringData !== 'undefined') {
28222822
new ApbctGatheringData().restartFieldsListening();
28232823
}
28242824
new ApbctEventTokenTransport().restartBotDetectorEventTokenAttach();
@@ -2928,6 +2928,68 @@ class ApbctHandler {
29282928
}
29292929
}
29302930

2931+
/**
2932+
* Catch Iframe fetch request
2933+
* @return {void}
2934+
*/
2935+
catchIframeFetchRequest() {
2936+
setTimeout(function() {
2937+
try {
2938+
// Give next gen iframe
2939+
const foundIframe = Array.from(document.querySelectorAll('iframe')).find(
2940+
(iframe) => iframe.src?.includes('givewp-route'),
2941+
);
2942+
2943+
if (!foundIframe) {
2944+
return;
2945+
}
2946+
2947+
// Cross origin access check
2948+
let contentWindow;
2949+
try {
2950+
contentWindow = foundIframe.contentWindow;
2951+
if (!contentWindow || !contentWindow.fetch) {
2952+
return;
2953+
}
2954+
} catch (securityError) {
2955+
// access denied
2956+
return;
2957+
}
2958+
2959+
// Save original iframe fetch
2960+
const originalIframeFetch = contentWindow.fetch;
2961+
2962+
// Intercept and add fields to body
2963+
contentWindow.fetch = async function(...args) {
2964+
try {
2965+
// is body and boddy has append func
2966+
if (args && args[1] && args[1].body) {
2967+
if (
2968+
args[1].body instanceof FormData || (typeof args[1].body.append === 'function')
2969+
) {
2970+
if (+ctPublic.settings__data__bot_detector_enabled) {
2971+
args[1].body.append(
2972+
'ct_bot_detector_event_token',
2973+
apbctLocalStorage.get('bot_detector_event_token'),
2974+
);
2975+
} else {
2976+
args[1].body.append('ct_no_cookie_hidden_field', getNoCookieData());
2977+
}
2978+
}
2979+
}
2980+
} catch (e) {
2981+
// do nothing due fields add error
2982+
}
2983+
2984+
// run origin fetch
2985+
return originalIframeFetch.apply(contentWindow, args);
2986+
};
2987+
} catch (error) {
2988+
// do nothing on unexpected error
2989+
}
2990+
}, 1000);
2991+
}
2992+
29312993
/**
29322994
* Catch fetch request
29332995
* @return {void}
@@ -2967,95 +3029,127 @@ class ApbctHandler {
29673029
})
29683030
)
29693031
) {
3032+
/**
3033+
* Select key/value pair depending on botDetectorEnabled flag
3034+
* @param {bool} botDetectorEnabled
3035+
* @return {{key: string, value: string}|false} False on empty gained data.
3036+
*/
3037+
const selectFieldsData = function(botDetectorEnabled) {
3038+
const result = {
3039+
'key': null,
3040+
'value': null,
3041+
};
3042+
if (botDetectorEnabled) {
3043+
result.key = 'ct_bot_detector_event_token';
3044+
result.value = apbctLocalStorage.get('bot_detector_event_token');
3045+
} else {
3046+
result.key = 'ct_no_cookie_hidden_field';
3047+
result.value = getNoCookieData();
3048+
};
3049+
return result.key && result.value ? result : false;
3050+
};
3051+
3052+
/**
3053+
*
3054+
* @param {string} body Fetch request data body.
3055+
* @param {object|bool} fieldPair Key value to inject.
3056+
* @return {string} Modified body.
3057+
*/
3058+
const attachFieldsToBody = function(body, fieldPair = false) {
3059+
if (fieldPair) {
3060+
if (body instanceof FormData || typeof body.append === 'function') {
3061+
body.append(fieldPair.key, fieldPair.value);
3062+
} else {
3063+
let bodyObj = JSON.parse(body);
3064+
if (!bodyObj.hasOwnProperty(fieldPair.key)) {
3065+
bodyObj[fieldPair.key] = fieldPair.value;
3066+
body = JSON.stringify(bodyObj);
3067+
}
3068+
}
3069+
}
3070+
return body;
3071+
};
3072+
29703073
let preventOriginalFetch = false;
29713074

29723075
window.fetch = async function(...args) {
3076+
// if no data set provided - exit
3077+
if (
3078+
!args ||
3079+
!args[0] ||
3080+
!args[1] ||
3081+
!args[1].body
3082+
) {
3083+
return defaultFetch.apply(window, args);
3084+
}
3085+
29733086
// Metform block
29743087
if (
29753088
Array.from(document.forms).some((form) => form.classList.contains('metform-form-content')) &&
2976-
args &&
2977-
args[0] &&
29783089
typeof args[0].includes === 'function' &&
29793090
(args[0].includes('/wp-json/metform/') ||
29803091
(ctPublicFunctions._rest_url && (() => {
29813092
try {
29823093
return args[0].includes(new URL(ctPublicFunctions._rest_url).pathname + 'metform/');
29833094
} catch (e) {
2984-
return false;
3095+
return defaultFetch.apply(window, args);
29853096
}
29863097
})())
29873098
)
29883099
) {
2989-
if (args && args[1] && args[1].body) {
2990-
if (+ctPublic.settings__data__bot_detector_enabled) {
2991-
args[1].body.append(
2992-
'ct_bot_detector_event_token',
2993-
apbctLocalStorage.get('bot_detector_event_token'),
2994-
);
2995-
} else {
2996-
args[1].body.append('ct_no_cookie_hidden_field', getNoCookieData());
2997-
}
3100+
try {
3101+
args[1].body = attachFieldsToBody(
3102+
args[1].body,
3103+
selectFieldsData(+ctPublic.settings__data__bot_detector_enabled),
3104+
);
3105+
} catch (e) {
3106+
return defaultFetch.apply(window, args);
29983107
}
29993108
}
3109+
30003110
// WP Recipe Maker block
30013111
if (
30023112
Array.from(document.forms).some(
30033113
(form) => form.classList.contains('wprm-user-ratings-modal-stars-container'),
30043114
) &&
3005-
args &&
3006-
args[0] &&
30073115
typeof args[0].includes === 'function' &&
30083116
args[0].includes('/wp-json/wp-recipe-maker/')
30093117
) {
3010-
if (args[1] && args[1].body) {
3011-
if (typeof args[1].body === 'string') {
3012-
let bodyObj;
3013-
try {
3014-
bodyObj = JSON.parse(args[1].body);
3015-
} catch (e) {
3016-
bodyObj = {};
3017-
}
3018-
if (+ctPublic.settings__data__bot_detector_enabled) {
3019-
bodyObj.ct_bot_detector_event_token =
3020-
apbctLocalStorage.get('bot_detector_event_token');
3021-
} else {
3022-
bodyObj.ct_no_cookie_hidden_field = getNoCookieData();
3023-
}
3024-
args[1].body = JSON.stringify(bodyObj);
3025-
}
3118+
try {
3119+
args[1].body = attachFieldsToBody(
3120+
args[1].body,
3121+
selectFieldsData(+ctPublic.settings__data__bot_detector_enabled),
3122+
);
3123+
} catch (e) {
3124+
return defaultFetch.apply(window, args);
30263125
}
30273126
}
30283127

30293128
// WooCommerce add to cart request, like:
30303129
// /index.php?rest_route=/wc/store/v1/cart/add-item
3031-
if (args && args[0] &&
3032-
args[0].includes('/wc/store/v1/cart/add-item') &&
3033-
args && args[1] && args[1].body
3130+
if (
3131+
typeof args[0].includes === 'function' &&
3132+
args[0].includes('/wc/store/v1/cart/add-item')
30343133
) {
3035-
if (
3036-
+ctPublic.settings__data__bot_detector_enabled &&
3037-
+ctPublic.settings__forms__wc_add_to_cart
3038-
) {
3039-
try {
3040-
let bodyObj = JSON.parse(args[1].body);
3041-
if (!bodyObj.hasOwnProperty('ct_bot_detector_event_token')) {
3042-
bodyObj.ct_bot_detector_event_token =
3043-
apbctLocalStorage.get('bot_detector_event_token');
3044-
args[1].body = JSON.stringify(bodyObj);
3045-
}
3046-
} catch (e) {
3047-
return false;
3134+
try {
3135+
if (
3136+
+ctPublic.settings__forms__wc_add_to_cart
3137+
) {
3138+
args[1].body = attachFieldsToBody(
3139+
args[1].body,
3140+
selectFieldsData(+ctPublic.settings__data__bot_detector_enabled),
3141+
);
30483142
}
3049-
} else {
3050-
args[1].body.append('ct_no_cookie_hidden_field', getNoCookieData());
3143+
} catch (e) {
3144+
return defaultFetch.apply(window, args);
30513145
}
30523146
}
30533147

30543148
// bitrix24 EXTERNAL form
30553149
if (+ctPublic.settings__forms__check_external &&
3056-
args && args[0] &&
3150+
typeof args[0].includes === 'function' &&
30573151
args[0].includes('bitrix/services/main/ajax.php?action=crm.site.form.fill') &&
3058-
args[1] && args[1].body && args[1].body instanceof FormData
3152+
args[1].body instanceof FormData
30593153
) {
30603154
const currentTargetForm = document.querySelector('.b24-form form');
30613155
let data = {
@@ -3720,7 +3814,7 @@ function apbct_ready() {
37203814
handler.detectForcedAltCookiesForms();
37213815

37223816
// Gathering data when bot detector is disabled
3723-
if (!+ctPublic.settings__data__bot_detector_enabled) {
3817+
if (!+ctPublic.settings__data__bot_detector_enabled && typeof ApbctGatheringData !== 'undefined') {
37243818
const gatheringData = new ApbctGatheringData();
37253819
gatheringData.setSessionId();
37263820
gatheringData.writeReferrersToSessionStorage();
@@ -3772,6 +3866,7 @@ function apbct_ready() {
37723866

37733867
handler.catchXmlHttpRequest();
37743868
handler.catchFetchRequest();
3869+
handler.catchIframeFetchRequest();
37753870
handler.catchJqueryAjax();
37763871
handler.catchWCRestRequestAsMiddleware();
37773872

0 commit comments

Comments
 (0)