AUTH_SESSION_TTL) return false; $_SESSION['nfm_last'] = time(); return true; } function do_login($u, $p){ if ($u === AUTH_USERNAME && make_pwd_hash($p) === AUTH_PASSWORD_MD5){ $_SESSION = array(); session_regenerate_id(true); $_SESSION['nfm_user'] = $u; $_SESSION['nfm_last'] = time(); return true; } return false; } function do_logout(){ $_SESSION = array(); if (ini_get('session.use_cookies')) { $params = session_get_cookie_params(); setcookie(session_name(), '', time()-42000, $params['path'], $params['domain'], !empty($params['secure']), !empty($params['httponly'])); } session_destroy(); } /* ===================== DEV HELPER: BUAT HASH PASSWORD (MD5) ===================== */ if (isset($_GET['a']) && $_GET['a']==='makehash') { $err = ''; if ($_SERVER['REQUEST_METHOD']==='POST'){ $p = isset($_POST['p'])?$_POST['p']:''; if ($p===''){ $err='Masukkan password'; } else { $h = make_pwd_hash($p); header('Content-Type: text/plain; charset=utf-8'); echo "MD5 (tempel ke AUTH_PASSWORD_MD5):\n".$h."\n"; exit; } } ?> Buat Hash Password (MD5)

Buat Hash Password (MD5)

'.$err.'
'; } ?>


Setelah dapat hash, tempel ke konstanta AUTH_PASSWORD_MD5 pada file ini.

Catatan: MD5 tidak direkomendasikan untuk sistem publik.

absolut berbasis $base (cwd) */ function resolvePath($candidate, $base){ $c = trim((string)$candidate); if ($c === '') return $base; if (isWindows()){ if (preg_match('#^[A-Za-z]:\\\\#',$c) || strpos($c,'\\\\')===0) return $c; // absolut return rtrim($base, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$c; } else { if (strpos($c,'/') === 0) return $c; // absolut return rtrim($base, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$c; } } function isTextFile($path){ $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); $textExt = array('txt','md','log','json','xml','yml','yaml','csv','ini','cfg','conf','php','js','ts','css','scss','less','html','htm','sh','bat','py','java','kt','c','cpp','cs','go','rb','lua','sql'); if (in_array($ext, $textExt, true)) return true; if (is_file($path) && is_readable($path) && filesize($path) <= MAX_EDIT_BYTES){ $sample = @file_get_contents($path, false, null, 0, 1024); if ($sample === false) return false; return (strpos($sample, "\0") === false); } return false; } function isImageFile($path){ $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return in_array($ext, array('png','jpg','jpeg','gif','webp','bmp','svg'), true); } function bytesHuman($b){ $u = array('B','KB','MB','GB','TB'); $i=0; while ($b>=1024 && $igetPathname(), strlen($src)+1); $to = rtrim($dst, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$rel; if ($f->isDir()){ if (!is_dir($to)) @mkdir($to, 0775, true); } else { @copy($f->getPathname(), $to); } } return true; } function h($s){ return htmlspecialchars($s,ENT_QUOTES,'UTF-8'); } function q($s){ return rawurlencode($s); } function breadcrumbAbs($path){ if (isWindows()){ $p = rtrim($path, DIRECTORY_SEPARATOR); if (preg_match('#^([A-Za-z]:)\\\\?#', $p, $m)) { $drive = $m[1]; $rest = trim(substr($p, strlen($drive)), "\\/"); $parts = $rest !== '' ? explode('\\', $rest) : array(); $crumbs = array(''.h($drive.'\\').''); $accum = $drive.'\\'; foreach($parts as $seg){ $accum = rtrim($accum, '\\').'\\'.$seg; $crumbs[] = ''.h($seg).''; } return implode(' / ', $crumbs); } else { $rest = ltrim($p, "\\"); $parts = $rest!=='' ? explode('\\', $rest) : array(); $accum = '\\\\'; $crumbs = array(''.h('\\\\').''); foreach($parts as $seg){ $accum = rtrim($accum, '\\').'\\'.$seg; $crumbs[] = ''.h($seg).''; } return implode(' / ', $crumbs); } } else { $p = rtrim($path, '/'); if ($p === '') $p = '/'; if ($p === '/') return '/'; $rel = ltrim($p, '/'); $parts = $rel !== '' ? explode('/', $rel) : array(); $crumbs = array('/'); $accum = ''; foreach($parts as $seg){ $accum .= '/'.$seg; $crumbs[] = ''.h($seg).''; } return implode(' / ', $crumbs); } } /* ===================== ROUTING LOGIN ===================== */ $action = isset($_GET['a'])?$_GET['a']:''; if ($action === 'logout'){ do_logout(); header('Location: ?'); exit; } if (AUTH_ENABLED && !is_logged_in()){ $err = ''; if ($action==='login' && $_SERVER['REQUEST_METHOD']==='POST'){ $u = isset($_POST['u'])?$_POST['u']:''; $p = isset($_POST['p'])?$_POST['p']:''; if (do_login($u,$p)){ $redir = isset($_GET['p']) ? '?p='.q($_GET['p']) : '?'; header('Location: '.$redir); exit; } else { $err = 'Username atau password salah.'; } } ?> <?php echo h(APP_TITLE); ?> – Login

'.h($err).'
'; } ?>


Buat hash MD5 di ?a=makehash, lalu tempel ke file.
'text/plain','log'=>'text/plain','md'=>'text/markdown','json'=>'application/json', 'xml'=>'application/xml','svg'=>'image/svg+xml','png'=>'image/png','jpg'=>'image/jpeg', 'jpeg'=>'image/jpeg','gif'=>'image/gif','webp'=>'image/webp','css'=>'text/css','js'=>'application/javascript','html'=>'text/html','htm'=>'text/html' ); $ct = isset($map[$ext])?$map[$ext]:'application/octet-stream'; header('Content-Type: '.$ct.'; charset=utf-8'); header('Content-Length: '.filesize($path)); readfile($path); exit; } if ($action==='zip' && $_SERVER['REQUEST_METHOD']==='POST' && ALLOW_ZIP && is_dir($cwd) && is_writable($cwd)){ $items = isset($_POST['items'])?$_POST['items']:array(); $zipName = trim(isset($_POST['zipname'])?$_POST['zipname']:'archive_'.date('Ymd_His').'.zip'); if (!$items) exit('Tidak ada item dipilih.'); $zipPath = rtrim($cwd, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$zipName; if (file_exists($zipPath)) exit('Nama arsip sudah ada.'); if (class_exists('ZipArchive')){ $zip = new ZipArchive(); if ($zip->open($zipPath, ZipArchive::CREATE)!==TRUE) exit('Gagal membuat ZIP.'); foreach($items as $rel){ $abs = rtrim($cwd, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$rel; $abs = safePath($abs); if (is_dir($abs) && is_readable($abs)){ $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($abs, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST); $base = basename($abs); foreach($it as $f){ $local = $base.'/'.substr($f->getPathname(), strlen($abs)+1); $local = str_replace(DIRECTORY_SEPARATOR,'/',$local); if ($f->isDir()) $zip->addEmptyDir($local); else $zip->addFile($f->getPathname(), $local); } } elseif (is_file($abs) && is_readable($abs)){ $zip->addFile($abs, basename($abs)); } } $zip->close(); header('Location: ?p='.rawurlencode($cwd).'&msg='.rawurlencode('ZIP dibuat: '.$zipName)); exit; } else exit('ZipArchive tidak tersedia.'); } if ($action==='unzip' && $_SERVER['REQUEST_METHOD']==='POST' && ALLOW_UNZIP){ $zipIn = isset($_POST['zipfile']) ? $_POST['zipfile'] : ''; $toIn = isset($_POST['todir']) ? $_POST['todir'] : ''; // perbaikan: relatif dari $cwd $zipFile = safePath(resolvePath($zipIn, $cwd)); $toDir = safePath(resolvePath($toIn !== '' ? $toIn : $cwd, $cwd)); if (!is_readable($zipFile)) exit('File arsip tidak dapat dibaca.'); if (!is_dir($toDir)) @mkdir($toDir,0775,true); if (!is_dir($toDir) || !is_writable($toDir)) exit('Tujuan tidak bisa dipakai.'); $done=false; if (class_exists('ZipArchive') && strtolower(pathinfo($zipFile,PATHINFO_EXTENSION))==='zip'){ $zip=new ZipArchive(); if($zip->open($zipFile)===TRUE){ $zip->extractTo($toDir); $zip->close(); $done=true; } } if(!$done && class_exists('PharData')){ try{ $phar=new PharData($zipFile); $phar->extractTo($toDir,null,true); $done=true; }catch(Exception $e){} } if(!$done) exit('Gagal extract (ZipArchive/PharData tidak tersedia/format tidak didukung).'); header('Location: ?p='.rawurlencode($toDir).'&msg='.rawurlencode('Unzip berhasil')); exit; } if ($action==='upload' && $_SERVER['REQUEST_METHOD']==='POST'){ // SELALU ke folder aktif $dest = is_dir($cwd) ? $cwd : START_DIR; if (!is_writable($dest)) exit('Folder tujuan tidak writable.'); $notif=array(); if (!empty($_FILES['files'])){ $files = array(); if (is_array($_FILES['files']['name'])){ $count = count($_FILES['files']['name']); for($i=0;$i<$count;$i++){ $files[] = array( 'name' => $_FILES['files']['name'][$i], 'tmp' => $_FILES['files']['tmp_name'][$i], 'err' => $_FILES['files']['error'][$i], ); } } else { $files[] = array( 'name' => $_FILES['files']['name'], 'tmp' => $_FILES['files']['tmp_name'], 'err' => $_FILES['files']['error'], ); } foreach($files as $f){ $name=$f['name']; $tmp=$f['tmp']; $err=$f['err']; if ($err!==UPLOAD_ERR_OK){ $notif[]="❌ {$name} (error {$err})"; continue; } $target = uniqueName($dest, $name); $in = @fopen($tmp, 'rb'); if (!$in){ $notif[]="❌ gagal buka tmp untuk {$name}"; continue; } $out = @fopen($target, 'xb'); if (!$out){ fclose($in); $notif[]="❌ gagal tulis {$name}"; continue; } $ok = stream_copy_to_stream($in, $out) !== false; fclose($in); fclose($out); if (!$ok){ @unlink($target); $notif[]="❌ gagal salin {$name}"; continue; } @chmod($target, 0664); $notif[] = "✅ ".basename($target); } } header('Location: ?p='.rawurlencode($dest).'&msg='.rawurlencode(implode(' | ',$notif))); exit; } if ($action==='newfile' && $_SERVER['REQUEST_METHOD']==='POST'){ $dir = $cwd; if (!is_dir($dir) || !is_writable($dir)) exit('Folder tujuan tidak writable.'); $name = trim(isset($_POST['name'])?$_POST['name']:''); $content = isset($_POST['content'])?$_POST['content']:''; if ($name==='') exit('Nama file kosong.'); $target=uniqueName($dir,$name); if (@file_put_contents($target,$content)===false) exit('Gagal membuat file.'); header('Location: ?p='.rawurlencode($target).'&msg='.rawurlencode('File dibuat.')); exit; } if ($action==='newdir' && $_SERVER['REQUEST_METHOD']==='POST'){ $dir = $cwd; if (!is_dir($dir) || !is_writable($dir)) exit('Folder tujuan tidak writable.'); $name=trim(isset($_POST['name'])?$_POST['name']:''); if ($name==='') exit('Nama folder kosong.'); $target=rtrim($dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$name; if (file_exists($target)) exit('Folder sudah ada.'); if (!@mkdir($target,0775,true)) exit('Gagal membuat folder.'); header('Location: ?p='.rawurlencode($target).'&msg='.rawurlencode('Folder dibuat.')); exit; } if ($action==='rename' && $_SERVER['REQUEST_METHOD']==='POST'){ $old = safePath(isset($_POST['old'])?$_POST['old']:''); $newBase = trim(isset($_POST['new'])?$_POST['new']:''); // Sanitasi: hapus path separator agar tetap di folder yang sama $newBase = preg_replace('#[\\\\/]+#','', $newBase); if ($newBase==='') exit('Nama baru kosong / tidak valid.'); $dstDir = dirname($old); if (!is_writable($old)) exit('Sumber tidak writable.'); if (!is_writable($dstDir)) exit('Folder tujuan tidak writable.'); $candidate = rtrim($dstDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$newBase; $new = file_exists($candidate) ? uniqueName($dstDir, $newBase) : $candidate; if (!@rename($old,$new)) exit('Gagal rename.'); header('Location: ?p='.rawurlencode($new).'&msg='.rawurlencode('Rename berhasil.')); exit; } function rrmdir($dir){ if (!is_dir($dir)) return false; $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST); foreach($it as $f){ if ($f->isDir()) @rmdir($f->getPathname()); else @unlink($f->getPathname()); } return @rmdir($dir); } if ($action==='delete' && $_SERVER['REQUEST_METHOD']==='POST'){ $target=safePath(isset($_POST['target'])?$_POST['target']:''); $ok=false; if (is_dir($target)) $ok=rrmdir($target); elseif (is_file($target)) $ok=@unlink($target); header('Location: ?p='.rawurlencode(dirname($target)).'&msg='.rawurlencode($ok?'Terhapus.':'Gagal hapus.')); exit; } if ($action==='save' && $_SERVER['REQUEST_METHOD']==='POST'){ $file=safePath(isset($_POST['file'])?$_POST['file']:''); $content=isset($_POST['content'])?$_POST['content']:''; if (!is_file($file) || !is_writable($file)) exit('File tidak bisa ditulis.'); if (strlen($content) > MAX_EDIT_BYTES) exit('Konten terlalu besar.'); $ok = (@file_put_contents($file,$content)!==false); header('Location: ?p='.rawurlencode($file).'&msg='.rawurlencode($ok?'Tersimpan.':'Gagal simpan.')); exit; } if ($action==='chmod' && $_SERVER['REQUEST_METHOD']==='POST' && ALLOW_CHMOD){ $target=safePath(isset($_POST['target'])?$_POST['target']:''); $mode=isset($_POST['mode'])?$_POST['mode']:''; if (!preg_match('/^[0-7]{3,4}$/',$mode)) exit('Mode tidak valid.'); $ok=@chmod($target, octdec($mode)); header('Location: ?p='.rawurlencode($target).'&msg='.rawurlencode($ok?'CHMOD ok.':'CHMOD gagal.')); exit; } if ($action==='move' && $_SERVER['REQUEST_METHOD']==='POST'){ $src = safePath(isset($_POST['src'])?$_POST['src']:''); $dstDir = safePath(isset($_POST['dst'])?$_POST['dst']:''); if (!file_exists($src)) exit('Sumber tidak ditemukan.'); if (!is_dir($dstDir)) exit('Tujuan harus folder.'); if (!is_writable($dstDir)) exit('Tujuan tidak writable.'); if (is_dir($src) && isDescendantPath($src, $dstDir)) exit('Tidak boleh memindah folder ke dalam dirinya sendiri / turunannya.'); $target = uniqueName($dstDir, basename($src)); $ok = @rename($src, $target); if (!$ok){ $ok = (is_dir($src)?(copyDir($src, $target) && rrmdir($src)):(@copy($src, $target) && @unlink($src))); } header('Location: ?p='.rawurlencode($ok?$target:$src).'&msg='.rawurlencode($ok?'Dipindah.':'Gagal pindah.')); exit; } /* ===== Listing ===== */ $sortBy = isset($_GET['sort'])?$_GET['sort']:'name'; $sortDir = isset($_GET['dir'])?$_GET['dir']:'asc'; $keyword = ($action==='search' && ALLOW_SEARCH)?trim(isset($_GET['q'])?$_GET['q']:''):''; $items = array(); if (is_dir($cwd) && is_readable($cwd)){ if ($action==='search' && $keyword!==''){ $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cwd, FilesystemIterator::SKIP_DOTS)); foreach($it as $fi){ $p = $fi->getPathname(); if (stripos($p,$keyword)!==false){ $items[] = array('name'=>$fi->getFilename(),'path'=>$p,'is_dir'=>$fi->isDir(),'size'=>$fi->isFile()?$fi->getSize():0,'mtime'=>$fi->getMTime()); } } } else { $scan=@scandir($cwd); if ($scan){ foreach($scan as $n){ if ($n==='.'||$n==='..') continue; $p=rtrim($cwd, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$n; $items[] = array('name'=>$n,'path'=>$p,'is_dir'=>@is_dir($p),'size'=>@is_file($p)?@filesize($p):0,'mtime'=>@filemtime($p)?@filemtime($p):0); } } } $items = sortItems($items,$sortBy,$sortDir); } $authUser = AUTH_ENABLED ? AUTH_USERNAME : 'guest'; ?> <?php echo h(APP_TITLE); ?>

User: Logout
'.h((string)$_GET['msg']).'
'):''; ?>
Buat File Baru



Unzip / Extract Arsip
Isi Folder: Sort: Nama · Ukuran · Diubah
(Centang kolom paling kiri)
#NamaUkuranDiubahModeAksi
⬆️ .. (naik)
📁 📄 ⬇️ 👁️ ✏️ 📦 📝 🔧
Kosong / tak terbaca.

Pratinjau & Edit: (read-only)'; ?>



Batal

Pratinjau Gambar:

Pratinjau Teks: