Welcome Guest, Not a member yet? Register   Sign In
Uploadify (jQuery) + CI Sessions + CI Upload Class *Again*
#1

[eluser]~Chris~[/eluser]
I'm back!

About 4 years ago I posted an article using codeigniter with swfupload, located here: http://ellislab.com/forums/viewthread/97399/

Well, things have changed and now we have Uploadify, which is awesome, and I noticed there were still some fairly recent replies to that other topic, so I thought I would write a new topic with how I'm doing it now, with Uploadify!. I believe its pretty secure, but I'm sure there are ways to make it even more secure.

If your using Uploadifive, you can pretty much ignore this, as HTML5 doesnt have all the issues that the flash version of uploadify has. But if your using the Flash Based uploadify, its important to remember that flash has its own cookies and doesn't share them with the browser, so your sessions dont travel with the request made from the flash applet in Uploadify. Here is a solution to work with that.

I will assume you you will be uploading an image, lets say a png file. This tut will revolve around that just to get you started, but of course is not limited to that.

Configuration:
In order for this to work you need to store the sessions in your database, make sure you have all the proper tables installed. I chose to encrypt my cookies, so make sure your encrypt key is set up.

config/config.php
Code:
$config['sess_cookie_name']  = 'ci_session';
$config['sess_expiration']  = 7200;
$config['sess_expire_on_close'] = FALSE;
$config['sess_encrypt_cookie'] = TRUE;
$config['sess_use_database'] = TRUE;
$config['sess_table_name']  = 'sessions';
$config['sess_match_ip']  = TRUE;
$config['sess_match_useragent'] = TRUE;
$config['sess_time_to_update'] = 300;

Uploadify sends all files (regardless of type) with the mimetype of application/octet-stream
You need to add this mimetype to file extension or it will get rejected by the upload class.
config/mimes.php
Code:
'png' => array('image/png',  'image/x-png', 'application/octet-stream'),

Extend the sessions class. We will have uploadify send an encrypted session id, and have the sessions class decode and use it if its present.
libraries/MY_Session.php
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Session extends CI_Session
{
public function __construct() {
  parent::__construct();
  
                //flash seems to use this user agent, so we can identify if the request is coming from uploadify
  if ($this->userdata('user_agent') == "Shockwave Flash") {
  
                        //a custom session variable, if your already "logged in" on your flash session, than just make sure the session is still valid.
   if ($this->userdata('logged_in')) {
    
    //make sure parent is still active
    if(!$this->userdata('parent_session'))
    {
     $this->sess_destroy();
     return;
    }
    
    $this->CI->db->where('session_id', $this->userdata('parent_session'));
    $this->CI->db->where('ip_address', $this->userdata('ip_address'));
    $this->CI->db->select("last_activity");
    
    $query = $this->CI->db->get($this->sess_table_name);
    
    // couldnt find session
    if ($query->num_rows() == 0)
    {
     $this->sess_destroy();
     return;
    }
    
    $row = $query->row();
    $last_activity = $row->last_activity;
    //check that the session hasnt expired
    if (($last_activity + $this->sess_expiration) < $this->now)
    {
     $this->sess_destroy();
     return;
    }
    
   //not yet logged in
   } else {
    
    $sessdata = $this->CI->input->post('sessdata');
    if ($sessdata) {
     //decode the sess data
     $sessdata = $this->CI->encrypt->decode($sessdata);
     $sessdata = unserialize($sessdata);
    
     if (empty($sessdata['session_id']) || empty($sessdata['timestamp'])) {
      $this->sess_destroy();
      return;
     }
    
     //attempt to clone the session...
     $parent_session['session_id'] = $sessdata['session_id'];
     $parent_session['ip_address'] = $this->userdata('ip_address');
    
     $this->CI->db->where('session_id', $parent_session['session_id']);
     $this->CI->db->where('ip_address', $parent_session['ip_address']);
    
     $query = $this->CI->db->get($this->sess_table_name);
    
     // couldnt find session
     if ($query->num_rows() == 0)
     {
      $this->sess_destroy();
      return;
     }
    
     //retreive data
     $row = $query->row();
     $parent_session['last_activity'] = $row->last_activity;
     if (isset($row->user_data) AND $row->user_data != '')
     {
      $custom_data = $this->_unserialize($row->user_data);
    
      if (is_array($custom_data))
      {
       foreach ($custom_data as $key => $val)
       {
        $parent_session[$key] = $val;
       }
      }
     }
    
     //check that the session hasnt expired
     if (($parent_session['last_activity'] + $this->sess_expiration) < $this->now)
     {
      $this->sess_destroy();
      return;
     }
    
     if ($parent_session['logged_in']) {
    
                                        //DO STUFF HERE
                                        //You want to mimic the values of the parent session. But for better security flash will still maintain its own session id. if you use a logged_in flag and user_id in your session vars to check if a user is signed on and identify them, you'll want to set that up here.

      $this->set_userdata('parent_session', $parent_session['session_id']);
      $this->set_userdata('logged_in', $parent_session['logged_in']);
      $this->set_userdata('user_id', $parent_session['user_id']);
      
     }
    
    } else {
     $this->sess_destroy();
     return;
    }
   }
  
  
  }
}

        //this method will help get an encrypted session id to send through uploadify
public function get_encrypted_sessdata() {
  $data['session_id'] = $this->userdata('session_id');
  $data['timestamp'] = time();
  
  $data = serialize($data);
  $data = $this->CI->encrypt->encode($data);
  return $data;
}
}

#2

[eluser]~Chris~[/eluser]
Controller:
heres a snippet for your upload method. note that this can be in an authenticated controller, since the flash session will authenticate itself via the session id.
Code:
class UploadController extends CI_Controller {

...

public function uploadify() {
  $config['upload_path'] = "path_to_save_files";
  $config['allowed_types'] = 'png';
  $this->load->library('upload', $config);

  if ( ! $this->upload->do_upload("userfile"))
  {
   $error = $this->upload->display_errors();
   // do stuff
   show_error('doh!', 500);
  }
  else
  {
   $data = $this->upload->data();
   // do stuff on success
   echo "yay!";
  }
}
}

And finally, here is the the view snippet showing how to set up uploadify.

Code:
<div class="uploadify-queue" id="file-queue"></div>
&lt;input type="file" name="userfile" id="upload_btn" /&gt;

&lt;script type='text/javascript' &gt;
$(function() {
$('#upload_btn').uploadify({
  'debug'   : false,
  
  'swf'   : '/assets/swf/uploadify.swf',
  'uploader'  : '&lt;?=site_url('uploadcontroller/uploadify')?&gt;',
  'cancelImage' : '/assets/img/uploadify-cancel.png',
  'queueID'  : 'file-queue',
  'buttonClass'  : 'button',
  'buttonText' : "Upload Files",
  'multi'   : true,
  'auto'   : true,
  
  'fileTypeExts' : '*.png',
  'fileTypeDesc' : 'png Files',
  
  'formData'  : {'sessdata' : '&lt;?=$this->session->get_encrypted_sessdata()?&gt;'},
  'method'  : 'post',
  'fileObjName' : 'userfile',
  
  'queueSizeLimit': 99,
  'simUploadLimit': 2,
  'sizeLimit'  : 10240000
    });
    
});
&lt;/script&gt;

And there it is. Hope that helps people. There is even more you could do with that, but I will leave that up to your imagination.

disclaimer* i didn't spell check, and i rarely uppercase my I's
disclaimer2*: mmm just in case heres a license for the code written in this topic. http://opensource.org/licenses/OSL-3.0
Your free to use any code I've written: Attribution (to Chris Churchwell) is appreciated.
#3

[eluser]TunaMaxx[/eluser]
This is a really timely follow-up; Glad to see you just posted in the last few months.

Now to go try it out!
#4

[eluser]Unknown[/eluser]
hi, chris.
if I need to use swfupload, is the MY_Session class roughly the same?




Theme © iAndrew 2016 - Forum software by © MyBB