CodeIgniter File Upload: Setting Disallowed File Types

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.

Want more articles like this one in your Inbox? Subscribe