24 March 2012

Fancy Directory Listing

Pembaca yang budiman, ada kalanya kita ingin membuat sebuah directory yang ada dalam server yang kita miliki bisa di browse layaknya file explorer. Beberapa server menyediakan fitur tersebut, fitur tersebut dinamakan directory listing. Namun tampilan dari directory listing tersebut  sangatlah standar seperti gambar di atas.
Dalam percobaan kali ini kita ingin membuat tampilan diatas lebih style supaya lebih menarik. Kita akan mencoba membuatnya dengan menggunakan script php dan css. Tentunya server yang kita miliki sudah terintegrasi dengan php.
Ok, beriikut skenario yang akan kita lakukan:
  1. Sebuah file php akan menjadi interface utama oleh karena itu kita harus menamakan file ini dengan nama index.php, sehingga ketika user ingin membuka URL directory listing tersebut maka default file index.php otomatis akan diberikan.
  2. File php ini bertugas me-list-ing seluruh file dan folder yang ada dalam directory tersebut dan menampilkannya dengan link yang tertuju pada file atau folder itu sendiri.
  3. File index.php yang mana merupakan file itu sendiri tidak boleh ditampilkan pada directory listing tersebut.
  4. Untuk icon yang akan kita perlukan kita bisa membuat icon-nya sendiri, atau mengambil dari repository server yang sudah ter-install. Dalam server Apache biasanya sudah terdistribusi dengan url tertentu.
Mari kita lakukan, sekarang coba kita lihat code file index.php dibawah ini :

<?php
$dir = dirname(".");
$files1 = scandir($dir);
$item = "";
$type = "";
$size = "";
$lastMod = "";

foreach ($files1 as $dirItem) {
        if (!fnmatch("index.php", $dirItem)) {
                if (is_file($dirItem)) {
                        $type = "File";
                        $size = filesize($dirItem)." B";
                        $lastMod = filemtime($dirItem);
                        $ext = pathinfo($dirItem, PATHINFO_EXTENSION);
                } else {
                        $type = "Dir";
                        $size = "0 B";
                        $lastMod = filemtime($dirItem);
                        $ext = "dir";
                }

                //display
                $item .= "<tr>";
                $item .= "<td><a href='$dirItem'>" . $dirItem . "</a></td>";
                $item .= "<td>" . date("d-M-Y H:i:s", $lastMod) . "</td>";
                $item .= "<td align='right'>$size</td>";
                $item .= "<tr>";
        }
}
?>
<html>
<head>
</head>
<body >
<center>
        <h3>Index Of <?php echo  dirname($_SERVER['PHP_SELF'])?> </h3>
        <table border=1>
                <th>Index</th>
                <th>Last Modified</th>
                <th>Size</th>
                <?php echo $item;?>
        </table>
        <?php echo $_SERVER['SERVER_SOFTWARE']; ?>
</center>
</body>
</html>




Mari kita bahas satu persatu kode diatas.

$dir = dirname(".");
$files1 = scandir($dir);
$item = "";
$type = "";
$size = "";
$lastMod = "";


Pada baris pertama kita mendeklarasikan variabel dir yang memiliki nilai current directory dimana file ini berada, kemudian baris selanjutnya kita melakukan scanning seluruh isi directory dengan method scandir(); milik php, dan baris-baris selanjutnya adalah baris-baris deklarasi variabel yang nantinya akan kita pakai pada baris-baris selanjutnya. 

Perhatikan baris-baris dibawah ini lagi:

foreach ($files1 as $dirItem) {
        if (!fnmatch("index.php", $dirItem)) {
                if (is_file($dirItem)) {
                        $type = "File";
                        $size = filesize($dirItem)." B";
                        $lastMod = filemtime($dirItem);
                        $ext = pathinfo($dirItem, PATHINFO_EXTENSION);
                } else {
                        $type = "Dir";
                        $size = "0 B";
                        $lastMod = filemtime($dirItem);
                        $ext = "dir";
                }

                //display
                $item .= "<tr>";
                $item .= "<td><a href='$dirItem'>" . $dirItem . "</a></td>";
                $item .= "<td>" . date("d-M-Y H:i:s", $lastMod) . "</td>";
                $item .= "<td align='right'>$size</td>";
                $item .= "<tr>";
        }
}




Kode diatas mendeskripsikan bagaimana kita me-loop array hasil scanning, dimana dalam loop tersebut ada blok  yang memeriksa apakah dirItem tidak sama dengan pattern index.php, jika memang tidak sama, kemudian kita fetch info-info yang kita perlukan untuk ditampilkan. Dalam blok pemeriksaan dirItem juga ada blok yang memeriksa apakah dirItem tersebut adalah file atau folder, sebab untuk folder tidak mungkin kita bisa mem-fetch info besarnya size folder tersebut. Jika digambarkan dalam sebuah diagram Flowchart, bisa dilihat dalam diagram berikut ini:
Mungkin saja diagram tersebut menyalahi aturan penulisan diagram, tapi mudah-mudahan dengan diagram tersebut kode diatas bisa lebih mudah dipahami :P. 
Kemudian perhatikan kode-kode berikut ini:

