blob: fcfd89915f52c2e8fcddb6c52da8027d657fbe63 [file] [log] [blame]
Derek Jones4b9c6292011-07-01 17:40:48 -05001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Greg Aker0711dc82011-01-05 10:49:40 -06009 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * File Uploading Class
20 *
21 * @package CodeIgniter
22 * @subpackage Libraries
23 * @category Uploads
24 * @author ExpressionEngine Dev Team
25 * @link http://codeigniter.com/user_guide/libraries/file_uploading.html
26 */
27class CI_Upload {
Barry Mienydd671972010-10-04 16:33:58 +020028
Greg Aker58fdee82010-11-10 15:07:09 -060029 public $max_size = 0;
30 public $max_width = 0;
31 public $max_height = 0;
32 public $max_filename = 0;
Adam Jackettccbbea12011-08-21 16:19:11 -040033 public $max_filename_increment = 100;
Greg Aker58fdee82010-11-10 15:07:09 -060034 public $allowed_types = "";
35 public $file_temp = "";
36 public $file_name = "";
37 public $orig_name = "";
38 public $file_type = "";
39 public $file_size = "";
40 public $file_ext = "";
41 public $upload_path = "";
42 public $overwrite = FALSE;
43 public $encrypt_name = FALSE;
44 public $is_image = FALSE;
45 public $image_width = '';
46 public $image_height = '';
47 public $image_type = '';
48 public $image_size_str = '';
49 public $error_msg = array();
50 public $mimes = array();
51 public $remove_spaces = TRUE;
52 public $xss_clean = FALSE;
53 public $temp_prefix = "temp_file_";
54 public $client_name = '';
Barry Mienydd671972010-10-04 16:33:58 +020055
Greg Aker58fdee82010-11-10 15:07:09 -060056 protected $_file_name_override = '';
Barry Mienydd671972010-10-04 16:33:58 +020057
Derek Allard2067d1a2008-11-13 22:59:24 +000058 /**
59 * Constructor
60 *
61 * @access public
62 */
Greg Aker58fdee82010-11-10 15:07:09 -060063 public function __construct($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000064 {
65 if (count($props) > 0)
66 {
67 $this->initialize($props);
68 }
Barry Mienydd671972010-10-04 16:33:58 +020069
Derek Allard2067d1a2008-11-13 22:59:24 +000070 log_message('debug', "Upload Class Initialized");
71 }
Barry Mienydd671972010-10-04 16:33:58 +020072
Derek Allard2067d1a2008-11-13 22:59:24 +000073 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +020074
Derek Allard2067d1a2008-11-13 22:59:24 +000075 /**
76 * Initialize preferences
77 *
Derek Allard2067d1a2008-11-13 22:59:24 +000078 * @param array
79 * @return void
Barry Mienydd671972010-10-04 16:33:58 +020080 */
Greg Aker58fdee82010-11-10 15:07:09 -060081 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000082 {
83 $defaults = array(
Adam Jackettccbbea12011-08-21 16:19:11 -040084 'max_size' => 0,
85 'max_width' => 0,
86 'max_height' => 0,
87 'max_filename' => 0,
88 'max_filename_increment' => 100,
89 'allowed_types' => "",
90 'file_temp' => "",
91 'file_name' => "",
92 'orig_name' => "",
93 'file_type' => "",
94 'file_size' => "",
95 'file_ext' => "",
96 'upload_path' => "",
97 'overwrite' => FALSE,
98 'encrypt_name' => FALSE,
99 'is_image' => FALSE,
100 'image_width' => '',
101 'image_height' => '',
102 'image_type' => '',
103 'image_size_str' => '',
104 'error_msg' => array(),
105 'mimes' => array(),
106 'remove_spaces' => TRUE,
107 'xss_clean' => FALSE,
108 'temp_prefix' => "temp_file_",
109 'client_name' => ''
Barry Mienydd671972010-10-04 16:33:58 +0200110 );
111
112
Derek Allard2067d1a2008-11-13 22:59:24 +0000113 foreach ($defaults as $key => $val)
114 {
115 if (isset($config[$key]))
116 {
117 $method = 'set_'.$key;
118 if (method_exists($this, $method))
119 {
120 $this->$method($config[$key]);
121 }
122 else
123 {
124 $this->$key = $config[$key];
Barry Mienydd671972010-10-04 16:33:58 +0200125 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000126 }
127 else
128 {
129 $this->$key = $val;
130 }
131 }
Barry Mienydd671972010-10-04 16:33:58 +0200132
Derek Jonese9d723f2010-07-12 10:10:59 -0500133 // if a file_name was provided in the config, use it instead of the user input
134 // supplied file name for all uploads until initialized again
135 $this->_file_name_override = $this->file_name;
Derek Allard2067d1a2008-11-13 22:59:24 +0000136 }
Barry Mienydd671972010-10-04 16:33:58 +0200137
Derek Allard2067d1a2008-11-13 22:59:24 +0000138 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200139
Derek Allard2067d1a2008-11-13 22:59:24 +0000140 /**
141 * Perform the file upload
142 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000143 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200144 */
Greg Aker58fdee82010-11-10 15:07:09 -0600145 public function do_upload($field = 'userfile')
Derek Allard2067d1a2008-11-13 22:59:24 +0000146 {
Eric Barnes92808342011-03-18 09:02:37 -0400147
Robin Sowell0ecc0622011-01-30 16:47:43 -0500148 // Is $_FILES[$field] set? If not, no reason to continue.
Derek Allard2067d1a2008-11-13 22:59:24 +0000149 if ( ! isset($_FILES[$field]))
150 {
151 $this->set_error('upload_no_file_selected');
152 return FALSE;
153 }
Barry Mienydd671972010-10-04 16:33:58 +0200154
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 // Is the upload path valid?
156 if ( ! $this->validate_upload_path())
157 {
158 // errors will already be set by validate_upload_path() so just return FALSE
159 return FALSE;
160 }
161
162 // Was the file able to be uploaded? If not, determine the reason why.
163 if ( ! is_uploaded_file($_FILES[$field]['tmp_name']))
164 {
165 $error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];
166
167 switch($error)
168 {
169 case 1: // UPLOAD_ERR_INI_SIZE
170 $this->set_error('upload_file_exceeds_limit');
171 break;
172 case 2: // UPLOAD_ERR_FORM_SIZE
173 $this->set_error('upload_file_exceeds_form_limit');
174 break;
175 case 3: // UPLOAD_ERR_PARTIAL
Barry Mienydd671972010-10-04 16:33:58 +0200176 $this->set_error('upload_file_partial');
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 break;
178 case 4: // UPLOAD_ERR_NO_FILE
Barry Mienydd671972010-10-04 16:33:58 +0200179 $this->set_error('upload_no_file_selected');
Derek Allard2067d1a2008-11-13 22:59:24 +0000180 break;
181 case 6: // UPLOAD_ERR_NO_TMP_DIR
182 $this->set_error('upload_no_temp_directory');
183 break;
184 case 7: // UPLOAD_ERR_CANT_WRITE
185 $this->set_error('upload_unable_to_write_file');
186 break;
187 case 8: // UPLOAD_ERR_EXTENSION
188 $this->set_error('upload_stopped_by_extension');
189 break;
Derek Jones4b9c6292011-07-01 17:40:48 -0500190 default : $this->set_error('upload_no_file_selected');
Derek Allard2067d1a2008-11-13 22:59:24 +0000191 break;
192 }
193
194 return FALSE;
195 }
196
Derek Jonese9d723f2010-07-12 10:10:59 -0500197
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 // Set the uploaded data as class variables
Barry Mienydd671972010-10-04 16:33:58 +0200199 $this->file_temp = $_FILES[$field]['tmp_name'];
200 $this->file_size = $_FILES[$field]['size'];
Andrey Andreev3a3c9472011-09-24 14:25:33 +0300201 $this->_file_mime_type($_FILES[$field]);
202 $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $this->file_type);
Derek Jones616fb022010-04-22 16:52:18 -0500203 $this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
Derek Jonese9d723f2010-07-12 10:10:59 -0500204 $this->file_name = $this->_prep_filename($_FILES[$field]['name']);
205 $this->file_ext = $this->get_extension($this->file_name);
206 $this->client_name = $this->file_name;
Barry Mienydd671972010-10-04 16:33:58 +0200207
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 // Is the file type allowed to be uploaded?
209 if ( ! $this->is_allowed_filetype())
210 {
211 $this->set_error('upload_invalid_filetype');
212 return FALSE;
213 }
214
Derek Jonese9d723f2010-07-12 10:10:59 -0500215 // if we're overriding, let's now make sure the new name and type is allowed
216 if ($this->_file_name_override != '')
217 {
218 $this->file_name = $this->_prep_filename($this->_file_name_override);
Phil Sturgeon1e74da22010-12-15 10:45:06 +0000219
220 // If no extension was provided in the file_name config item, use the uploaded one
Pascal Kriete14287f32011-02-14 13:39:34 -0500221 if (strpos($this->_file_name_override, '.') === FALSE)
Phil Sturgeon1e74da22010-12-15 10:45:06 +0000222 {
223 $this->file_name .= $this->file_ext;
224 }
225
226 // An extension was provided, lets have it!
227 else
228 {
229 $this->file_ext = $this->get_extension($this->_file_name_override);
230 }
Derek Jonese9d723f2010-07-12 10:10:59 -0500231
232 if ( ! $this->is_allowed_filetype(TRUE))
233 {
234 $this->set_error('upload_invalid_filetype');
Barry Mienydd671972010-10-04 16:33:58 +0200235 return FALSE;
Derek Jonese9d723f2010-07-12 10:10:59 -0500236 }
237 }
Barry Mienydd671972010-10-04 16:33:58 +0200238
Derek Jonese9d723f2010-07-12 10:10:59 -0500239 // Convert the file size to kilobytes
240 if ($this->file_size > 0)
241 {
242 $this->file_size = round($this->file_size/1024, 2);
243 }
244
Derek Allard2067d1a2008-11-13 22:59:24 +0000245 // Is the file size within the allowed maximum?
246 if ( ! $this->is_allowed_filesize())
247 {
248 $this->set_error('upload_invalid_filesize');
249 return FALSE;
250 }
251
252 // Are the image dimensions within the allowed size?
253 // Note: This can fail if the server has an open_basdir restriction.
254 if ( ! $this->is_allowed_dimensions())
255 {
256 $this->set_error('upload_invalid_dimensions');
257 return FALSE;
258 }
259
260 // Sanitize the file name for security
261 $this->file_name = $this->clean_file_name($this->file_name);
Barry Mienydd671972010-10-04 16:33:58 +0200262
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 // Truncate the file name if it's too long
264 if ($this->max_filename > 0)
265 {
266 $this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);
267 }
268
269 // Remove white spaces in the name
270 if ($this->remove_spaces == TRUE)
271 {
272 $this->file_name = preg_replace("/\s+/", "_", $this->file_name);
273 }
274
275 /*
276 * Validate the file name
277 * This function appends an number onto the end of
278 * the file if one with the same name already exists.
279 * If it returns false there was a problem.
280 */
281 $this->orig_name = $this->file_name;
282
283 if ($this->overwrite == FALSE)
284 {
285 $this->file_name = $this->set_filename($this->upload_path, $this->file_name);
Barry Mienydd671972010-10-04 16:33:58 +0200286
Derek Allard2067d1a2008-11-13 22:59:24 +0000287 if ($this->file_name === FALSE)
288 {
289 return FALSE;
290 }
291 }
292
293 /*
Derek Jonese9d723f2010-07-12 10:10:59 -0500294 * Run the file through the XSS hacking filter
295 * This helps prevent malicious code from being
Derek Jones4b9c6292011-07-01 17:40:48 -0500296 * embedded within a file. Scripts can easily
Derek Jonese9d723f2010-07-12 10:10:59 -0500297 * be disguised as images or other file types.
298 */
299 if ($this->xss_clean)
300 {
301 if ($this->do_xss_clean() === FALSE)
302 {
303 $this->set_error('upload_unable_to_write_file');
304 return FALSE;
305 }
306 }
307
308 /*
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 * Move the file to the final destination
310 * To deal with different server configurations
Derek Jones4b9c6292011-07-01 17:40:48 -0500311 * we'll attempt to use copy() first. If that fails
312 * we'll use move_uploaded_file(). One of the two should
Derek Allard2067d1a2008-11-13 22:59:24 +0000313 * reliably work in most environments
314 */
315 if ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))
316 {
317 if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))
318 {
Barry Mienydd671972010-10-04 16:33:58 +0200319 $this->set_error('upload_destination_error');
320 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000321 }
322 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000323
324 /*
325 * Set the finalized image dimensions
326 * This sets the image width/height (assuming the
Derek Jones4b9c6292011-07-01 17:40:48 -0500327 * file was an image). We use this information
Derek Allard2067d1a2008-11-13 22:59:24 +0000328 * in the "data" function.
329 */
330 $this->set_image_properties($this->upload_path.$this->file_name);
331
332 return TRUE;
333 }
Barry Mienydd671972010-10-04 16:33:58 +0200334
Derek Allard2067d1a2008-11-13 22:59:24 +0000335 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200336
Derek Allard2067d1a2008-11-13 22:59:24 +0000337 /**
338 * Finalized Data Array
Barry Mienydd671972010-10-04 16:33:58 +0200339 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000340 * Returns an associative array containing all of the information
341 * related to the upload, allowing the developer easy access in one array.
342 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000343 * @return array
Barry Mienydd671972010-10-04 16:33:58 +0200344 */
Greg Aker58fdee82010-11-10 15:07:09 -0600345 public function data()
Derek Allard2067d1a2008-11-13 22:59:24 +0000346 {
347 return array (
348 'file_name' => $this->file_name,
349 'file_type' => $this->file_type,
350 'file_path' => $this->upload_path,
351 'full_path' => $this->upload_path.$this->file_name,
352 'raw_name' => str_replace($this->file_ext, '', $this->file_name),
353 'orig_name' => $this->orig_name,
Derek Jonese9d723f2010-07-12 10:10:59 -0500354 'client_name' => $this->client_name,
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 'file_ext' => $this->file_ext,
356 'file_size' => $this->file_size,
357 'is_image' => $this->is_image(),
358 'image_width' => $this->image_width,
359 'image_height' => $this->image_height,
360 'image_type' => $this->image_type,
361 'image_size_str' => $this->image_size_str,
362 );
363 }
Barry Mienydd671972010-10-04 16:33:58 +0200364
Derek Allard2067d1a2008-11-13 22:59:24 +0000365 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200366
Derek Allard2067d1a2008-11-13 22:59:24 +0000367 /**
368 * Set Upload Path
369 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 * @param string
371 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200372 */
Greg Aker58fdee82010-11-10 15:07:09 -0600373 public function set_upload_path($path)
Derek Allard2067d1a2008-11-13 22:59:24 +0000374 {
375 // Make sure it has a trailing slash
376 $this->upload_path = rtrim($path, '/').'/';
377 }
Barry Mienydd671972010-10-04 16:33:58 +0200378
Derek Allard2067d1a2008-11-13 22:59:24 +0000379 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200380
Derek Allard2067d1a2008-11-13 22:59:24 +0000381 /**
382 * Set the file name
383 *
384 * This function takes a filename/path as input and looks for the
385 * existence of a file with the same name. If found, it will append a
386 * number to the end of the filename to avoid overwriting a pre-existing file.
387 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000388 * @param string
389 * @param string
390 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200391 */
Greg Aker58fdee82010-11-10 15:07:09 -0600392 public function set_filename($path, $filename)
Derek Allard2067d1a2008-11-13 22:59:24 +0000393 {
394 if ($this->encrypt_name == TRUE)
Barry Mienydd671972010-10-04 16:33:58 +0200395 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000396 mt_srand();
Barry Mienydd671972010-10-04 16:33:58 +0200397 $filename = md5(uniqid(mt_rand())).$this->file_ext;
Derek Allard2067d1a2008-11-13 22:59:24 +0000398 }
Barry Mienydd671972010-10-04 16:33:58 +0200399
Derek Allard2067d1a2008-11-13 22:59:24 +0000400 if ( ! file_exists($path.$filename))
401 {
402 return $filename;
403 }
Barry Mienydd671972010-10-04 16:33:58 +0200404
Derek Allard2067d1a2008-11-13 22:59:24 +0000405 $filename = str_replace($this->file_ext, '', $filename);
Barry Mienydd671972010-10-04 16:33:58 +0200406
Derek Allard2067d1a2008-11-13 22:59:24 +0000407 $new_filename = '';
Adam Jackettccbbea12011-08-21 16:19:11 -0400408 for ($i = 1; $i < $this->max_filename_increment; $i++)
Barry Mienydd671972010-10-04 16:33:58 +0200409 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000410 if ( ! file_exists($path.$filename.$i.$this->file_ext))
411 {
412 $new_filename = $filename.$i.$this->file_ext;
413 break;
414 }
415 }
416
417 if ($new_filename == '')
418 {
419 $this->set_error('upload_bad_filename');
420 return FALSE;
421 }
422 else
423 {
424 return $new_filename;
425 }
426 }
Barry Mienydd671972010-10-04 16:33:58 +0200427
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200429
Derek Allard2067d1a2008-11-13 22:59:24 +0000430 /**
431 * Set Maximum File Size
432 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000433 * @param integer
434 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200435 */
Greg Aker58fdee82010-11-10 15:07:09 -0600436 public function set_max_filesize($n)
Derek Allard2067d1a2008-11-13 22:59:24 +0000437 {
438 $this->max_size = ((int) $n < 0) ? 0: (int) $n;
439 }
Barry Mienydd671972010-10-04 16:33:58 +0200440
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200442
Derek Allard2067d1a2008-11-13 22:59:24 +0000443 /**
444 * Set Maximum File Name Length
445 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000446 * @param integer
447 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200448 */
Greg Aker58fdee82010-11-10 15:07:09 -0600449 public function set_max_filename($n)
Derek Allard2067d1a2008-11-13 22:59:24 +0000450 {
451 $this->max_filename = ((int) $n < 0) ? 0: (int) $n;
452 }
453
454 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200455
Derek Allard2067d1a2008-11-13 22:59:24 +0000456 /**
457 * Set Maximum Image Width
458 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000459 * @param integer
460 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200461 */
Greg Aker58fdee82010-11-10 15:07:09 -0600462 public function set_max_width($n)
Derek Allard2067d1a2008-11-13 22:59:24 +0000463 {
464 $this->max_width = ((int) $n < 0) ? 0: (int) $n;
465 }
Barry Mienydd671972010-10-04 16:33:58 +0200466
Derek Allard2067d1a2008-11-13 22:59:24 +0000467 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200468
Derek Allard2067d1a2008-11-13 22:59:24 +0000469 /**
470 * Set Maximum Image Height
471 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000472 * @param integer
473 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200474 */
Greg Aker58fdee82010-11-10 15:07:09 -0600475 public function set_max_height($n)
Derek Allard2067d1a2008-11-13 22:59:24 +0000476 {
477 $this->max_height = ((int) $n < 0) ? 0: (int) $n;
478 }
Barry Mienydd671972010-10-04 16:33:58 +0200479
Derek Allard2067d1a2008-11-13 22:59:24 +0000480 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200481
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 /**
483 * Set Allowed File Types
484 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000485 * @param string
486 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200487 */
Greg Aker58fdee82010-11-10 15:07:09 -0600488 public function set_allowed_types($types)
Derek Allard2067d1a2008-11-13 22:59:24 +0000489 {
Derek Jonese12f64e2010-03-02 22:55:08 -0600490 if ( ! is_array($types) && $types == '*')
491 {
492 $this->allowed_types = '*';
493 return;
494 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000495 $this->allowed_types = explode('|', $types);
496 }
Barry Mienydd671972010-10-04 16:33:58 +0200497
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200499
Derek Allard2067d1a2008-11-13 22:59:24 +0000500 /**
501 * Set Image Properties
502 *
503 * Uses GD to determine the width/height/type of image
504 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000505 * @param string
506 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200507 */
Greg Aker58fdee82010-11-10 15:07:09 -0600508 public function set_image_properties($path = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000509 {
510 if ( ! $this->is_image())
511 {
512 return;
513 }
514
515 if (function_exists('getimagesize'))
516 {
517 if (FALSE !== ($D = @getimagesize($path)))
Barry Mienydd671972010-10-04 16:33:58 +0200518 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
520
521 $this->image_width = $D['0'];
522 $this->image_height = $D['1'];
523 $this->image_type = ( ! isset($types[$D['2']])) ? 'unknown' : $types[$D['2']];
Derek Jones4b9c6292011-07-01 17:40:48 -0500524 $this->image_size_str = $D['3']; // string containing height and width
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 }
526 }
527 }
Barry Mienydd671972010-10-04 16:33:58 +0200528
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200530
Derek Allard2067d1a2008-11-13 22:59:24 +0000531 /**
532 * Set XSS Clean
533 *
534 * Enables the XSS flag so that the file that was uploaded
535 * will be run through the XSS filter.
536 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000537 * @param bool
538 * @return void
539 */
Greg Aker58fdee82010-11-10 15:07:09 -0600540 public function set_xss_clean($flag = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000541 {
542 $this->xss_clean = ($flag == TRUE) ? TRUE : FALSE;
543 }
Barry Mienydd671972010-10-04 16:33:58 +0200544
Derek Allard2067d1a2008-11-13 22:59:24 +0000545 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200546
Derek Allard2067d1a2008-11-13 22:59:24 +0000547 /**
548 * Validate the image
549 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000550 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200551 */
Greg Aker58fdee82010-11-10 15:07:09 -0600552 public function is_image()
Derek Allard2067d1a2008-11-13 22:59:24 +0000553 {
554 // IE will sometimes return odd mime-types during upload, so here we just standardize all
555 // jpegs or pngs to the same file type.
556
Derek Jones4b9c6292011-07-01 17:40:48 -0500557 $png_mimes = array('image/x-png');
Derek Allard2067d1a2008-11-13 22:59:24 +0000558 $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');
Barry Mienydd671972010-10-04 16:33:58 +0200559
Derek Allard2067d1a2008-11-13 22:59:24 +0000560 if (in_array($this->file_type, $png_mimes))
561 {
562 $this->file_type = 'image/png';
563 }
Barry Mienydd671972010-10-04 16:33:58 +0200564
Derek Allard2067d1a2008-11-13 22:59:24 +0000565 if (in_array($this->file_type, $jpeg_mimes))
566 {
567 $this->file_type = 'image/jpeg';
568 }
569
570 $img_mimes = array(
571 'image/gif',
572 'image/jpeg',
573 'image/png',
Barry Mienydd671972010-10-04 16:33:58 +0200574 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000575
576 return (in_array($this->file_type, $img_mimes, TRUE)) ? TRUE : FALSE;
577 }
Barry Mienydd671972010-10-04 16:33:58 +0200578
Derek Allard2067d1a2008-11-13 22:59:24 +0000579 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200580
Derek Allard2067d1a2008-11-13 22:59:24 +0000581 /**
582 * Verify that the filetype is allowed
583 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000584 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200585 */
Greg Aker58fdee82010-11-10 15:07:09 -0600586 public function is_allowed_filetype($ignore_mime = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000587 {
Derek Jonese12f64e2010-03-02 22:55:08 -0600588 if ($this->allowed_types == '*')
589 {
590 return TRUE;
591 }
Barry Mienydd671972010-10-04 16:33:58 +0200592
Derek Allard2067d1a2008-11-13 22:59:24 +0000593 if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types))
594 {
595 $this->set_error('upload_no_file_types');
596 return FALSE;
597 }
Barry Mienydd671972010-10-04 16:33:58 +0200598
Derek Jonese9d723f2010-07-12 10:10:59 -0500599 $ext = strtolower(ltrim($this->file_ext, '.'));
Barry Mienydd671972010-10-04 16:33:58 +0200600
Derek Jonese9d723f2010-07-12 10:10:59 -0500601 if ( ! in_array($ext, $this->allowed_types))
Derek Allard2067d1a2008-11-13 22:59:24 +0000602 {
Derek Jonese9d723f2010-07-12 10:10:59 -0500603 return FALSE;
604 }
Derek Jonesafa282f2009-02-10 17:11:52 +0000605
Barry Mienydd671972010-10-04 16:33:58 +0200606 // Images get some additional checks
Derek Jonese9d723f2010-07-12 10:10:59 -0500607 $image_types = array('gif', 'jpg', 'jpeg', 'png', 'jpe');
Barry Mienydd671972010-10-04 16:33:58 +0200608
Derek Jonese9d723f2010-07-12 10:10:59 -0500609 if (in_array($ext, $image_types))
610 {
611 if (getimagesize($this->file_temp) === FALSE)
Derek Jonesafa282f2009-02-10 17:11:52 +0000612 {
Derek Jonese9d723f2010-07-12 10:10:59 -0500613 return FALSE;
Barry Mienydd671972010-10-04 16:33:58 +0200614 }
Derek Jonese9d723f2010-07-12 10:10:59 -0500615 }
Barry Mienydd671972010-10-04 16:33:58 +0200616
Derek Jonese9d723f2010-07-12 10:10:59 -0500617 if ($ignore_mime === TRUE)
618 {
619 return TRUE;
620 }
Barry Mienydd671972010-10-04 16:33:58 +0200621
Derek Jonese9d723f2010-07-12 10:10:59 -0500622 $mime = $this->mimes_types($ext);
Barry Mienydd671972010-10-04 16:33:58 +0200623
Derek Jonese9d723f2010-07-12 10:10:59 -0500624 if (is_array($mime))
625 {
626 if (in_array($this->file_type, $mime, TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000627 {
Derek Jonese9d723f2010-07-12 10:10:59 -0500628 return TRUE;
Barry Mienydd671972010-10-04 16:33:58 +0200629 }
Derek Jonese9d723f2010-07-12 10:10:59 -0500630 }
631 elseif ($mime == $this->file_type)
632 {
633 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000634 }
Barry Mienydd671972010-10-04 16:33:58 +0200635
Derek Allard2067d1a2008-11-13 22:59:24 +0000636 return FALSE;
637 }
Barry Mienydd671972010-10-04 16:33:58 +0200638
Derek Allard2067d1a2008-11-13 22:59:24 +0000639 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200640
Derek Allard2067d1a2008-11-13 22:59:24 +0000641 /**
642 * Verify that the file is within the allowed size
643 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000644 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200645 */
Greg Aker58fdee82010-11-10 15:07:09 -0600646 public function is_allowed_filesize()
Derek Allard2067d1a2008-11-13 22:59:24 +0000647 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500648 if ($this->max_size != 0 AND $this->file_size > $this->max_size)
Derek Allard2067d1a2008-11-13 22:59:24 +0000649 {
650 return FALSE;
651 }
652 else
653 {
654 return TRUE;
655 }
656 }
Barry Mienydd671972010-10-04 16:33:58 +0200657
Derek Allard2067d1a2008-11-13 22:59:24 +0000658 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200659
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 /**
661 * Verify that the image is within the allowed width/height
662 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000663 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200664 */
Greg Aker58fdee82010-11-10 15:07:09 -0600665 public function is_allowed_dimensions()
Derek Allard2067d1a2008-11-13 22:59:24 +0000666 {
667 if ( ! $this->is_image())
668 {
669 return TRUE;
670 }
671
672 if (function_exists('getimagesize'))
673 {
674 $D = @getimagesize($this->file_temp);
675
676 if ($this->max_width > 0 AND $D['0'] > $this->max_width)
677 {
678 return FALSE;
679 }
680
681 if ($this->max_height > 0 AND $D['1'] > $this->max_height)
682 {
683 return FALSE;
684 }
685
686 return TRUE;
687 }
688
689 return TRUE;
690 }
Barry Mienydd671972010-10-04 16:33:58 +0200691
Derek Allard2067d1a2008-11-13 22:59:24 +0000692 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200693
Derek Allard2067d1a2008-11-13 22:59:24 +0000694 /**
695 * Validate Upload Path
696 *
697 * Verifies that it is a valid upload path with proper permissions.
698 *
699 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000700 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200701 */
Greg Aker58fdee82010-11-10 15:07:09 -0600702 public function validate_upload_path()
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 {
704 if ($this->upload_path == '')
705 {
706 $this->set_error('upload_no_filepath');
707 return FALSE;
708 }
Barry Mienydd671972010-10-04 16:33:58 +0200709
Derek Allard2067d1a2008-11-13 22:59:24 +0000710 if (function_exists('realpath') AND @realpath($this->upload_path) !== FALSE)
711 {
712 $this->upload_path = str_replace("\\", "/", realpath($this->upload_path));
713 }
714
715 if ( ! @is_dir($this->upload_path))
716 {
717 $this->set_error('upload_no_filepath');
718 return FALSE;
719 }
720
721 if ( ! is_really_writable($this->upload_path))
722 {
723 $this->set_error('upload_not_writable');
724 return FALSE;
725 }
726
Derek Jones4b9c6292011-07-01 17:40:48 -0500727 $this->upload_path = preg_replace("/(.+?)\/*$/", "\\1/", $this->upload_path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000728 return TRUE;
729 }
Barry Mienydd671972010-10-04 16:33:58 +0200730
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200732
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 /**
734 * Extract the file extension
735 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000736 * @param string
737 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200738 */
Greg Aker58fdee82010-11-10 15:07:09 -0600739 public function get_extension($filename)
Derek Allard2067d1a2008-11-13 22:59:24 +0000740 {
741 $x = explode('.', $filename);
742 return '.'.end($x);
Barry Mienydd671972010-10-04 16:33:58 +0200743 }
744
Derek Allard2067d1a2008-11-13 22:59:24 +0000745 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200746
Derek Allard2067d1a2008-11-13 22:59:24 +0000747 /**
748 * Clean the file name for security
749 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000750 * @param string
751 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200752 */
Greg Aker58fdee82010-11-10 15:07:09 -0600753 public function clean_file_name($filename)
Derek Allard2067d1a2008-11-13 22:59:24 +0000754 {
755 $bad = array(
756 "<!--",
757 "-->",
758 "'",
759 "<",
760 ">",
761 '"',
762 '&',
763 '$',
764 '=',
765 ';',
766 '?',
767 '/',
768 "%20",
769 "%22",
770 "%3c", // <
Barry Mienydd671972010-10-04 16:33:58 +0200771 "%253c", // <
772 "%3e", // >
773 "%0e", // >
774 "%28", // (
775 "%29", // )
776 "%2528", // (
777 "%26", // &
778 "%24", // $
779 "%3f", // ?
780 "%3b", // ;
Derek Allard2067d1a2008-11-13 22:59:24 +0000781 "%3d" // =
782 );
Barry Mienydd671972010-10-04 16:33:58 +0200783
Derek Allard2067d1a2008-11-13 22:59:24 +0000784 $filename = str_replace($bad, '', $filename);
785
786 return stripslashes($filename);
787 }
788
789 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200790
Derek Allard2067d1a2008-11-13 22:59:24 +0000791 /**
792 * Limit the File Name Length
793 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000794 * @param string
795 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200796 */
Greg Aker58fdee82010-11-10 15:07:09 -0600797 public function limit_filename_length($filename, $length)
Derek Allard2067d1a2008-11-13 22:59:24 +0000798 {
799 if (strlen($filename) < $length)
800 {
801 return $filename;
802 }
Barry Mienydd671972010-10-04 16:33:58 +0200803
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 $ext = '';
805 if (strpos($filename, '.') !== FALSE)
806 {
807 $parts = explode('.', $filename);
808 $ext = '.'.array_pop($parts);
809 $filename = implode('.', $parts);
810 }
Barry Mienydd671972010-10-04 16:33:58 +0200811
Derek Allard2067d1a2008-11-13 22:59:24 +0000812 return substr($filename, 0, ($length - strlen($ext))).$ext;
813 }
814
815 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200816
Derek Allard2067d1a2008-11-13 22:59:24 +0000817 /**
818 * Runs the file through the XSS clean function
819 *
820 * This prevents people from embedding malicious code in their files.
821 * I'm not sure that it won't negatively affect certain files in unexpected ways,
822 * but so far I haven't found that it causes trouble.
823 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000824 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200825 */
Greg Aker58fdee82010-11-10 15:07:09 -0600826 public function do_xss_clean()
Barry Mienydd671972010-10-04 16:33:58 +0200827 {
Derek Jonese9d723f2010-07-12 10:10:59 -0500828 $file = $this->file_temp;
Barry Mienydd671972010-10-04 16:33:58 +0200829
Derek Allard2067d1a2008-11-13 22:59:24 +0000830 if (filesize($file) == 0)
831 {
832 return FALSE;
833 }
Barry Mienydd671972010-10-04 16:33:58 +0200834
Greg Akerf82e51c2010-04-14 19:33:50 -0500835 if (function_exists('memory_get_usage') && memory_get_usage() && ini_get('memory_limit') != '')
836 {
837 $current = ini_get('memory_limit') * 1024 * 1024;
Barry Mienydd671972010-10-04 16:33:58 +0200838
Greg Akerc78a2592010-06-09 11:45:32 -0500839 // There was a bug/behavioural change in PHP 5.2, where numbers over one million get output
Derek Jones4b9c6292011-07-01 17:40:48 -0500840 // into scientific notation. number_format() ensures this number is an integer
Greg Akerc78a2592010-06-09 11:45:32 -0500841 // http://bugs.php.net/bug.php?id=43053
Barry Mienydd671972010-10-04 16:33:58 +0200842
Greg Akerc78a2592010-06-09 11:45:32 -0500843 $new_memory = number_format(ceil(filesize($file) + $current), 0, '.', '');
Barry Mienydd671972010-10-04 16:33:58 +0200844
Greg Akerc78a2592010-06-09 11:45:32 -0500845 ini_set('memory_limit', $new_memory); // When an integer is used, the value is measured in bytes. - PHP.net
Greg Akerf82e51c2010-04-14 19:33:50 -0500846 }
847
848 // If the file being uploaded is an image, then we should have no problem with XSS attacks (in theory), but
849 // IE can be fooled into mime-type detecting a malformed image as an html file, thus executing an XSS attack on anyone
Derek Jones4b9c6292011-07-01 17:40:48 -0500850 // using IE who looks at the image. It does this by inspecting the first 255 bytes of an image. To get around this
851 // CI will itself look at the first 255 bytes of an image to determine its relative safety. This can save a lot of
Barry Mienydd671972010-10-04 16:33:58 +0200852 // processor power and time if it is actually a clean image, as it will be in nearly all instances _except_ an
Greg Akerf82e51c2010-04-14 19:33:50 -0500853 // attempted XSS attack.
854
855 if (function_exists('getimagesize') && @getimagesize($file) !== FALSE)
856 {
Barry Mienydd671972010-10-04 16:33:58 +0200857 if (($file = @fopen($file, 'rb')) === FALSE) // "b" to force binary
858 {
Greg Akerf82e51c2010-04-14 19:33:50 -0500859 return FALSE; // Couldn't open the file, return FALSE
Barry Mienydd671972010-10-04 16:33:58 +0200860 }
Greg Akerf82e51c2010-04-14 19:33:50 -0500861
Barry Mienydd671972010-10-04 16:33:58 +0200862 $opening_bytes = fread($file, 256);
863 fclose($file);
Greg Akerf82e51c2010-04-14 19:33:50 -0500864
865 // These are known to throw IE into mime-type detection chaos
866 // <a, <body, <head, <html, <img, <plaintext, <pre, <script, <table, <title
867 // title is basically just in SVG, but we filter it anyhow
868
869 if ( ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\s>]/i', $opening_bytes))
870 {
871 return TRUE; // its an image, no "triggers" detected in the first 256 bytes, we're good
872 }
873 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000874
875 if (($data = @file_get_contents($file)) === FALSE)
876 {
877 return FALSE;
878 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000879
Greg Akerf82e51c2010-04-14 19:33:50 -0500880 $CI =& get_instance();
Greg Akerf82e51c2010-04-14 19:33:50 -0500881 return $CI->security->xss_clean($data, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000882 }
Barry Mienydd671972010-10-04 16:33:58 +0200883
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200885
Derek Allard2067d1a2008-11-13 22:59:24 +0000886 /**
887 * Set an error message
888 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000889 * @param string
890 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200891 */
Greg Aker58fdee82010-11-10 15:07:09 -0600892 public function set_error($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +0000893 {
Barry Mienydd671972010-10-04 16:33:58 +0200894 $CI =& get_instance();
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 $CI->lang->load('upload');
Barry Mienydd671972010-10-04 16:33:58 +0200896
Derek Allard2067d1a2008-11-13 22:59:24 +0000897 if (is_array($msg))
898 {
899 foreach ($msg as $val)
900 {
Barry Mienydd671972010-10-04 16:33:58 +0200901 $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000902 $this->error_msg[] = $msg;
903 log_message('error', $msg);
Barry Mienydd671972010-10-04 16:33:58 +0200904 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000905 }
906 else
907 {
908 $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
909 $this->error_msg[] = $msg;
910 log_message('error', $msg);
911 }
912 }
Barry Mienydd671972010-10-04 16:33:58 +0200913
Derek Allard2067d1a2008-11-13 22:59:24 +0000914 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200915
Derek Allard2067d1a2008-11-13 22:59:24 +0000916 /**
917 * Display the error message
918 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000919 * @param string
920 * @param string
921 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200922 */
Greg Aker58fdee82010-11-10 15:07:09 -0600923 public function display_errors($open = '<p>', $close = '</p>')
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 {
925 $str = '';
926 foreach ($this->error_msg as $val)
927 {
928 $str .= $open.$val.$close;
929 }
Barry Mienydd671972010-10-04 16:33:58 +0200930
Derek Allard2067d1a2008-11-13 22:59:24 +0000931 return $str;
932 }
Barry Mienydd671972010-10-04 16:33:58 +0200933
Derek Allard2067d1a2008-11-13 22:59:24 +0000934 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200935
Derek Allard2067d1a2008-11-13 22:59:24 +0000936 /**
937 * List of Mime Types
938 *
Derek Jones4b9c6292011-07-01 17:40:48 -0500939 * This is a list of mime types. We use it to validate
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 * the "allowed types" set by the developer
941 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 * @param string
943 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200944 */
Greg Aker58fdee82010-11-10 15:07:09 -0600945 public function mimes_types($mime)
Derek Allard2067d1a2008-11-13 22:59:24 +0000946 {
947 global $mimes;
Barry Mienydd671972010-10-04 16:33:58 +0200948
Derek Allard2067d1a2008-11-13 22:59:24 +0000949 if (count($this->mimes) == 0)
950 {
Greg Aker3a746652011-04-19 10:59:47 -0500951 if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
bubbafoley0ea04142011-03-17 14:55:41 -0500952 {
Greg Aker3a746652011-04-19 10:59:47 -0500953 include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
Eric Barnesfdd5b112011-03-21 21:28:58 -0400954 }
Greg Aker3a746652011-04-19 10:59:47 -0500955 elseif (is_file(APPPATH.'config/mimes.php'))
Eric Barnesfdd5b112011-03-21 21:28:58 -0400956 {
Greg Aker3a746652011-04-19 10:59:47 -0500957 include(APPPATH.'config//mimes.php');
bubbafoley0ea04142011-03-17 14:55:41 -0500958 }
959 else
960 {
Eric Barnesfdd5b112011-03-21 21:28:58 -0400961 return FALSE;
bubbafoley0ea04142011-03-17 14:55:41 -0500962 }
Eric Barnes92808342011-03-18 09:02:37 -0400963
Eric Barnesfdd5b112011-03-21 21:28:58 -0400964 $this->mimes = $mimes;
965 unset($mimes);
Derek Allard2067d1a2008-11-13 22:59:24 +0000966 }
Barry Mienydd671972010-10-04 16:33:58 +0200967
Derek Allard2067d1a2008-11-13 22:59:24 +0000968 return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime];
969 }
970
971 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200972
Derek Allard2067d1a2008-11-13 22:59:24 +0000973 /**
974 * Prep Filename
975 *
976 * Prevents possible script execution from Apache's handling of files multiple extensions
977 * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
978 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000979 * @param string
980 * @return string
981 */
Greg Aker58fdee82010-11-10 15:07:09 -0600982 protected function _prep_filename($filename)
Derek Allard2067d1a2008-11-13 22:59:24 +0000983 {
Greg Aker924000e2010-07-22 11:04:58 -0500984 if (strpos($filename, '.') === FALSE OR $this->allowed_types == '*')
Derek Allard2067d1a2008-11-13 22:59:24 +0000985 {
986 return $filename;
987 }
Derek Allard616dab82009-02-16 15:44:32 +0000988
Derek Allard2067d1a2008-11-13 22:59:24 +0000989 $parts = explode('.', $filename);
990 $ext = array_pop($parts);
991 $filename = array_shift($parts);
Derek Allard616dab82009-02-16 15:44:32 +0000992
Derek Allard2067d1a2008-11-13 22:59:24 +0000993 foreach ($parts as $part)
994 {
Derek Jonese9d723f2010-07-12 10:10:59 -0500995 if ( ! in_array(strtolower($part), $this->allowed_types) OR $this->mimes_types(strtolower($part)) === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000996 {
997 $filename .= '.'.$part.'_';
998 }
999 else
1000 {
1001 $filename .= '.'.$part;
1002 }
1003 }
Derek Allardd70b0642009-02-16 13:51:42 +00001004
Derek Allard2067d1a2008-11-13 22:59:24 +00001005 $filename .= '.'.$ext;
Barry Mienydd671972010-10-04 16:33:58 +02001006
Derek Allard2067d1a2008-11-13 22:59:24 +00001007 return $filename;
1008 }
1009
1010 // --------------------------------------------------------------------
1011
Andrey Andreev3a3c9472011-09-24 14:25:33 +03001012 /**
1013 * File MIME type
1014 *
1015 * Detects the (actual) MIME type of the uploaded file, if possible.
1016 * The input array is expected to be $_FILES[$field]
1017 *
1018 * @param array
1019 * @return void
1020 */
1021 protected function _file_mime_type($file)
1022 {
1023 $file_type = '';
1024
1025 // Use if the Fileinfo extension, if available (only versions above 5.3 support the FILEINFO_MIME_TYPE flag)
1026 if ( (float) substr(phpversion(), 0, 3) >= 5.3 && function_exists('finfo_file'))
1027 {
1028 $finfo = new finfo(FILEINFO_MIME_TYPE);
1029 if ($finfo !== FALSE) // This is possible, if there is no magic MIME database file found on the system
1030 {
1031 $file_type = $finfo->file($file['tmp_name']);
1032
1033 /* According to the comments section of the PHP manual page,
1034 * it is possible that this function returns an empty string
1035 * for some files (e.g. if they don't exist in the magic MIME database.
1036 */
1037 if (strlen($file_type) > 1)
1038 {
1039 $this->file_type = $file_info;
1040 return;
1041 }
1042 }
1043 }
1044
1045 // Fall back to the deprecated mime_content_type(), if available
1046 if (function_exists('mime_content_type'))
1047 {
1048 $this->file_type = @mime_content_type($file['tmp_name']);
1049 return;
1050 }
1051
1052 /* This is an ugly hack, but UNIX-type systems provide a native way to detect the file type,
1053 * which is still more secure than depending on the value of $_FILES[$field]['type'].
1054 *
1055 * Notes:
1056 * - a 'W' in the substr() expression bellow, would mean that we're using Windows
1057 * - many system admins would disable the exec() function due to security concerns, hence the function_exists() check
1058 */
1059 if (substr(PHP_OS, 0, 1) !== 'W' && function_exists('exec'))
1060 {
1061 $output = array();
1062 @exec('file --brief --mime-type ' . escapeshellarg($file['tmp_path']), $output, $return_code);
1063 if ($return_code === 0 && strlen($output[0]) > 0) // A return status code != 0 would mean failed execution
1064 {
1065 $this->file_type = rtrim($output[0]);
1066 return;
1067 }
1068 }
1069
1070 $this->file_type = $file['type'];
1071 }
1072
1073 // --------------------------------------------------------------------
1074
Derek Allard2067d1a2008-11-13 22:59:24 +00001075}
1076// END Upload Class
1077
1078/* End of file Upload.php */
Andrey Andreev3a3c9472011-09-24 14:25:33 +03001079/* Location: ./system/libraries/Upload.php */