File: /home/pclast/public_html/wp-content/plugins/zhaket-updater/includes/Booster/booster-js.php
<script id="zhaket-booster" data-no-minify="1" data-no-optimize="1" data-noptimize="1" data-rocket-status="opt-out">
(function(){
// --- Configuration ---
const debug = <?php echo !empty($settings['debug_mode']) ? 'true' : 'false'; ?>;
const blocked = <?php echo $json_blocked; ?>;
const cdnMap = <?php echo $json_cdn_map; ?>;
const whitelist = <?php echo $whitelisted_domains; ?>;
const maxTime = <?php echo $timeout; ?>;
const reportUrl = '<?php echo $ajax_url; ?>';
const currentHost = window.location.hostname;
// تشخیص اینکه آیا سرویس ورکر در حال حاضر فعال است یا خیر
const isSwActive = <?php echo $is_sw_active ? 'true' : 'false'; ?>;
if (debug) {
console.log('%c[Zhaket Booster Start] Debug Mode Active', "color: #27ae60; font-weight: bold;");
if (isSwActive) {
console.log('%c⚡ Running in SW Mode: DOM Interception Disabled, Performance Monitoring Active.', "color: #2980b9;");
} else {
console.log('%c⚠️ Running in Fallback Mode: DOM Interception & Monitoring both Active.', "color: #f39c12;");
}
}
/**
* Logic:
* 1. Own Domain -> Allow + isLocal: true (Bypass tracking)
* 2. Blocked -> Block
* 3. CDN -> Replace
* 4. Whitelist/Default -> Allow + isLocal: false
*/
function getProcessedUrl(src) {
if (!src || typeof src !== 'string' || src.startsWith('data:')) return { action: 'allow', url: src, isLocal: true };
try {
const urlObj = new URL(src, window.location.origin);
const fullUrl = urlObj.href;
const host = urlObj.hostname;
const isDomainMatch = (pattern) => host === pattern || host.endsWith('.' + pattern);
const isFullUrlMatch = (pattern) => fullUrl.includes(pattern);
if (isDomainMatch(currentHost)) return { action: 'allow', url: src, isLocal: true };
if (blocked.some(p => isDomainMatch(p) || isFullUrlMatch(p))) {
if (debug && !isSwActive) console.log(`%c[Blocked By Zhaket Booster]%c ${src}`, "color: red; font-weight: bold;", "color: inherit;");
return { action: 'block', url: src, isLocal: false };
}
const cdnMatch = cdnMap[src] || cdnMap[fullUrl] || cdnMap[src.replace(window.location.origin, '')];
if (cdnMatch) {
if (debug && !isSwActive) console.log(`%c[CDN Replace By Zhaket Booster]%c ${src} -> ${cdnMatch}`, "color: blue; font-weight: bold;", "color: inherit;");
return { action: 'replace', url: cdnMatch, isLocal: false };
}
if (whitelist.some(p => isDomainMatch(p) || isFullUrlMatch(p))) return { action: 'allow', url: src, isLocal: false };
return { action: 'allow', url: src, isLocal: false };
} catch (e) {
return { action: 'allow', url: src, isLocal: false };
}
}
// =========================================================
// 🔴 بخش Fallback: فقط در صورت خاموش بودن SW اجرا میشود
// =========================================================
if (!isSwActive) {
// --- 1. Intercept Element Creation ---
const _createElement = document.createElement.bind(document);
document.createElement = function(tag) {
const el = _createElement(tag);
const tagName = tag.toLowerCase();
if (tagName === 'script' || tagName === 'link' || tagName === 'img' || tagName === 'iframe') {
const targetAttr = tagName === 'link' ? 'href' : 'src';
Object.defineProperty(el, targetAttr, {
get: function() { return this.getAttribute(targetAttr); },
set: function(val) {
const result = getProcessedUrl(val);
if (result.action === 'block') {
if (tagName === 'script') el.setAttribute('type', 'javascript/blocked');
return;
}
if (result.action === 'replace') {
val = result.url;
el.removeAttribute('integrity');
}
this.setAttribute(targetAttr, val);
}
});
const _setAttribute = el.setAttribute.bind(el);
el.setAttribute = function(name, value) {
if (name.toLowerCase() === targetAttr) {
const result = getProcessedUrl(value);
if (result.action === 'block') {
if (tagName === 'script') _setAttribute.call(this, 'type', 'javascript/blocked');
return;
}
if (result.action === 'replace') {
value = result.url;
this.removeAttribute('integrity');
}
}
return _setAttribute.call(this, name, value);
};
}
return el;
};
// --- 2. Network Interception (Fetch & XHR) ---
const _fetch = window.fetch;
window.fetch = function(input, init) {
let url = (typeof input === 'string') ? input : (input?.url || '');
const result = getProcessedUrl(url);
if (result.action === 'block') return Promise.reject(new Error('Blocked by Zhaket Booster'));
if (result.action === 'replace') {
if (typeof input === 'string') input = result.url;
else if (input && input.url) input = new Request(result.url, input);
}
return _fetch.apply(this, arguments);
};
const _open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
const result = getProcessedUrl(url);
this._isBlocked = (result.action === 'block');
const finalUrl = result.action === 'replace' ? result.url : url;
return _open.call(this, method, finalUrl, arguments[2], arguments[3], arguments[4]);
};
const _send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
if (this._isBlocked) {
setTimeout(() => this.dispatchEvent(new Event('error')), 0);
return;
}
return _send.apply(this, arguments);
};
// --- 3. Mutation Observer ---
const processNode = (node) => {
if (node.nodeType !== 1 || node.hasAttribute('data-booster-processed')) return;
const isScript = node.tagName === 'SCRIPT';
const isLink = node.tagName === 'LINK';
const attr = isScript ? 'src' : (isLink ? 'href' : (node.tagName === 'IFRAME' || node.tagName === 'IMG' ? 'src' : null));
if (!attr || !node.hasAttribute(attr)) return;
const url = node.getAttribute(attr);
if (!url) return;
const result = getProcessedUrl(url);
node.setAttribute('data-booster-processed', 'true');
if (result.action === 'block') {
if (isScript) node.setAttribute('type', 'javascript/blocked');
node.remove();
} else if (result.action === 'replace') {
if (isScript) {
const newScript = document.createElement('script');
newScript.src = result.url;
newScript.setAttribute('data-booster-processed', 'true');
Array.from(node.attributes).forEach(a => {
if (a.name !== 'src' && a.name !== 'data-booster-processed' && a.name !== 'integrity') {
newScript.setAttribute(a.name, a.value);
}
});
if (node.parentNode) node.parentNode.insertBefore(newScript, node);
node.remove();
} else {
node.setAttribute(attr, result.url);
node.removeAttribute('integrity');
}
}
};
const observer = new MutationObserver(muts => {
muts.forEach(m => m.addedNodes.forEach(node => {
processNode(node);
if (node.querySelectorAll) node.querySelectorAll('script, link, iframe, img').forEach(processNode);
}));
});
observer.observe(document.documentElement, { childList: true, subtree: true });
document.querySelectorAll('script, link, iframe, img').forEach(processNode);
} // پایان بخش Fallback
// =========================================================
// 🟢 بخش مانیتورینگ: همیشه اجرا میشود (مستقل از وضعیت SW)
// =========================================================
let reportBuffer = [];
let reportTimer = null;
const DEBOUNCE_DELAY = 5000; // ارسال یکپارچه بعد از 5 ثانیه
function sendBatchedReports() {
if (reportBuffer.length === 0) return;
if (reportTimer) { clearTimeout(reportTimer); reportTimer = null; }
try {
const isAuthorizedUser = document.body && (
document.body.classList.contains('logged-in') ||
document.body.classList.contains('wp-admin')
);
if (isAuthorizedUser) {
const data = new FormData();
data.append('reports', JSON.stringify(reportBuffer));
if (navigator.sendBeacon) navigator.sendBeacon(reportUrl, data);
else fetch(reportUrl, { method: 'POST', body: data, keepalive: true }).catch(()=>{});
if (debug) console.log(`%c📊 [Zhaket Booster] Batch Report Sent: %c${reportBuffer.length} slow/failed items`, "color: green; font-weight: bold;", "color: inherit;");
}
} catch (e) {}
reportBuffer = [];
}
function queueReportItem(itemData) {
reportBuffer.push(itemData);
if (reportTimer) clearTimeout(reportTimer);
reportTimer = setTimeout(sendBatchedReports, DEBOUNCE_DELAY);
}
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') sendBatchedReports();
});
if (window.PerformanceObserver) {
const perfObserver = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
const result = getProcessedUrl(entry.name);
// منابعی که بلاک شدهاند یا متعلق به دامنه خودت هستند بررسی نمیشوند
if (result.action === 'block' || result.isLocal) return;
const isCached = entry.transferSize === 0 && entry.decodedBodySize > 0;
const isSlow = !isCached && entry.duration > maxTime;
const isFailed = 'responseStatus' in entry ? entry.responseStatus >= 400 : false;
if (isSlow || isFailed) {
if (debug) {
const status = isFailed ? `FAILED (HTTP ${entry.responseStatus || 'Error'})` : `${Math.round(entry.duration)}ms`;
console.log(`%c🐢 [Queued External Resource]%c ${entry.name} (${status})`, "color: orange; font-weight: bold;", "color: inherit;");
}
queueReportItem({
url: entry.name,
duration: isFailed ? (entry.responseStatus || 0) : entry.duration,
issue_type: isFailed ? 'failed' : 'slow'
});
}
});
});
perfObserver.observe({ type: 'resource', buffered: true });
}
})();
</script>