<?php if (!defined('DASHBOARD_ROOT')) { http_response_code(403); exit; } RBAC::enforce('manage.fleet'); require_once __DIR__ . '/../modules/security/obfuscation_handler.php'; ?> <div class="tab-workspace" id="ws-obfuscation"> <div class="ws-header"> <div class="ws-title-block"> <div class="ws-kicker">PROTECTION</div> <h2 class="ws-title">Obfuscation</h2> <div class="ws-subtitle">DOM rotation and source code camouflage</div> </div> </div> <div class="ws-body"> <div id="obf-status" style="margin-top:20px"> <div style="text-align:center;padding:60px;color:var(--text-dim);font-size:12px">Loading obfuscation status...</div> </div> <div id="obf-preview" style="margin-top:20px"></div> </div> </div> <script nonce="<?= $cspNonce ?>"> (function(){ function getCSRF(){var m=document.querySelector('meta[name="csrf-token"]');return m?m.content:'';} function esc(s){var d=document.createElement('div');d.textContent=s;return d.innerHTML;} function loadStatus(){ var fd=new FormData();fd.append('_obf_action','status');fd.append('_csrf',getCSRF()); fetch('',{method:'POST',body:fd,credentials:'same-origin'}).then(function(r){return r.json()}).then(function(d){ if(!d.ok)return;var s=d.stats;var el=document.getElementById('obf-status'); var h='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:16px">'; [{label:'CSS Classes',value:s.css_classes,color:'var(--blue)'},{label:'Tables',value:s.tables,color:'var(--green)'},{label:'Columns',value:s.columns,color:'var(--yellow)'},{label:'Files',value:s.files,color:'var(--red)'},{label:'IDs',value:s.ids,color:'var(--purple,#a78bfa)'}].forEach(function(c){ h+='<div style="background:rgba(255,255,255,.03);border:1px solid var(--border);border-radius:var(--radius-md);padding:20px;text-align:center"><div style="font-size:28px;font-weight:700;color:'+c.color+'">'+c.value+'</div><div style="font-size:9px;text-transform:uppercase;letter-spacing:1.2px;color:var(--text-dim);margin-top:6px">'+c.label+'</div></div>'; }); h+='</div>'; h+=s.last_rotation?'<div style="margin-top:16px;font-size:10px;color:var(--text-dim)">Last rotation: '+s.last_rotation+'</div>':'<div style="margin-top:16px;font-size:10px;color:var(--yellow)">No manifest found. Obfuscation not yet initialized.</div>'; h+='<div style="margin-top:20px;display:flex;gap:10px"><button class="ws-action-btn" id="btn-obf-preview">Preview Manifest</button></div>'; el.innerHTML=h; document.getElementById('btn-obf-preview').addEventListener('click',loadPreview); }); } function loadPreview(){ var fd=new FormData();fd.append('_obf_action','preview');fd.append('_csrf',getCSRF()); fetch('',{method:'POST',body:fd,credentials:'same-origin'}).then(function(r){return r.json()}).then(function(d){ if(!d.ok)return;var el=document.getElementById('obf-preview'); if(!d.sample.length){el.innerHTML='<div style="padding:20px;color:var(--text-dim);font-size:11px">Manifest is empty</div>';return;} var h='<div style="font-size:10px;text-transform:uppercase;letter-spacing:1.2px;color:var(--text-dim);margin-bottom:10px">Manifest Sample</div>'; h+='<table style="width:100%;border-collapse:collapse;font-size:11px"><thead><tr style="color:var(--text-dim);text-align:left"><th style="padding:6px 10px">Type</th><th style="padding:6px 10px">Original</th><th style="padding:6px 10px">Obfuscated</th></tr></thead><tbody>'; d.sample.forEach(function(s){h+='<tr style="border-top:1px solid var(--border)"><td style="padding:6px 10px;color:var(--blue)">'+esc(s.type)+'</td><td style="padding:6px 10px;font-family:monospace;color:var(--text-bright)">'+esc(s.original)+'</td><td style="padding:6px 10px;font-family:monospace;color:var(--green)">'+esc(s.obfuscated)+'</td></tr>';}); h+='</tbody></table>';el.innerHTML=h; }); } loadStatus(); })(); </script>