CodeIgniter File Upload: Setting Disallowed File Types
July 29, 2009
Recently I was working with a client on a file upload page in CodeIgniter. The client wanted to accept any file type except for those that could be considered malicious (For example – Windows EXEs, VB scripts, etc.). Seemed easy enough as I’ve done file uploading in CodeIgniter many times.
Initially I jumped into the File Upload Class and started to implement the page, but quickly discovered that the ‘allowed_types’ preference is a required field by default. That’s not exactly ideal when the list of allowed files is considerably larger than those that are disallowed. The solution I chose was to extend the existing File Upload Class as follows:
<?php
class MY_Upload extends CI_Upload {
// declare disallowed types variable
var $disallowed_types = '';
// add in the 'disallowed_types' default during initialization
function initialize($config = array()) {
$defaults = array(
'max_size' => 0,
'max_width' => 0,
'max_height' => 0,
'max_filename' => 0,
'allowed_types' => "",
'disallowed_types' => "",
'file_temp' => "",
'file_name' => "",
'orig_name' => "",
'file_type' => "",
'file_size' => "",
'file_ext' => "",
'upload_path' => "",
'overwrite' => FALSE,
'encrypt_name' => FALSE,
'is_image' => FALSE,
'image_width' => '',
'image_height' => '',
'image_type' => '',
'image_size_str' => '',
'error_msg' => array(),
'mimes' => array(),
'remove_spaces' => TRUE,
'xss_clean' => FALSE,
'temp_prefix' => "temp_file_"
);
foreach ($defaults as $key => $val) {
if (isset($config[$key])) {
$method = 'set_'.$key;
if (method_exists($this, $method)) {
$this->$method($config[$key]);
}
else {
$this->$key = $config[$key];
}
}
else {
$this->$key = $val;
}
}
}
// set disallowed filetypes
function set_disallowed_types($types) {
$this->disallowed_types = explode('|', $types);
}
// adapted to not require allowed_types and to check for disallowed types if it exists
function is_allowed_filetype() {
// if allowed file type list is not defined
if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types)) {
// if disallowed file type list is not defined
if (count($this->disallowed_types) == 0 OR ! is_array($this->disallowed_types))
return TRUE;
// check for disallowed file types and return
// negated because is_disallowed_filetype returns opposite result as this function
return ! $this->is_disallowed_filetype();
}
// proceed as usual with allowed file type list check
return parent::is_allowed_filetype();
}
// check for disallowed file types
function is_disallowed_filetype() {
// no file types provided
if (count($this->disallowed_types) == 0 OR ! is_array($this->disallowed_types))
return FALSE;
// search through disallowed for this file type
foreach ($this->disallowed_types as $val) {
$mime = $this->mimes_types(strtolower($val));
if (is_array($mime)) {
if (in_array($this->file_type, $mime, TRUE)) {
return TRUE;
}
}
else {
if ($mime == $this->file_type) {
return TRUE;
}
}
}
return FALSE;
}
}
?>
Now, rather than using $config[‘allowed_types’], you will want to use $config[‘disallowed_types’] while initializing the File Upload Library. Extensions should be listed in the same manner.
Note that as is with the default File Upload library, disallowed MIME types must be defined in config/mimes.php.