File & Directory Browser adalah script PHP tunggal (single-file PHP script) yang aman, responsif, dan sangat ringan untuk menampilkan daftar file serta direktori. Dilengkapi dengan fitur pengurutan instan, pencarian real-time tanpa reload halaman, verifikasi hash file (CRC32, MD5, SHA-1) menggunakan sistem cache lokal, perlindungan ketat dari eksploitasi path traversal, proteksi folder berbasis password dengan bcrypt hashing, serta antarmuka modern bertema glassmorphic berbasis Bootstrap 5 dan Font Awesome 6.
File & Directory Browser is a security-hardened, highly responsive, and lightweight single-file PHP script designed to display file and directory lists. It features real-time search without reloading, instant sorting, file hash verification (CRC32, MD5, SHA-1) with a local caching mechanism, strict protection against path traversal attacks, bcrypt-secured password-protected folders, and a premium glassmorphic user interface built using Bootstrap 5 and Font Awesome 6.
X-Robots-Tag: noindex, nofollow, noarchive dan <meta name="robots" content="noindex,nofollow">.HttpOnly, SameSite=Strict, dan Secure flag..cache otomatis menggunakan file .htaccess dan index.html kosong untuk webserver non-Apache (Nginx, Caddy, Lighttpd).password_hash / password_verify) โ password tidak pernah disimpan plaintext.bin2hex(random_bytes(32)) dengan regenerasi pasca-login./ atau Ctrl+K (Cmd+K di Mac) untuk langsung fokus ke pencarian, dan Escape untuk membersihkan serta melepas fokus.aria-sort, breadcrumb aria-current="page", indikator fokus keyboard :focus-visible, live region semantik <output class="empty-state">, serta dukungan @media (prefers-reduced-motion: reduce).phpcs), PHPStan Level Max (Level 9, 0 error), dan Psalm Level 3 (0 error).X-Robots-Tag: noindex, nofollow, noarchive and <meta name="robots" content="noindex,nofollow">.HttpOnly, SameSite=Strict, and Secure attributes..cache directory featuring both .htaccess and auto-generated index.html for non-Apache web servers (Nginx, Caddy, Lighttpd).password_hash / password_verify) โ passwords are never stored in plaintext.bin2hex(random_bytes(32)) tokens with post-login regeneration./ or Ctrl+K (Cmd+K on Mac) to jump to search, and Escape to clear and blur.aria-sort, active breadcrumbs with aria-current="page", visible keyboard focus rings (:focus-visible), semantic <output class="empty-state"> status region, and @media (prefers-reduced-motion: reduce) support.| Layanan / Requirement | Versi Minimum / Minimum Version |
|---|---|
| PHP | 8.0 atau lebih baru / or newer (Didukung hingga PHP 8.4+ / Tested up to PHP 8.4+) |
| PHP Extensions | session, hash, json, pcre, spl |
| Web Server | Apache (direkomendasikan / recommended), Nginx, Lighttpd, Caddy, dll |
Buka file index.php untuk menyesuaikan setelan variabel berikut di bagian paling atas:
$browseDirectories = true; // Mengizinkan penelusuran sub-direktori
$title = 'Index of '; // Format judul halaman utama
$subtitle = ' files'; // Format sub-judul halaman
$showDirectories = true; // Menampilkan direktori
$showDirectoriesFirst = true; // Mengurutkan direktori di posisi atas
$showHiddenFiles = false; // Menyembunyikan/menampilkan file dot (.)
$dateFormat = 'd-M-Y H:i'; // Format tanggal modifikasi file
$allowExternalSymlinks = false; // Mengizinkan symlink ke luar root
$enableHashCache = true; // Mengaktifkan penyimpanan cache hash file
$passwordSessionLifetime = 2400; // Durasi sesi login folder (detik)
// Generate bcrypt hash terlebih dahulu:
// php -r "echo password_hash('password_anda', PASSWORD_BCRYPT);"
$protectedFolders = [
'nama-folder' => '$2y$12$hashBcryptAnda...',
];
โ ๏ธ PENTING: Jangan pernah menyimpan password plaintext. Selalu gunakan hasil
password_hash().
$baseDir tidak dapat di-enumerate jika $allowExternalSymlinks bernilai false.$baseDir cannot be enumerated when $allowExternalSymlinks is false.index.html kosong secara otomatis di direktori .cache/ berdampingan dengan .htaccess guna mencegah kebocoran directory listing pada web server non-Apache (Nginx, Caddy, Lighttpd, PHP CLI server).index.html in .cache/ directory alongside .htaccess to prevent directory listing on non-Apache web servers (Nginx, Caddy, Lighttpd, PHP CLI server).X-Robots-Tag: noindex, nofollow, noarchive pada sendSecurityHeaders() serta tag <meta name="robots" content="noindex,nofollow"> pada halaman verifikasi password dan pengecekan hash untuk privasi indexing yang seragam.X-Robots-Tag: noindex, nofollow, noarchive in sendSecurityHeaders() and <meta name="robots" content="noindex,nofollow"> on password & hash check pages for unified search privacy.parse_url() sebelum mengakses $parsedUrl['path'], mencegah warning PHP 8 โTrying to access array offset on value of type falseโ saat menerima URI request yang malformed.parse_url() return value before accessing $parsedUrl['path'], preventing PHP 8 โTrying to access array offset on falseโ warning on malformed request URIs.\r dan \n pada URL pengalihan di normalizer URL untuk mencegah potensi serangan CRLF / HTTP response splitting.\r and \n in the URL normalizer redirector to prevent potential CRLF header injection.#noResultRow tidak muncul saat tidak ada file yang cocok akibat konflik style inline dengan class .hidden-row; beralih menggunakan classList.toggle('hidden-row').#noResultRow remained invisible when 0 files matched due to inline style conflict with .hidden-row stylesheet rule; switched to classList.toggle('hidden-row').#emptyRow) secara mulus selama pemfilteran pencarian aktif agar tidak terjadi tumpang-tindih teks.#emptyRow) gracefully during active search filtering.encodeRelativePath() yang sebelumnya terlewat pada link kembali ke direktori induk (..) di tabel daftar file.encodeRelativePath() to parent directory link in table body..footer menjadi #94a3b8) hingga mencapai rasio kontras 7.5:1+, lulus uji kepatuhan WCAG AAA..footer color #94a3b8), achieving a contrast ratio of > 7.5:1 and passing WCAG AAA compliance.aria-sort:
scope="col" dan atribut dinamis aria-sort (ascending/descending/none) pada elemen header tabel <th> melalui fungsi helper khusus.scope="col" and dynamic aria-sort attributes (ascending/descending/none) to header <th> elements via a dedicated helper function.aria-current="page" pada segmen breadcrumb aktif untuk memudahkan navigasi pembaca layar (screen reader).aria-current="page" to the active breadcrumb path segment for improved screen reader navigation.:focus-visible dengan outline aksen indigo pada seluruh link, tombol, dan input form untuk kenyamanan navigasi keyboard.:focus-visible outlines for links, buttons, and form inputs for seamless keyboard navigation.<output>:
role="status" pada elemen <tr> dengan elemen semantik native <output class="empty-state"> untuk kompatibilitas assistive device yang lebih universal.role="status" on <tr> with semantic <output class="empty-state"> for universal assistive device support.@media (prefers-reduced-motion: reduce) guna menghormati preferensi pengguna yang menonaktifkan atau meminimalkan animasi sistem.@media (prefers-reduced-motion: reduce) CSS rules to honor user motion preferences./ dan Ctrl+K (atau Cmd+K di macOS) untuk fokus instan ke kolom pencarian, serta Escape untuk mengosongkan dan melepas fokus input./ and Ctrl+K (Cmd+K on macOS) search shortcut to instantly focus the input, and Escape to clear search criteria and blur..hash-table th dan menambahkan fallback window.location.href pada tombol Back di halaman pengecekan hash jika riwayat peramban kosong..hash-table th elements and added fallback window.location.href to the back button on the hash verification page when browser history is empty.strnatcasecmp) pada fungsi usort() ketika kriteria tanggal atau ukuran memiliki nilai yang identik, menjamin urutan daftar selalu konsisten.strnatcasecmp) in usort() for deterministic ordering when date or size attributes match.aria-sort ke dalam fungsi pembantu getSortAriaAttribute().getSortAriaAttribute() helper function.phpcs --standard=PSR12.phpcs --standard=PSR12.APP_VERSION = '3.9.0' yang ditampilkan pada footer halaman.APP_VERSION = '3.9.0' constant displayed seamlessly in the application footer.bin2hex(random_bytes(32))
instead of non-cryptographic time-based hashing (uniqid + microtime). Added explicit DevSkim
ignore annotations (DS197836, DS126858) for intentional file checksum features
(md5, sha1), query string parameters, and filesystem cache keys.javascript:history.back() URI from hash page back-link; replaced with a proper
<button id="backBtn"> handled via nonce script block to fully comply with strict CSP
script-src policy.style="display:none" from #noResultRow element; moved to CSS class
.hidden-row to comply with strict CSP style-src policy.nonce attribute to <noscript><style> blocks on all pages for consistent CSP
compliance across all rendering paths.getSafeHost() is now validated to be within valid TCP range (1โ65535)
to prevent malformed Host header injection via out-of-range port values.<td> elements (date-primary
and date-secondary as separate columns) while file rows had 4. Unified date display so both dir
and file rows use a single <td class="date-cell"> containing both primary and secondary
spans inside, matching thead column count of 4.sanitizePath() preg_replace with /u modifier now has explicit fallback if the regex
fails due to invalid UTF-8 input, preventing silent null return.ensureCacheDir() now checks mkdir() return value and logs error on failure instead of
silently continuing, preventing obscure cache-write errors downstream.calculateHashes() now calls error_log() when fopen() fails, improving production
debuggability.writeHashCache() now verifies return value of rename() and logs on failure, ensuring
temp file cleanup even on rename failure.humanizeFilesize() now uses number_format() instead of round() to ensure consistent
decimal display (e.g., โ1.0 MBโ not โ1 MBโ).humanizeFilesize() caches count($units) before the loop to avoid repeated function calls
on every iteration.$unlockedSessions reference at directory browsing section replaced with explicit null-safe
array initialization to prevent potential reference warnings.$_GET['sort'] ?? 'name' and $_GET['order'] ?? 'asc' with explicit null coalescing
before allowlist check for strict_types safety.phpcbf and manual formatting fixes across all PHP
files to resolve all syntax, indentation, and spacing errors (0 PHPCS errors remaining).getMediaIconClass(), createHashCacheDir(),
readHashCache(), and listDirectory() to reduce multiple return statements (max 1 per function).isValidHashData(), processDirectoryItem(), and
getScandirFiles() helper functions, reducing cognitive complexity in readHashCache()
(from 22 to 2) and listDirectory() (from 24 to 3).buildDirectoryEntry() and sort button icons ($nameIcon, $dateIcon, $sizeIcon) with
clear if statements. Reduced parameter count of processDirectoryItem() from 9 to 5.foreach($requiredExtensions) sebelumnya ditempatkan di dalam blok if (version_compare()) setelah exit(), sehingga seluruh pemeriksaan ekstensi tidak pernah dieksekusi akibat brace yang salah posisi.foreach($requiredExtensions) was placed inside the version_compare() if-block after exit(), causing all extension checks to never execute due to a misplaced closing brace.e() escaping pada $lockedFolder di hidden input dan seluruh atribut HTML renderPasswordPage() untuk mencegah Reflected XSS melalui nama folder.e() escaping on $lockedFolder in the renderPasswordPage() hidden input and all HTML attributes to prevent Reflected XSS via folder name.queryUrl() Empty String:
queryUrl() kini mengembalikan '' (string kosong) alih-alih '?' saat parameter kosong, mencegah URL yang tidak valid pada link sortir dan breadcrumb.queryUrl() now returns '' (empty string) instead of '?' when params are empty, preventing malformed URLs in sort links and breadcrumbs.calculateHashes() fread Error:
calculateHashes() kini melakukan pengecekan fread() === false secara benar sebelum memanggil hash_update(), mencegah komputasi hash pada pembacaan file yang gagal.calculateHashes() now correctly short-circuits on fread() === false before calling hash_update(), preventing hash computation on failed reads.isValidHashData() Hex Length Validation:
isValidHashData() kini memvalidasi panjang hex string secara ketat per algoritma (crc32=8, md5=32, sha1=40) untuk menolak entri cache yang korup atau dipalsukan.isValidHashData() now strictly validates hex string length per algorithm (crc32=8, md5=32, sha1=40) to reject corrupt or spoofed cache entries.ensureCacheDir() Path Sanitization:
ensureCacheDir() kini membersihkan $hashCacheVersion sebelum menggunakannya sebagai komponen path filesystem untuk mencegah path injection.ensureCacheDir() now sanitizes $hashCacheVersion before using it as a filesystem path component to prevent path injection.@ suppression berlebihan pada fungsi I/O file (file_put_contents, rename, unlink, chmod, fopen) dan menggantinya dengan pemeriksaan nilai kembalian secara eksplisit.@ error suppression on file I/O functions (file_put_contents, rename, unlink, chmod, fopen) and replaced with explicit return-value checks.getFirstLockedFolder():
unlocked_folders yang kedaluwarsa di dalam getFirstLockedFolder() untuk mencegah membengkaknya data sesi secara tak terbatas.unlocked_folders session entries inside getFirstLockedFolder() to prevent unbounded session bloat over time.Content-Type Header:
Content-Type: text/html; charset=UTF-8 secara eksplisit di sendSecurityHeaders() untuk menghilangkan ketergantungan pada deteksi charset browser.Content-Type: text/html; charset=UTF-8 header in sendSecurityHeaders() to remove reliance on browser charset sniffing.(int) pada output $lockTimeRemaining di HTML untuk keamanan strict_types dan rendering bilangan bulat yang bersih.(int) cast on $lockTimeRemaining output in HTML for strict_types safety and clean integer rendering.style inline pada container halaman hash yang melanggar kebijakan CSP ketat.style attribute on the hash page container that violated the strict CSP policy.onsubmit inline pada form pencarian untuk kepatuhan penuh CSP script-src tanpa 'unsafe-inline'.onsubmit handler from the search form to achieve full CSP script-src compliance.session_regenerate_id(true) setelah verifikasi password folder berhasil untuk mencegah session fixation.session_regenerate_id(true) after successful folder password verification to prevent session fixation.X-XSS-Protection: 0 Header:
X-XSS-Protection: 0 untuk menonaktifkan XSS auditor browser lama (mencegah false positive).X-XSS-Protection: 0 header to disable the legacy browser XSS auditor and prevent false positives.isHiddenName() Static Cache:
strtolower di isHiddenName() menggunakan variabel static untuk menghindari pemanggilan array_map berulang.strtolower mapping in isHiddenName() using a static variable to avoid repeated array_map calls.humanizeFilesize() Loop Optimization:
humanizeFilesize().humanizeFilesize().ob_end_flush() Safety Check:
ob_end_flush dengan pemeriksaan ob_get_level() untuk keamanan.ob_end_flush shutdown handler with an ob_get_level() safety check.intdiv() untuk tampilan waktu penguncian guna mencegah keluaran float pada pesan yang terlihat pengguna.intdiv() for lock time display to prevent float output in user-facing messages.fa-folder-open) pada navigasi breadcrumb, sekaligus mempertahankan ikon folder tertutup standar pada tampilan daftar untuk konsistensi visual.fa-folder-open) in breadcrumb navigation while retaining standard closed folder icons in the file list view for visual consistency.%2F (slash ter-encode) yang sebelumnya menyebabkan spinner loader tidak berhenti.%2F) which previously caused the spinner loader to get stuck indefinitely.$loginMaxAttempts = 5) dan durasi penguncian login ($loginLockSeconds = 300) untuk proteksi folder dengan tampilan hitung mundur (countdown) secara real-time.if bersarang yang redundan.ob_end_flush() dari bagian akhir skrip ke register_shutdown_function() terpusat agar buffer selalu dibilas secara otomatis dan aman saat skrip berakhir.$loginMaxAttempts = 5) and temporary lockout timers ($loginLockSeconds = 300) with real-time countdown display.if statements to resolve code analyzer warnings.ob_end_flush() to a centralized register_shutdown_function() to ensure proper output buffer cleaning upon termination.h2 menggunakan var(--text-primary) dan .text-muted/.text-secondary agar kontras dan terbaca jelas.h2 heading color via var(--text-primary) and updating .text-muted/.text-secondary rules to use crisp high-contrast colors.folder menjadi berkas.index.php pada URL serta mengarahkan otomatis (HTTP 301) permintaan lama /index.php?folder=XXX menjadi /?berkas=XXX untuk SEO dan navigasi yang lebih bersih.folder to berkas.index.php path segment from URLs and implemented automatic redirects (HTTP 301) from /index.php?folder=XXX to /?berkas=XXX for cleaner SEO routing.%2F dalam parameter query berkas otomatis diterjemahkan kembali menjadi / (?berkas=folder1/subfolder1), dan mengarahkan otomatis jika diakses dengan format URL-encoded.%2F in query parameters back to slashes to display clean folder paths (e.g. ?berkas=folder1/subfolder1), redirecting requests containing URL-encoded %2F to clean slash representations.© 2009–2026 · All Rights Reserved) guna menghindari kendala rendering simbol di berbagai tipe browser.getFileIconClass(), menghapus 6 sub-fungsi pendukung untuk mempermudah pemeliharaan kode jangka panjang.getFileIconClass(), removing six helper subfunctions to maximize readability and ease of maintenance.style="..." pada elemen HTML (#search-form-container, #fileTable, dan tag <col>) untuk kepatuhan 100% terhadap Content Security Policy (CSP) tanpa 'unsafe-inline'.<noscript> dengan menyematkan nonce-key CSP secara dinamis..cssText di JavaScript menjadi modifikasi properti style individual guna mencegah pemblokiran CSP.style="..." attributes on HTML tags (#search-form-container, #fileTable, and <col> elements) to achieve 100% CSP compliance without relying on 'unsafe-inline'.<noscript> block..cssText manipulation to use individual style property settings instead, avoiding CSP style-src blocks.repo.alsyundawy.com โ tulisan tajam, terang, tidak buram, dan ramah mata.repo.alsyundawy.com โ featuring high readability, crisp text, and zero eye-strain.password_hash(PASSWORD_BCRYPT) / password_verify().=== menjadi password_verify() untuk mencegah timing attack.onclick diblokir oleh Content-Security-Policy โ dipindah ke nonce-tagged script block.array_values() setelah array_filter() untuk menghindari off-by-one pada subfolder dalam.?) dengan animasi hover dan dukungan dark/light mode.array_change_key_case($protectedFolders) ke luar loop foreach pada render tabel โ dari O(n) menjadi O(1).aria-label pada hash fingerprint link dan aria-hidden="true" pada ikon dekoratif.findOriginalFolderKey() untuk mereduksi cognitive complexity pada getFirstLockedFolder().listDirectory, processDirectoryItem, readHashCache) dengan memisahkannya ke helper functions yang modular dan memiliki satu jalur return.secure secara eksplisit.background-clip bersama dengan -webkit-background-clip.<button> untuk menunjang kontrol aksesibilitas via keyboard.realpath yang berat pada symlink.isDisplayableFolder guna mencegah kebocoran direktori tersembunyi.[!IMPORTANT]
๐ฎ๐ฉ Bahasa Indonesia (DocNote)
- Hak Akses Direktori Cache: Pastikan direktori tempat script dijalankan memiliki izin tulis (write permission) agar script dapat membuat direktori
.cacheotomatis. Jika hak akses tidak tersedia, fitur penyimpanan cache hash akan dinonaktifkan demi keselamatan runtime.- Dukungan SSL/HTTPS: Untuk keamanan optimal, jalankan script ini di lingkungan yang didukung HTTPS untuk menjamin enkripsi cookie sesi CSRF dan token transit.
- Pemblokiran File Sensitif: Secara bawaan, script memblokir file berekstensi seperti
.php,.bat,.env,.sql, dan sejenisnya untuk mencegah eksekusi kode berbahaya serta kebocoran informasi kredensial.- Password Folder โ Wajib Hash: Password untuk fitur proteksi folder TIDAK BOLEH disimpan dalam bentuk teks biasa (plaintext). Gunakan selalu hasil dari
password_hash('password_anda', PASSWORD_BCRYPT). Jalankan perintah berikut untuk generate hash:php -r "echo password_hash('password_anda', PASSWORD_BCRYPT);"- CSP & Inline Event Handler: Script ini menggunakan Content-Security-Policy berbasis nonce. Inline
onclick=""attribute pada HTML akan diblokir oleh CSP โ semua event listener harus didaftarkan dalam<script nonce="...">block.- Proteksi Multi-Webserver: Folder
.cache/secara otomatis membuat file.htaccessdanindex.htmlkosong untuk mencegah directory listing di Apache, Nginx, Caddy, Lighttpd, maupun PHP Built-in Server.- Pintasan Keyboard Pencarian: Tekan
/atauCtrl+K(Cmd+Kdi macOS) di mana saja pada halaman untuk langsung fokus ke kotak pencarian, dan tekanEscapeuntuk menghapus teks pencarian dan melepas fokus input.- Kepatuhan Aksesibilitas (WCAG 2.2 AA/AAA): Script memenuhi standar aksesibilitas terkini dengan kontras warna tinggi (WCAG AAA), navigasi keyboard dengan
:focus-visible, penanda lokasiaria-current="page", status sortiraria-sort, pembaca layar semantik<output class="empty-state">, serta dukunganprefers-reduced-motion.๐ฌ๐ง English (DocNote)
- Cache Folder Permissions: Ensure that the directory where the script executes has write permissions so it can spawn the
.cachefolder automatically. If permissions are missing, hash caching will be bypassed gracefully to ensure execution.- HTTPS/SSL Deployment: It is highly recommended to host this script under an SSL/HTTPS enabled domain to guarantee safe transit of session cookies and browser tokens.
- Exclusion of Sensitive Files: By default, critical file formats including
.php,.bat,.env,.sql, and others are locked from being displayed or hashed to prevent unauthorized code execution and credential leakage.- Folder Passwords โ Must Be Hashed: Folder protection passwords MUST NOT be stored as plaintext. Always use the output of
password_hash('your_password', PASSWORD_BCRYPT). Generate a hash with:php -r "echo password_hash('your_password', PASSWORD_BCRYPT);"- CSP & Inline Event Handlers: This script uses a nonce-based Content-Security-Policy. Inline
onclick=""HTML attributes will be blocked by CSP โ all event listeners must be registered inside a<script nonce="...">block.- Multi-Web Server Protection: The
.cache/folder automatically generates both.htaccessand an emptyindex.htmlfile to prevent directory listing across Apache, Nginx, Caddy, Lighttpd, and the PHP Built-in Server.- Search Keyboard Shortcuts: Press
/orCtrl+K(Cmd+Kon macOS) anywhere on the page to immediately focus the search input, and pressEscapeto clear search criteria and blur the input field.- Accessibility Compliance (WCAG 2.2 AA/AAA): The script adheres to modern accessibility standards featuring high contrast ratios (WCAG AAA), keyboard navigation with
:focus-visible, breadcrumbaria-current="page", table headeraria-sort, semantic<output class="empty-state">screen reader live region, andprefers-reduced-motionsupport.
Anda bebas untuk mengubah, mendistribusikan script ini untuk keperluan anda.
If you find this project helpful and would like to support it, please consider donating via https://www.paypal.me/alsyundawy or https://ko-fi.com/alsyundawy. Thank you for your support!
Jika Anda merasa terbantu dan ingin mendukung proyek ini, pertimbangkan untuk berdonasi melalui https://www.paypal.me/alsyundawy atau https://ko-fi.com/alsyundawy. Terima kasih atas dukungannya!
Jika Anda merasa terbantu dan ingin mendukung proyek ini, pertimbangkan untuk berdonasi melalui QRIS. Terima kasih atas dukungannya!
MIT License โ Copyright ยฉ 2026 HARRY DS ALSYUNDAWY โ ALSYUNDAWY IT SOLUTION
Note: Please retain credit to the original author (HARRY DS ALSYUNDAWY โ ALSYUNDAWY IT SOLUTION) if you use or modify this script. Attribution is appreciated but not legally required under the MIT License.