Tag: Snippet

Catatan Sibudi

  • Bug Y2K38 pada Fungsi date() PHP

    Agar tidak bertele-tele, coba saja kode PHP berikut ini.

    <?php
    echo date('l d F Y H:i:s', strtotime('2038-02-19 3:14:07'));
    

    Seperti yang kita tau, fungsi date() pada kode PHP di atas akan mengembalikan sebuah string waktu sesuai format ‘l d F Y H:i:s’. Harusnya pada browser akan tercetak:

    Friday 19 February 2038 03:14:07

    Namun jika waktu yang tercetak tidak seperti di atas, berarti aplikasi PHP Anda mempunyai kemungkinan terkena bug Y2K38.

    Apa yang dimaksud bug Y2K38? Y2K38 yang disebut juga sebagai Unix Millenium Bug, dapat mempengaruhi sistem yang menggunakan 32-bit signed integer untuk merepresentasikan waktu (hari, tanggal, bulan, tahun, jam, menit, dsb). Sebagai patokan awalnya adalah Kamis, 1 Januari 1970 00:00:00 UTC dan akan berakhir pada Selasa, 19 Januari 2038 03:14:07 UTC. Jika waktu sudah melewati 19 Januari 2038 03:14:07 UTC, akan terjadi integer overflow. Semua bit sudah terpakai, kecuali bit pertama yang tidak boleh digunakan karena sebagai signed bit (0 = positif, 1 = negatif).

    Kondisi signed bit yang diinkremen (ditambah dengan 1) selama proses perhitungan maju ini mengakibatkan nilainya mendadak berubah menjadi negatif, dalam kasus integer overflow ini nilainya menjadi negatif yang maksimum (angka paling kecil). Kemudian proses perhitungan maju berlanjut sampai negatif 0. Hal ini akan mengacaukan perhitungan waktu pada sistem. Gambar yang diambil dari Wikimedia ini menjelaskan dengan sempurna proses tersebut.

    Bug Y2K38

    Tahun 2038 masih lebih dari 20 tahun lagi, seharusnya masalah ini tidak perlu dikuatirkan. Pada tahun itu mungkin aplikasi yang Anda buat sekarang sudah usang dan tidak digunakan. Akan tetapi sebagai seorang programer yang baik sudah seharusnya memikirkan segala kemungkinan. Mungkin saja ada orang yang memakai kode yang Anda buat untuk aplikasi lain yang membutuhkan perhitungan waktu sampai 30 tahun ke depan.

    Menggunakan sistem 64-bit mungkin dapat menyelamatkan Anda, karena bagaimanapun juga 64-bit signed integer jauh lebih lebar jangkauannya dibanding 32-bit signed integer. Tapi saya belum pernah mencoba sejauh itu. Alternatif lain yang lebih mudah yaitu dengan menggunakan class PHP DateTime yang diperkenalkan mulai PHP versi 5.2.

    <?php
    $mydate = new DateTime('2038-02-19 3:14:07');
    echo $mydate -> format('l d F Y H:i:s');
    

    Dengan menggunakan DateTime aplikasi PHP tidak terkena bug Y2K38, karena mampu menangani waktu sampai pada 31 Desember 9999! Mungkin Anda berniat mewariskan kode ini untuk generasi berikutnya 😀

  • Memanipulasi URL pada Status Bar Browser

    Mungkin teknik ini hanya digunakan oleh para penjahat dunia maya. Orang yang merasa perlu untuk menyembunyikan apa yang seharusnya bebas diketahui publik. Penting bagi kita untuk mengetahui teknik yang digunakan oleh para penjahat untuk melindungi diri bukan untuk sebaliknya. Biasanya ini digunakan untuk menyembunyikan/memanipulasi link referal atau sebagai langkah awal kejahatan phishing.

    Ketika kita menyorotkan mouse pada sebuah tautan (link), misalnya ini, maka akan muncul URL dari tautan tersebut pada status bar. Biasanya terletak pada pojok kiri bawah sebuah browser.

    Sebuah tautan yang benar adalah menggunakan tag HTML <a> dengan atribut href dan title. Atribut href wajib ada karena dibutuhkan sebagai tujuan sebuah tautan dan memunculkan URL pada status bar, sedangkan title opsional.

    <a href="http://sibudi.net" title="Websiteku">klik di sini</a>
    

    Berikut ini adalah 3 teknik yang digunakan untuk menyembunyikan atau memanipulasi tautan.

    Cara pertama

    <a style="cursor:pointer" onClick="location.href='http://sibudi.net'" >klik di sini</a>
    

    Pada kode di atas, atribut href sengaja tidak ditulis. Dalam keadaan normal hal tersebut tidak berbahaya, hanya akan menampilkan tulisan “klik di sini” pada browser dan tidak bisa diklik. Namun dengan tambahan sedikit kode JavaScript di atas, tautan di atas akan mengarah pada “http://sibudi.net” tanpa dapat dilihat tujuannya oleh pengguna awam.

    Untuk lebih meyakinkan dapat ditambahkan inline css cursor:pointer yang akan mengubah pointer menjadi gambar tangan. Bisa juga ditambahkan text-decoration:underline dan color sesuai dengan warna yang digunakan pada browser.

    Cara kedua (hanya bekerja pada browser IE):

    <a href="http://sibudi.net" onMouseOver="window.status='http://www.google.com'; return true" onMouseOut="window.status=''">klik di sini</a>
    

    Tautan di atas tidak lagi hanya menyembunyikan URL tapi memanipulasi URL. Jadi pada status bar tertulis “http://google.com” padahal jika diklik akan menuju ke “http://sibudi.net”. Namun teknik itu tidak akan bekerja pada browser selain IE.

    Cara ketiga

    <script>
    function redirect(URL) {
    
      document.location = URL;
      return false;
    }
    </script>
    
    <a href="http://google.com" onClick="return redirect('http://sibudi.net');">klik di sini</a>
    

    Teknik ketiga adalah gabungan dari 2 teknik sebelumnya, yaitu menggunakan atribut href dan onClick. Seperti yang kita tau, atribut href akan memunculkan URL pada status bar. Ketika tautan di atas diklik, maka akan membangkitkan event onClick dan memanggil fungsi JavaScript redirect.

    Perlu dicatat bahwa ketiga teknik di atas sangat bergantung pada JavaScript. Jadi tidak akan bekerja pada browser yang di-disable Javascript-nya. Tautan akan tetap mengarah sesuai pada atribut href dan hanya berupa teks biasa jika atribut href tidak ada. Untuk menangani masalah JavaScript ini, bisa mengacu pada tulisan menangani browser dengan JavaScript disable.

  • Validasi dan Sanitasi Form dengan PHP

    Salah satu fitur PHP yang paling penting adalah kemampuannya untuk mengolah form HTML. Form adalah halaman yang hampir dapat dijumpai pada setiap website, contohnya adalah form untuk login, form pendaftaran, form kontak, dll. Mengolah form HTML dengan PHP sangat mudah, dan karena kemudahannya inilah banyak programer yang membuat form secara sembarangan.

    Validasi dan sanitasi data adalah 2 hal yang tidak bisa dilepaskan ketika bekerja dengan form. Data yang tidak valid dan tidak bersih, tidak hanya akan menghasilkan informasi yang salah tetapi juga akan menimbulkan masalah keamanan. Artikel ini akan membahas proses pembuatan form dari yang sederhana sampai yang cukup kompleks dengan validasi dan sanitasi data. Hasil akhir diharapkan mampu meminimalkan kesalahan dan masalah kemananan pada form.

    Contoh 1. Pengolahan form paling sederhana dengan PHP
    nama file: test.html

    <form name="form_test" method="post" action="test.php">
      <p><label for="email">Email </label><input name="email" type="text"/></p>
      <p><label for="website">Website </label><input name="website" type="text" /></p>
      <p><input type="submit" name="submit" value="kirim"></p>
    </form>
    

    nama file: test.php

    <?php
    echo 'Email: ' . $_POST['email'] . '<br />';
    echo 'Website: ' . $_POST['website'];
    

    Pada contoh di atas, tidak ada kode yang memvalidasi dan menyanitasi masukan dari pengguna. Akibatnya apapun data yang dimasukan oleh pengguna akan langsung diproses oleh PHP. Hal ini tidak boleh terjadi. Salah satu masalah yang mungkin terjadi adalah ketika pengguna tidak memasukan data sesuai format dengan benar (baik email maupun website). Sebenarnya HTML5 dapat sedikit membantu tugas para programer, yaitu dengan mengganti nilai type menjadi “email” dan “url“.

    Contoh 2. HTML5 form
    nama file: test.html

    <form name="form_test" method="post" action="test.php">
      <p><label for="email">Email </label><input name="email" type="email"/></p>
      <p><label for="website">Website </label><input name="website" type="url" /></p>
      <p><input type="submit" name="submit" value="kirim"></p>
    </form>
    

    Dengan kode di atas, sekarang akan muncul tooltips ketika pengguna salah memasukan email atau website. Sebagai catatan, belum semua browser mendukung fitur ini, jadi validasi dan sanitasi pada server side (kode PHP) mutlak diperlukan.

    Memeriksa validitas dan membersihkan data dari karakter-karakter yang tidak diinginkan adalah pekerjaan yang tidak mudah. Untungnya, mulai versi 5.2, PHP mempunyai function yang disebut filter_var yang akan membuat pekerjaan programer menjadi jauh lebih mudah. Function filter_var dapat melakukan kedua hal tersebut, baik validasi maupun sanitasi data. Sebenarnya apakah perbedaan di antara keduanya?

    1. Validasi: menentukan apakah sebuah data memiliki format yang valid.
    2. Sanitasi: menghilangkan karakter-karakter yang tidak diinginkan pada sebuah data.

    Mengapa harus keduanya? Karena ada kemungkinan pengguna, baik sengaja maupun tidak sengaja memasukan karakter yang bisa berakibat buruk pada aplikasi. Berikut ini adalah contoh penggunaan filter_var.

    <?php
    $string = "<h1>Hello, World!</h1>";
    $string = filter_var($string, FILTER_SANITIZE_STRING);
    echo 'variabel $string bernilai "' . $string . '"';
    

    Tampak pada contoh kode di atas, filter_var akan menghilangkan semua tag HTML pada suatu string. Sekarang ubah file “test.php” di atas untuk memvalidasi dan menyanitasi masukan email dan website.

    Contoh 3. PHP filter_var
    nama file: test.php

    <?php
    if (!empty($_POST['email'])) {  
      $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);  
      if (filter_var($email, FILTER_VALIDATE_EMAIL)) {  
        echo "Email $email valid.<br/>";  
      } else {  
        echo "Email $email tidak valid.<br/>";  
      }  
    } else {
      echo "Email harus diisi.<br/>";
    }
    
    if (!empty($_POST['website'])) {  
      $website = filter_var($_POST['website'], FILTER_SANITIZE_URL);  
      if (filter_var($website, FILTER_VALIDATE_URL)) {  
        echo "Website $website valid.";  
      } else {  
        echo "Website $website tidak valid.";  
      }  
    } else {
      echo "Website harus diisi";
    }
    

    Sebagai catatan, alamat website yang valid itu harus mengandung “http://“. Kode !empty($_POST['email']) adalah untuk memeriksa apakah pengguna memasukan data atau tidak.

    Selain dengan filter_var, masih ada cara lain yang bisa digunakan, terutama jika server belum mendukung function ini, yaitu dengan htmlspecialchars. Function htmlspecialchars akan mengkonversi 5 karakter khusus menjadi representasinya dalam bentuk kode. Kelima karakter tersebut beserta representasinya adalah sebagai berikut.

    • &‘ (ampersand) dikonversi menjadi ‘&amp;‘.
    • "‘ (double quote) dikonversi menjadi ‘&quot;‘.
    • '‘ (single quote) dikonversi menjadi ‘&#039;‘.
    • <' (less than) dikonversi menjadi '&lt;'
    • '>' (greater than) dikonversi menjadi '&gt;'

    Contoh penggunaannya adalah sebagai berikut.

    <?php
    $string = htmlspecialchars("<a href='test'>Test string</a>", ENT_QUOTES);
    echo $string; // &lt;a href=&#039;test&#039;&gt;Test string&lt;/a&gt;
    

    Jalankan kode di atas, lalu view source hasilnya. Hasil view source akan sama seperti yang ada pada baris komentar di atas. Pada function htmlspecialchars di atas, terdapat argumen ENT_QUOTES yang berarti akan mengkonversi ''' (single quote) dan '"' (double quote). Jika argumennya ENT_NOQUOTES, kedua quote tidak akan dikonversi.

    sql injection

    Akhirnya, jika bekerja dengan database, dibutuhkan suatu function yang akan melindungi database dari serangan SQL Injection. Function mysql_real_escape_string akan membersihkan semua data yang akan dimasukan ke dalam database.

    <?php
    $email = mysql_real_escape_string($email);
    $website = mysql_real_escape_string($website);
    $query = 'UPDATE nama_tabel SET website = ' . $website . ' WHERE email = ' . $email;  
    mysql_query($query);  
    
  • Menyingkat Kode PHP menggunakan Operator Ternary (?:)

    Salah satu konsep dasar pemrograman yang penting adalah pernyataan bersyarat, atau lebih dikenal dengan istilah percabangan. Percabangan adalah suatu kondisi yang dipakai oleh bahasa pemrograman untuk mengatur alur logika program. Dalam bahasa pemrograman PHP setidaknya dikenal 2 macam percabangan, yaitu if/else dan switch/case.

    Percabangan dengan if/else dapat disederhanakan menggunakan operator ternary. Contoh operator ternary bisa dijumpai pada artikel ini, ini, dan ini. Operator ternary memiliki bentuk dasar sebagai berikut:

    (pernyataan1) ? (pernyataan2) : (pernyataan3)

    Bentuk di atas memiliki arti: jika “pernyataan1” adalah benar, nilai kembalian adalah “pernyataan2”, dan jika sebaliknya, nilai kembalian adalah “pernyataan3”. Untuk lebih jelasnya, perhatikan contoh berikut.

    <?php
    $var = 7;
    $cek_var = $var > 5 ? true : false;
    

    Pada contoh di atas nilai variable $cek_var adalah true, karena pernyataan nilai $var lebih besar dari 5 adalah benar. Berikut ini adalah padanannya dalam bentuk if/else.

    <?php
    $var = 7;
    if ($var > 5)
      $cek_var = true;
    
    else
      $cek_var = false;
    

    Contoh aplikasi di dunia nyata adalah seperti yang biasa digunakan untuk memberikan nilai default pada sebuah variable.

    <?php
    $action = !isset($_POST['action']) ? 'default' : $_POST['action'];
    

    Kode di atas identik dengan:

    <?php
    if (!isset($_POST['action'])) {
        $action = 'default';
    } else {
        $action = $_POST['action'];
    }
    

    Bonus:
    Operasi menghitung jumlah hari (termasuk memeriksa tahun kabisat) dalam satu bulan menggunakan operator ternary bertingkat.

    <?php
    $bulan = 2; // bulan Februari
    $tahun = 2012; // ini tahun kabisat
    
    $jumlah_hari = ($bulan == 2 ? ($tahun % 4 ? 28 : ($tahun % 100 ? 29 : ($tahun %400 ? 28 : 29))) : (($bulan - 1) % 7 % 2 ? 30 : 31));
    echo $jumlah_hari;
    
  • Membuat Tombol “Back”

    Pada umumnya browser sudah memiliki tombol “back” yang berfungsi untuk kembali ke halaman sebelumnya. Seorang web developer harus mempunyai alasan yang bagus untuk memasangnya pada website, misal karena adanya permintaan khusus dari klien. Namun, artikel ini ditulis bukan demi klien, melainkan demi ilmu pengetahuan 🙂

    Ada 2 cara yang bisa dipakai, yaitu dengan JavaScript dan PHP. Untuk mencoba kode-kode di bawah ini, dibutuhkan sebuah halaman lain yang berisi link menuju ke halaman yang berisi tombol “back” ini.

    <input type="button" value="Go Back" onclick="history.back(-1)" />
    

    Tentunya implementasi menggunakan JavaScript masih kurang, karena ada kemungkinan user mematikan JavaScript di browser-nya. Berikut ini adalah implementasi dengan PHP.

    <?php
      $url = htmlspecialchars($_SERVER['HTTP_REFERER']);
    ?>
      <a href="<?=$url?>">Go Back</a>
    

    Pada snippet di atas digunakan fungsi PHP htmlspecialchars untuk mensanitasi input dari client. Meskipun secara fisik tidak ada input yang bisa disusupi oleh user, namun harus tetap berpegang pada prinsip dasar pengembangan website, yaitu jangan pernah percaya apa yang dikirimkan oleh client.

    Jika kode PHP di atas langsung dieksekusi tanpa melalui halaman lain, maka akan muncul pesan peringatan:

    Notice: Undefined index: HTTP_REFERER in /var/www/index.php on line 2

    Itu adalah pesan peringatan karena ada yang salah pada kode PHP. Untuk memperbaiki kesalahan itu bisa dipelajari di sini.

    <?php
      $url = isset($_SERVER['HTTP_REFERER']) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : '';
    ?>
      <a href="<?=$url?>">Go Back PHP</a>
    

    Dalam artikel singkat ini selain dipelajari cara membuat tombol “back” namun juga pentingnya menulis kode yang baik dan berkualitas. Kode yang baik dan berkualitas akan membuat website yang dibuat menjadi lebih aman. Mulailah menulis kode yang berkualitas dari kasus yang paling sederhana.