Tag: Tutorial

  • Bagaimana Mencari Bilangan Prima?

    Salah satu pertanyaan paling penting dalam dunia Matematika adalah menentukan apakah suatu angka merupakan bilangan prima atau tidak. Topik bilangan prima ini juga menjadi salah satu dari tujuh masalah utama dalam bidang Matematika (Millennium Prize Problems), yaitu Riemann hypothesis. Orang pertama yang sanggup memecahkan salah satunya akan mendapat hadiah US$1,000,000 dari Clay Mathematics Institute. Sampai sekarang masih tersisa enam soal yang belum terpecahkan termasuk Riemann hypothesis yang bila dapat dipecahkan dapat menguak pola distribusi bilangan prima.

    Bilangan prima adalah bilangan asli yang lebih besar dari 1 dan hanya memiliki dua faktor (pembagi) yaitu 1 dan bilangan itu sendiri. Contoh bilangan prima adalah 7, yang hanya memiliki dua faktor yaitu 1 dan 7. Sebaliknya, 6 bukan merupakan bilangan prima karena memiliki faktor-faktor 1, 2, 3, dan 6. Bilangan selain bilangan prima disebut bilangan komposit.

    Bilangan prima sangat menarik karena aturan untuk menentukan bilangan prima sudah sangat jelas dan mudah dipahami, namun belum ada rumus atau persamaan yang mudah untuk menentukan apakah sebuah angka merupakan bilangan prima atau bukan.

    Dalam tutorial kali ini akan dibahas bagaimana menentukan sebuah angka adalah prima atau bukan dengan menggunakan bahasa pemrograman Java. Cara yang paling sederhana adalah dengan mencoba membagi sebuah bilangan dengan setiap bilangan dari 2 sampai ke bilangan n – 1. Jika ada satu bilangan saja yang dapat habis membagi berarti bilangan tersebut bukan prima.

    boolean isPrime (int n) {
    
      for (int i=2; i<n; i++)
        if (n % i == 0)
          return false;
    
      return true;
    }
    

    Angka 2 adalah satu-satunya bilangan prima genap, jadi tidak perlu dipusingkan dengan mencobanya. Kode di atas mungkin cukup untuk mencari bilangan kecil, tapi kita butuh algoritma yang lebih cepat/mangkus untuk mencari bilangan besar. Kita tidak perlu mencari dari 2 sampai bilangan n, tapi cukup sampai n/2. Karena jika angka 2 habis membagi n, dapat dipastikan n/2 juga akan habis membagi n.

    boolean isPrime (int n) {
    
      for (int i=2; i*2<n; i++)
        if (n % i == 0)
          return false;
    
      return true;
    }
    

    Masih belum cukup cepat? Algoritma di atas bisa dioptimalkan lagi, yaitu dengan hanya memeriksa bilangan ganjil saja, karena semua bilangan genap pasti habis dibagi 2. Kemudian kita bisa efisienkan percobaan di atas dengan hanya memeriksa pembaginya sampai ke akar kuadrat dari bilangan n (dengan pembulatan ke bawah). Karena jika kita menderetkan semua faktor dari sebuah bilangan, akar kuadratnya pasti selalu berada di tengah-tengah deret tersebut. Misal faktor dari 81 adalah 1, 3, 9, 27, 81. Akar kuadrat dari 81 adalah 9, terletak tepat di tengah-tengah deret tersebut. Tidak perlu diperiksa setengah bagian setelah akar kuadrat karena pasti sudah ketahuan prima atau bukan.

    boolean isPrime (long n) {
    
      if (n % 2 == 0) return false;
        
        for (long i=3; i*i<=n; i+=2)
          if (n % i == 0)
            return false;
        
        return true;
    }
    

    Seperti terlihat pada potongan kode di atas, kita hanya memeriksa sampai ke akar kuadrat dari bilangan n dan hanya memproses bilangan ganjil. Dengan algoritma ini, program kita pasti mengalami peningkatan yang signifikan. Terutama ketika bekerja dengan angka yang sangat besar, itulah kenapa digunakan tipe data long.

    Sebenarnya ada satu lagi metode yang lebih mangkus yang disebut The Sieve of Eratosthenes. Namun kurang cocok dengan kebutuhan karena metode ini digunakan untuk mencari semua bilangan prima dari 2 sampai ke bilangan n.

  • Belajar Java – Array

    Array adalah kumpulan data yang memiliki tipe data dan jumlah elemen yang tetap (tidak bisa ditambah/dikurangi). Array pada Java adalah sebuah object, maka harus dideklarasikan menggunakan kata kunci new. Tiap data pada array disebut element, dan masing-masing element dapat diakses menggunakan index yang berupa angka. Index dimulai dari 0 sampai jumlah element – 1.

    Array Java

    Contoh untuk mendeklarasikan array sesuai gambar di atas adalah

    char [] arrayHuruf = new char[10];
    

    Sedangkan cara untuk menginisialisasinya adalah sebagai berikut

    arrayHuruf[0] = 'A';
    arrayHuruf[1] = 'B';
    //dst
    

    Bisa menggunakan perulangan untuk menginisialisasi array

    for (int i = 0; i < 10; i ++) {
    
      arrayHuruf[i] = (char) ('A' + i);
    }
    

    Array arrayHuruf akan berisi 10 karakter, yaitu ‘A’ sampai ‘J’ secara berurutan. Alternatif lain untuk menginisialisasi array, dapat menggunakan syntax sebagai berikut

    char[] arrayHuruf = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
    

    Jumlah element diketahui dari banyaknya nilai di antara tanda ‘{‘ dan ‘}’.

    Kita juga dapat mendeklarasikan array dari array atau lebih dikenal sebagai array multidimensi dengan cara seperti berikut char[][] namaArray = new char[10][2] atau char[][] namaArray = new char[10][], tapi tidak boleh seperti ini char[][] namaArray = new char[][2]. Dalam bahasa Java, pengertian array lebih sederhana daripada pada bahasa C, jadi jumlah element pada baris berikutnya jumlahnya boleh bervariasi (tidak harus sama dengan baris pertama).

    char[][] hurufAngka = new char[2][];
    hurufAngka[0] = new char[2]; // array index [0][0] sampai [0][1]
    hurufAngka[1] = new char[1]; // hanya ada array index [1][0]
    

    Array multidimensi juga dapat langsung dideklarasikan dan diinisialisasi seperti berikut

    char[][] hurufAngka = {
      { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' },
      { '1', '2', '3', '4', '5'}
    };
    

    Pada contoh untuk menginisialisasi di atas, kita menggunakan bentuk perulangan for (nilai_awal; nilai_akhir; penambahan/pengurangan), jadi jumlah element-nya harus diketahui. Bagaimana jika jumlah element tidak diketahui? Misalkan kita ingin mencetak array yang berisi huruf-huruf yang tidak diketahui secara pasti jumlahnya. Gunakan enhanced for yang penggunaannya mirip dengan foreach pada PHP.

    char[] arrayHuruf = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
    
    for ( char huruf : arrayHuruf ) {
      System.out.println( huruf );
    }
    

    Kita juga bisa menggunakan built-in property length untuk mengetahui jumlah element-nya.

    for (int i=0; i<arrayHuruf.length; i++)
      System.out.println( arrayHuruf[i] );
    

    Untuk menyalin array yang satu ke yang lainnya, bisa menggunakan method arraycopy yang ada pada class System.

    public static void arraycopy(Object arraySumber, int indexSumber, Object arraytujuan, int indexTujuan, int panjangElement)
    

    Contoh penggunaannya adalah seperti berikut

    int[] arraySumber = { 1, 2, 3, 4, 5 };
    int[] arrayTujuan = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    
    System.arraycopy (arraySumber, 0, arrayTujuan, 0, arraySumber.length);
    		
    for (int item : arrayTujuan)
      System.out.println ( item );
    

    Tambahan:
    Meskipun jumlah element pada array tidak bisa ditambah/dikurangi, kita bisa menciptakan array baru dari array yang sudah ada. Namun tentu saja, nilai yang sudah ada akan hilang.

    int [] array = new int[5];
    array = new int[10];
    
  • 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);  
    
  • Autentikasi dan Mengambil Data Pengguna dengan Facebook SDK

    Tutorial ini sudah banyak didokumentasikan di blog-blog baik dalam dan luar negeri, tetapi sangat membingungkan bagi saya. Beberapa tutorial menggunakan JavaScript SDK, sedangkan yang lain menggunakan PHP SDK. Belum lagi, banyak di antaranya yang sudah kadaluarsa dan diperburuk oleh revisi dari Facebook yang tidak menentu.

    Hal lain yang juga membingungkan adalah perbedaan tampilan kotak dialog yang menanyakan izin untuk mengakses data-data. Bandingkan tampilan dialog yang saya ambil dari Facebook Developers Guide berikut dengan yang dihasilkan dari tutorial ini.

    login with facebook

    Sebenarnya hanya ada 2 hal dasar yang menjadi alasan untuk menggunakan Facebook SDK.
    1. Kita mempunyai sistem “register” dan “login” sendiri, dan ingin menambahkan “Login with Facebook” sebagai pilihan bagi pengguna yang malas untuk mendaftar secara normal.
    2. Kita membutuhkan data-data pengguna yang sudah dicatat dengan baik oleh Facebook, tentunya dengan persetujuan pemilik akun.

    Dokumentasi dan kode sumber yang ada di Facebook Developers Guide sudah lengkap, namun susah diikuti dan tidak semuanya saya butuhkan. Tutorial ini akan menggabungkan Javascript SDK dan PHP SDK, karena cara ini menurut saya paling sederhana untuk memenuhi 2 kebutuhan dasar di atas.

    Langkah-langkah untuk menghubungkan website dengan Facebook SDK adalah:
    1. Daftarkan website pada halaman Facebook Developers, di situ akan diperoleh “App ID” dan “App Secret”.
    2. Buat sebuah table pada database untuk menyimpan data-data pengguna dari Facebook. Field-nya sesuai kebutuhan saja, contoh: nama, password, email, tipe (password yang dimaksud di sini bukan password facebook dan tipe akan berisi “facebook” jika data diambil dari facebook dan “normal” jika tidak).
    3. Download Facebook SDK. Ambil semua isi folder “src” (kita hanya membutuhkan ini).
    4. Tombol login bisa menggunakan tag HTML biasa

    <div class="fb-login-button">

    atau menggunakan JavaScript SDK.

    <fb:login-button>

    Dengan ini kita bisa mengakses data-data pengguna yang diatur secara publik (tidak disembunyikan), misalnya id, nama, jenis kelamin. Data-data yang tidak bisa diakses publik harus ditulis ke dalam atribut scope.

    <fb:login-button scope="email, read_stream"></fb:login-button>

    5. Deklarasikan Facebook object di paling atas halaman. Jangan lupa isi “App ID” dan “App secret”. Kemudian ambil data-data pengguna (sudah termasuk yang ditulis di atribut scope tadi) dengan Facebook API.

    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = '';
    $config['secret'] = '';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    

    6. Terakhir, data-data yang sudah diperoleh dari Facebook API bisa diolah sesuai keinginan. Untuk lebih memahami, baca komentar yang ada pada kode sumber.

    <?php if($user) { ?>
    
    //tampilkan foto dan nama user		      
    <img src="https://graph.facebook.com/<?php echo $user; ?>/picture">
    <?=$user_profile['name']?>
    		    
    <?php
    //ambil data-data yang ingin disimpan
    $fb_id = $user_profile['id'];
    $username = $user_profile['username'];
    $email = $user_profile['email'];
    
    //periksa apakah user sudah pernah login
    $insert = true;
    if (/*query untuk memeriksa apakah data sudah ada di database*/)
        $insert = false;
    
    //jika pertama kali login, masukan data user ke database
    if($insert) {
        /*query INSERT untuk memasukan data ke database*/
    }
    
    //login user
    /* kode untuk login user dan SESSION */
    ?>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    

    Gabungkan langkah ke-5 dan ke-6 serta tambahkan JavaScript SDK. Akhirnya kita akan memperoleh data dalam bentuk array setelah login dengan Facebook.

    <?php 
    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = 'isi_dengan_app_id';
    $config['secret'] = 'isi_dengan_app_secret';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    
    if ($user) { ?>
    
    <pre>
    <?php print_r($user_profile) ?>
    </pre>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    <div id="fb-root"></div>
    
    <script>
    window.fbAsyncInit = function() {
      FB.init({
        appId: '<?php echo $facebook->getAppID() ?>',
        cookie: true,
        xfbml: true,
        oauth: true
      });
      FB.Event.subscribe('auth.login', function(response) {
        window.location.reload();
      });
      FB.Event.subscribe('auth.logout', function(response) {
        window.location.reload();
      });
    };
    (function() {
      var e = document.createElement('script'); e.async = true;
      e.src = document.location.protocol +
        '//connect.facebook.net/en_US/all.js';
      document.getElementById('fb-root').appendChild(e);
    }());
    </script>
    
  • Validasi File Upload di PHP

    Validasi file upload sangat penting dilakukan karena adanya fitur mengunggah file ke web server adalah kegiatan yang cukup berbahaya. Ambil contoh pada sebuah web yang mengijinkan user untuk meng-upload foto/gambar bisa jadi dijadikan celah bagi para hacker untuk meletakan script berbahaya pada server.

    Berbekal beberapa baris kode PHP kita sudah bisa membuat file upload sederhana. Namun hanya mengandalkan script sederhana tersebut tidak cukup untuk membuat file upload yang bisa diandalkan.

    Untuk meminimalkan celah pada fitur file upload, dapat dilakukan dengan cara memverifikasi jenis file yang diupload. Kita tidak boleh mengandalkan informasi dari ekstensi file atau dari nilai $_FILES['berkas']['type'] atau dari mime type karena ketiga informasi tersebut bisa dipalsukan. Lebih baik menggunakan fungsi PHP exif_imagetype() untuk memeriksa signature dari file yang diupload atau fungsi PHP getimagesize() untuk memperoleh ukuran gambar.

    $fileType = exif_imagetype($_FILES['myFile']['tmp_name']);
    $allowed = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
    if (!in_array($fileType, $allowed)) {
      echo "hanya diijinkan untuk meng-upload file gambar (gif, jpg, atau png)";
    }
    

    Namun tidak menutup kemungkinan, fungsi PHP di atas juga belum cukup untuk menghentikan hacker yang kelewat kreatif. Jadi perlu ditambahkan juga pemeriksaan ekstensi file, dan ubah paksa file .php menjadi file .jpg sehingga kode php yang mungkin lolos dari pemeriksaan pertama tidak bisa dieksekusi di server.

    <form action="" method="post" enctype="multipart/form-data">
     <input type="file" name="myFile"/>
     <input type="submit" value="Upload"/>
    </form>
    
    <?php
    define("UPLOAD_DIR", "images/");
    
    if (!empty($_FILES['myFile']['name'])) {
    	
      // verifikasi file gambar (GIF, JPEG, atau PNG)
      $fileType = exif_imagetype($_FILES['myFile']['tmp_name']);
      $allowed = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
      if (!in_array($fileType, $allowed)) {
        echo "hanya diijinkan untuk meng-upload file gambar (gif, jpg, atau png)";
      }
    	
      else{
        $myFile = $_FILES['myFile'];
    
    
        // ubah paksa nama file yg mengandung selain huruf, angka, ".", "_", dan "-" dengan regex
        $name = preg_replace("/[^A-Z0-9._-]/i", "_", $myFile['name']);
    
        // periksa ekstensi file
        $parts = pathinfo($name);		
        if (isset($parts['extension'])) {
          $ext = $parts['extension'];
    			
          if ($ext !== 'jpg' && $ext !== 'gif' && $ext !== 'png')
            $ext = "jpg";
    			
    	$name = $parts['filename'] . '.' . $ext;
          }
    		
          else { // jika file tidak memiliki ekstensi maka berikan ekstensi .jpg
            $ext = 'jpg';
    	$name = $parts['filename'] . '.jpg';
          }
    
          // simpan file
          move_uploaded_file($myFile['tmp_name'], UPLOAD_DIR . $name);
      }
    }
    

    Sebagai tambahan, mungkin juga perlu untuk membatasi ukuran file yang diupload untuk melindungi website dari serangan yang mencoba mengganggu network traffic atau system load.