<html>
<head>
</head>
<body >
<center>
        <h3>Index Of <?php echo  dirname($_SERVER['PHP_SELF'])?> </h3>
        <table border=1>
                <th>Index</th>
                <th>Last Modified</th>
                <th>Size</th>
                <?php echo $item;?>
        </table>
        <?php echo $_SERVER['SERVER_SOFTWARE']; ?>
</center>
</body>
</html>


Nah kode diatas adalah layout-tampilan dari kode-kode yang sudah kita buat sebelumnya. Sampai disini percobaan pertama kita sudah selesai. Tinggal kita tambahkan beberapa fungsi dalam agar bisa dipakai dalam kode-kode yang tadi. Misal fungsi mengkonversi dari ukuran byte ke ukuran yang lebih besar seperti KB, MB, dan lain-lain. 
Berikut ini adalah kode yang berisi fungsi-fungsi yang bisa dipakai.
  1. Fungsi Konversi ukuran Byte.
    
    function _format_bytes($a_bytes) {
            if ($a_bytes < 1024) {
                    return $a_bytes . ' B';
            } elseif ($a_bytes < 1048576) {
                    return round($a_bytes / 1024, 2) . ' KB';
            } elseif ($a_bytes < 1073741824) {
                    return round($a_bytes / 1048576, 2) . ' MB';
            } elseif ($a_bytes < 1099511627776) {
                    return round($a_bytes / 1073741824, 2) . ' GB';
            } elseif ($a_bytes < 1125899906842624) {
                    return round($a_bytes / 1099511627776, 2) . ' TB';
            } elseif ($a_bytes < 1152921504606846976) {
                    return round($a_bytes / 1125899906842624, 2) . ' PB';
            } elseif ($a_bytes < 1180591620717411303424) {
                    return round($a_bytes / 1152921504606846976, 2) . ' EB';
            } elseif ($a_bytes < 1208925819614629174706176) {
                    return round($a_bytes / 1180591620717411303424, 2) . ' ZB';
            } else {
                    return round($a_bytes / 1208925819614629174706176, 2) . ' YiB';
            }
    }
    
    
  2. Fungsi Untuk memfetch Icon.
    
    function _get_icon($ext) {
            $ext = strtolower($ext);
            if ($ext == "dir") {
                    return "<image src='/icons/dir.png' width='12' height=12>";
            } elseif ($ext == "pdf" || $ext == "html" || $ext == "shtml" || $ext == "htm") {
                    return "<image src='/icons/layout.gif' width='12' height=12>";
            } elseif ($ext == "rar" || $ext == "zip" || $ext == "gz" || $ext == "tgz" || $ext == "z" || $ext == "Z") {
                    return "<image src='/icons/compressed.gif' width='12' height=12>";
            } elseif ($ext == "exe" || $ext == "bin") {
                    return "<image src='/icons/binary.gif' width='12' height=12>";
            } elseif ($ext == "hqx") {
                    return "<image src='/icons/binhex.gif' width='12' height=12>";
            } elseif ($ext == "tar") {
                    return "<image src='/icons/tar.gif' width='12' height=12>";
            } elseif ($ext == "txt" || $ext == "bat" || $ext == "sh" || $ext == "ini"|| $ext == "conf") {
                    return "<image src='/icons/script.gif' width='12' height=12>";
            } elseif ($ext == "wrl" || $ext == "wrl" || $ext == "gz" || $ext == "vrml" || $ext == "vrm" || $ext == "iv") {
                    return "<image src='/icons/world2.gif' width='12' height=12>";
            } elseif ($ext == "ps" || $ext == "ai" || $ext == "eps") {
                    return "<image src='/icons/a.gif' width='12' height=12>";
            } elseif ($ext == "pl" || $ext == "py") {
                    return "<image src='/icons/c.gif' width='12' height=12>";
            } elseif ($ext == "for") {
                    return "<image src='/icons/f.gif' width='12' height=12>";
            } elseif ($ext == "dvi") {
                    return "<image src='/icons/dvi.gif' width='12' height=12>";
            } elseif ($ext == "tex") {
                    return "<image src='/icons/tex.gif' width='12' height=12>";
            } elseif ($ext == "core") {
                    return "<image src='/icons/bomb.gif' width='12' height=12>";
            } else {
                    return "<image src='/icons/binary.gif' width='12' height=12>";
            }
    }
    
    
*** Untuk pemakaian fungsi ini pastikan jika url icons pada server kita bisa diakses misal http://localhost/icons/, sebab fungsi ini sangat bergantung dengan url tersebut.


Langkah selanjutnya adalah tinggal menambahkan stylesheet css, untuk mempercantik tampilan tersebut. Tampilan saya seperti dibawah ini, bagaimana dengan pembaca ?
Saya juga telah membuat ide ini menjadi sebuah project open-source yang saya host di google code pada link ini http://code.google.com/p/fancy-apache-directory-listing/. Dalam bundled aplikasi tersebut saya juga menyertakan script batch (for windows) dan shell (for linux), yang bisa langsung di eksekusi untuk meng-copy file index.php ke dalam sub-folder  dari directory list yang ingin kita buka.



Semoga Bermanfaat


Menteng, 24 Maret 2012
Josescalia

No comments: