Welcome to Abdul Malik Ikhsan's Blog

CORS ( Cross-Origin Resource Sharing ) : connecting multiple site with multiple request method

Posted in Javascript, Teknologi by samsonasik on April 23, 2011

CORS adalah draft teknologi yang dikembangkan oleh W3C sebagai alternatif yang lebih modern ketimbang JSONP. Ketika JSONP hanya men-support  GET request method, CORS juga mensupport POST request method. Teknologi ini dikembangkan karena semakin kompleksnya kebutuhan mashup data di dunia internet. Ide dasar dari CORS ini adalah meng-custom HTTP Header agar client dan server dapat mengetahui satu sama lain apabila request dan response berhasil atau gagal dilakukan.
Kali ini, saya akan mencoba memaparkan tentang contoh implementasi CORS menggunakan jQuery javascript library, dan plugin CORS. Plugin asli dapat didownload di sini , yang akan saya sampaikan di sini sudah saya modifikasi dari aslinya untuk kebutuhan jQuery versi 1.5.
Pertama, kita siapkan dulu jQuery library kita, bisa didownload di sini. Setelah itu, kita buat plugin untuk handle CORS sebagai berikut :

(function($) {
    //activate cors support <-- for jQuery 1.5
    jQuery.support.cors = true;

    $.corsGET = function(url,callback){
        try{
           jQuery.get(url, callback);
        }catch(e){
            // jQuery get() failed, try IE8 CORS, or use the proxy
            if (jQuery.browser.msie && window.XDomainRequest) {
                // Use Microsoft XDR
                var xdr = new XDomainRequest();
                xdr.open("get", url);
                xdr.onload = function() {
                    callback(this.responseText, 'success');
                };
                xdr.send();
            } else{
                try {
                    // Ancient browser, use our proxy
                    var ancientcallback = function() {
                    var textstatus = 'error';
                    var data = 'error';

                    if ((this.readyState == 4)
                        && (this.status == '200')) {
                            textstatus = 'success';
                            data = this.responseText;
                        }
                        callback(data, textstatus);
                    };

                    // proxy_xmlhttp is a separate script you'll have to set up
                    request = new proxy_xmlhttp();
                    request.open('GET', url, true);
                    request.onreadystatechange = ancientcallback;
                    request.send();
                } catch(e) {
                    // Could not fetch using the proxy
                    alert('failed !!! ');
                }
            }
        }
    };

    $.corsPOST = function(url,data,callback){
        try{
            jQuery.post(url, data, callback);
        }catch(e){
             // jQuery post() failed, try IE8 CORS, or use the proxy
            if (jQuery.browser.msie && window.XDomainRequest) {
                // Use XDR
                var xdr = new XDomainRequest();
                xdr.open("post", url);
                xdr.send(params);
                xdr.onload = function() {
                    callback(xdr.responseText, 'success');
                };
            } else{
                try {
                    // Use the proxy to post the data.
                    request = new proxy_xmlhttp();
                    request.open("POST", url, true);
                    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    request.send(params);
                } catch(e2) {
                   // could not post using the proxy
                   alert('failed !!! ');
                }
            }
        }
    };

})(jQuery);

Kita bisa simpan plugin ini dan kita beri nama : jquery.cors.js . Ok, setelah itu kita buat contoh file sebagai requester cross domain kita, contoh sebagai berikut :

<!DOCTYPE html>
<html>
<head>
  <title>
      Test CORS ( Cross-Origin Resource Sharing )
  </title>
  <script type="text/javascript" src="jquery-1.5.2.min.js"></script>
  <script type="text/javascript" src="jquery.cors.js"></script>
  <script type="text/javascript">
     $(document).ready(function(){
         $("#sendDataBtn").click(function(){
            //clear label ...
            $("#resultcors").html();

            if ($("#typeofparameter").val()=='get'){
              $.corsGET('http://service.yourdomain.com?nama='+$("input[name=nama]").val()+'&'+(new Date()).getTime() ,
                function(data){
                  $("#resultcors").html('The response is : '+data);
              });
            }else{
              $.corsPOST('http://service.yourdomain.com?'+(new Date()).getTime() , {  nama: $("input[name=nama]").val() },
                function(data){
                  $("#resultcors").html('The response is : '+data);
              });
            }
         });
     });
  </script>
</head>
<body>
    <input type="text" name="nama" size="50" /> <br />
    type : <select name="typeofparameter" id="typeofparameter">
               <option value="get">GET</option>
               <option value="post">POST</option>
           </select>

    <input type="button" id="sendDataBtn" value="Send Data" />

    <br />
    <label id="resultcors"></label>

</body>
</html>

Kalau sudah, kita buat deh file responder-nya ( kita buat di server lain atau atas nama domain lain).

<?php
// Specify domains from which requests are allowed
header('Access-Control-Allow-Origin: *');
// Specify which request methods are allowed
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
// Additional headers which may be sent along with the CORS request
// The X-Requested-With header allows jQuery requests to go through
header('Access-Control-Allow-Headers: X-Requested-With');
// Set the age to 1 day ( 86400 ) to improve speed/caching.
header('Access-Control-Max-Age: 86400');

// Exit early so the page isn't fully loaded for options requests
if (strtolower($_SERVER['REQUEST_METHOD']) == 'options') {
    exit();
}

// If raw post data, this could be from IE8 XDomainRequest
// Only use this if you want to populate $_POST in all instances
if (isset($HTTP_RAW_POST_DATA)) {
    $data = explode('&', $HTTP_RAW_POST_DATA);
    foreach ($data as $val) {
       if (!empty($val)) {
         list($key, $value) = explode('=', $val);
         $_POST[$key] = urldecode($value);
       }
    }
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    echo  '<strong>posted</strong> : '.strtoupper(  $_REQUEST['nama'] );
}

if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    echo '<strong>getted </strong> : '.strtoupper(  $_GET['nama'] );
}

Taraaaa….Sehingga jika ditest, akan tampil sebagai berikut :

Gambar :
http://t2.gstatic.com/images?q=tbn:ANd9GcSbW9iPimNholkyrzJ2tvD-uqRQ8_5KkBC4hVLys9XEVh4KTN81

Referensi :
http://plugins.jquery.com/project/cors
http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing
http://en.wikipedia.org/wiki/JSONP
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
http://enable-cors.org/
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
https://developer.mozilla.org/en/http_access_control
http://blueonionsoftware.com/blog.aspx?p=03aff202-4198-4606-b9d6-686fd13697ee
http://msdn.microsoft.com/en-us/library/cc288060%28v=vs.85%29.aspx

Zend Framework : Output Escaping – preventing XSS

Posted in Javascript, Teknologi, Tutorial PHP, Zend Framework by samsonasik on April 19, 2011

Cross-site scripting (XSS) merupakan salah satu jenis serangan injeksi kode yang secara umum ditemukan di aplikasi berbasis web melalui client-side script.  Salah satu cara menanganinya adalah dengan cara meng-escape output yang tampil pada halaman web. Pada Symfony Framework, output escaping otomatis dilakukan oleh framework itu sendiri, untuk Zend Framework , preventing XSS adalah tugas programmer :). XSS terjadi di bagian View, maka dari itu, Zend Framework menyediakan component Zend_View ( “view” portion of the ZF model-view-controller pattern) yang bisa digunakan untuk meng-escape output dari misalnya :

<script type="text/javascript">alert('hello');</script>

menjadi :

&lt;script type="text/javascript"&gt;alert('hello');&lt;/script&gt;

Sehingga kode javascript tidak tereksekusi. Nah, ada 2 cara penggunaan metode ini :
1. Encoding before echoing
Di layer View, tinggal kita panggil :

<?php echo $this->escape("<script type=\"text/javascript\">alert('hello');</script>"); ?>

2. Encoding when assigning template variables
Cara yang kedua ini, kita escape dulu di controller, contoh sebagai berikut :

$this->view->title = $this->view->escape("<script type=\"text/javascript\">alert('hello');</script>");

Baru di layer view :

 echo $this->title; 

Referensi :
http://www.scribd.com/doc/18171526/Secure-Programming-with-the-Zend-Framework
http://www.minte9.com/kb/zend-view-helper-programming-zend-framework-i329
http://devzone.zend.com/article/3412
http://en.wikipedia.org/wiki/Client-side_script
http://en.wikipedia.org/wiki/Cross-site_scripting
http://id.wikipedia.org/wiki/XSS
http://stackoverflow.com/questions/507593/what-is-the-best-way-to-escape-user-output-with-the-zend-framework

Zend Framework : Zend_Log – Working with Logs

Posted in Tutorial PHP, Zend Framework by samsonasik on April 17, 2011

Sebegitu pentingnya sebuah sejarah, sampai-sampai beberapa framework menambahkan fitur log, termasuk Zend Framework. Dengan adanya application log, kita bisa mengetahui apa saja yang telah terjadi yang bersinggungan dengan aplikasi kita. Log yang ada, salah satunya, bisa kita simpan di dalam file.
Kali ini, saya akan mencoba memaparkan penggunaan Zend_Log dengan media penyimpanan file dengan teknik Stream.
Pertama, yang kita butuhkan adalah file yang kita tunjuk sebagai media penyimpanan log, anggaplah kita simpan dalam PROJECTKITA\log\application.log, seperti berikut :


Kalau sudah, kita atur deh ErrorController kita sebagai berikut :

<?php
class ErrorController extends Zend_Controller_Action
{
public function errorAction()
{
$errors = $this->_getParam('error_handler');
switch ($errors->type) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
// 404 error -- controller or action not found
$this->getResponse()->setHttpResponseCode(404);
$this->view->message = 'Page not found';
break;
default:
// application error
$this->getResponse()->setHttpResponseCode(500);
$this->view->message = 'Application error';
break;
}

// Log exception, if logger available
if ($log = $this->getLog()) {
$log->crit($this->view->message . " : ". $errors->exception);
}

// conditionally display exceptions
if ($this->getInvokeArg('displayExceptions') == true) {
$this->view->exception = $errors->exception;
}

$this->view->request   = $errors->request;
}

public function getLog()
{
$bootstrap = $this->getInvokeArg('bootstrap');
if (!$bootstrap->hasPluginResource('Log')) {
return false;
}
$log = $bootstrap->getResource('Log');
return $log;
}

}

Selanjutnya, kita setting di application.ini kita, tambahkan kode berikut :

;call Zend_Log_Writer_Stream
resources.log.stream.writerName = "Stream"
resources.log.stream.writerParams.stream = APPLICATION_PATH "/../log/application.log"

Dari kode yang telah kita buat di atas, semua critical error akan dicatat dalam file application.log seperti berikut :

2011-04-16T20:54:33+07:00 CRIT (2): Page not found : exception 'Zend_Controller_Action_Exception' with message 'Action "aa" does not exist and was not trapped in __call()' in D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Action.php:485
Stack trace:
#0 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Action.php(515): Zend_Controller_Action->__call('aaAction', Array)
#1 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Dispatcher\Standard.php(295): Zend_Controller_Action->dispatch('aaAction')
#2 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#3 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Application\Bootstrap\Bootstrap.php(97): Zend_Controller_Front->dispatch()
#4 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
#5 D:\Zend\Apache2\htdocs\zftutwordpress\public\index.php(27): Zend_Application->run()
#6 {main}

Nah, bagaimana ketika kita mempunyai hal aktivitas lain yang ingin kita simpan juga dalam history ? Yang kita perlukan adalah meng-inisialisasi resource dalam file Bootstrap.php kita dengan menambahkan function _init* sebagai berikut :

protected function _initLog()
{
if ($this->hasPluginResource('log')){
$r = $this->getPluginResource('log');
$log = $r->getLog();
Zend_Registry::set('log', $log);
}
}


Kalau sudah, kita coba test dengan memanggil di sembarang action ( misal di TestlogController dengan action indexAction ) sebagai berikut  :

Zend_Registry::get('log')->info('something happened');

maka, di file log akan tampil semacam berikut :

2011-04-17T00:03:15+07:00 INFO (6): something happened

Hm…, asyik kan ? semoga bermanfaat 😀

Referensi :
http://www.zendcasts.com/transparent-logging-with-zend_log/2010/06/
http://framework.zend.com/manual/en/zend.log.writers.html
http://id.php.net/stream
http://en.wikipedia.org/wiki/Server_log
http://framework.zend.com/manual/en/learning.quickstart.create-model.html
http://en.wikipedia.org/wiki/Stream_%28computing%29

Zend Framework : View Partials – Dealing with Complex Templates

Posted in Tutorial PHP, Zend Framework by samsonasik on April 6, 2011

Bagi kamu-kamu yang ber-background Ruby on Rails, tentu sudah tidak asing lagi donkz dengan View Partials. Perbedaan rendering secara partial dengan normal view adalah bahwa partial mempunyai ruang lingkup variable sendiri, ia hanya akan melihat variable yang dilewatkan secara langsung. Sebagai contoh seperti berikut :

<?php echo $this->partial('foo.phtml', array('foo' => 'bar'));  ?> 

Dari contoh di atas, variable yang bisa dipakai di foo.phtml hanyalah single variable ‘foo’ dengan value ‘bar’. View Partials biasanya digunakan untuk menangani complex templates dengan mempunyai banyak view logic ( dalam konsep MVC, dibolehkan terdapat logic di view, asalkan logic tersebut digunakan untuk mengolah view , bukan mengolah data ). Misal kita ingin menampilkan data sehingga tampil seperti berikut :

Ok, kita bisa membuat Controller seperti di bawah :

<?php
//Controller
class TestpartialController extends Zend_Controller_Action
{
 public function init()
 {
 $this->getHelper('layout')->disableLayout();
 }

 //simple func to create fake data
 private function setItem($id,$name)
 {
 $item = new stdClass();
 $item->id = $id;
 $item->name = $name;

 return $item;
 }

 //index action -> render to index.phtml
 public function indexAction()
 {
 $items = array();
 $items[] = $this->setItem(1,'abdul');
 $items[] = $this->setItem(2,'malik');
 $items[] = $this->setItem(3,'ikhsan');
 $items[] = $this->setItem(4,'emang');
 $items[] = $this->setItem(5,'ganteng');
 $items[] = $this->setItem(6,'banget');
 $items[] = $this->setItem(7,'gitu lhoh');

 $this->view->items = $items;
 }
}

Nah, di sisi view, kita ingin menampilkan data dengan record bergantian warna-warni ( dibutuhkan logic untuk mengolah view ), maka kita bisa bagi menjadi 2, satu untuk “heading” ( index.phtml ) dan satu untuk dilooping dengan logic yg lebih kompleks ( rows.phtml ) .

<table width="70%">
 <tr>
 <th>ID</th>
 <th>NAME</th>
 </tr>
 <?php
 $alt = false;
 foreach($this->items as $item){
 $alt = !$alt;
 // 'render' another view
 echo $this->partial('testpartial/rows.phtml', array('alt'=>$alt, 'item'=>$item) );
 } ?>
</table>

Sekarang, kita buat file view lain yang akan dirender dengan variable yang dilewatkan

array('alt'=>$alt, 'item'=>$item)

Berikut contoh view logic ( rows.phtml ) :

<?php
 $style = "background-color:yellow;";  //view logic to manage view
 if ($this->alt) $style="";
?>
<tr style="<?php echo $style; ?>">
 <td><?php echo $this->item->id; ?></td>
 <td><?php echo $this->item->name; ?></td>
</tr>

Semoga bermanfaat 😀
Referensi :
http://www.zendcasts.com/zend-view-partials/2009/03/
http://devzone.zend.com/article/3412
http://framework.zend.com/manual/en/zend.view.helpers.html
http://stackoverflow.com/questions/746260/where-do-i-save-partial-views-in-zend-framework-to-be-accessible-for-all-views
http://stackoverflow.com/questions/931407/what-is-stdclass-in-php
http://www.webmaster-source.com/2009/08/20/php-stdclass-storing-data-object-instead-array/
http://us2.php.net/variables.scope