blob: a2437d072edba7566c324b73ee6fa7de85683345 [file] [log] [blame]
Derek Jones0b59f272008-05-13 04:22:33 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allardd2df9bc2007-04-15 17:41:17 +00002/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
Derek Allard3d879d52008-01-18 19:41:32 +00008 * @author ExpressionEngine Dev Team
Rick Ellise4a7db42008-09-12 23:35:09 +00009 * @copyright Copyright (c) 2008, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allardd2df9bc2007-04-15 17:41:17 +000012 * @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
Derek Allard3d879d52008-01-18 19:41:32 +000024 * @author ExpressionEngine Dev Team
Derek Jones7a9193a2008-01-21 18:39:20 +000025 * @link http://codeigniter.com/user_guide/libraries/file_uploading.html
Derek Allardd2df9bc2007-04-15 17:41:17 +000026 */
27class CI_Upload {
28
29 var $max_size = 0;
30 var $max_width = 0;
31 var $max_height = 0;
Rick Ellis2f26ba92008-10-04 01:38:01 +000032 var $max_filename = 0;
Derek Allardd2df9bc2007-04-15 17:41:17 +000033 var $allowed_types = "";
34 var $file_temp = "";
35 var $file_name = "";
36 var $orig_name = "";
37 var $file_type = "";
38 var $file_size = "";
39 var $file_ext = "";
40 var $upload_path = "";
41 var $overwrite = FALSE;
42 var $encrypt_name = FALSE;
43 var $is_image = FALSE;
44 var $image_width = '';
45 var $image_height = '';
46 var $image_type = '';
47 var $image_size_str = '';
48 var $error_msg = array();
49 var $mimes = array();
50 var $remove_spaces = TRUE;
51 var $xss_clean = FALSE;
52 var $temp_prefix = "temp_file_";
53
54 /**
55 * Constructor
56 *
57 * @access public
58 */
59 function CI_Upload($props = array())
60 {
61 if (count($props) > 0)
62 {
63 $this->initialize($props);
64 }
65
66 log_message('debug', "Upload Class Initialized");
67 }
68
69 // --------------------------------------------------------------------
70
71 /**
72 * Initialize preferences
73 *
74 * @access public
75 * @param array
76 * @return void
77 */
78 function initialize($config = array())
79 {
80 $defaults = array(
81 'max_size' => 0,
82 'max_width' => 0,
83 'max_height' => 0,
84 'allowed_types' => "",
85 'file_temp' => "",
86 'file_name' => "",
87 'orig_name' => "",
88 'file_type' => "",
89 'file_size' => "",
90 'file_ext' => "",
91 'upload_path' => "",
92 'overwrite' => FALSE,
93 'encrypt_name' => FALSE,
94 'is_image' => FALSE,
95 'image_width' => '',
96 'image_height' => '',
97 'image_type' => '',
98 'image_size_str' => '',
99 'error_msg' => array(),
100 'mimes' => array(),
101 'remove_spaces' => TRUE,
102 'xss_clean' => FALSE,
103 'temp_prefix' => "temp_file_"
104 );
105
106
107 foreach ($defaults as $key => $val)
108 {
109 if (isset($config[$key]))
110 {
111 $method = 'set_'.$key;
112 if (method_exists($this, $method))
113 {
114 $this->$method($config[$key]);
115 }
116 else
117 {
118 $this->$key = $config[$key];
119 }
120 }
121 else
122 {
123 $this->$key = $val;
124 }
125 }
126 }
127
128 // --------------------------------------------------------------------
129
130 /**
131 * Perform the file upload
132 *
133 * @access public
134 * @return bool
135 */
136 function do_upload($field = 'userfile')
137 {
138 // Is $_FILES[$field] set? If not, no reason to continue.
Derek Jones0b59f272008-05-13 04:22:33 +0000139 if ( ! isset($_FILES[$field]))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000140 {
Derek Allard9ece7432008-01-29 01:15:19 +0000141 $this->set_error('upload_no_file_selected');
Derek Allardd2df9bc2007-04-15 17:41:17 +0000142 return FALSE;
143 }
144
145 // Is the upload path valid?
Derek Jones0b59f272008-05-13 04:22:33 +0000146 if ( ! $this->validate_upload_path())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000147 {
Derek Jones8e946462008-05-08 19:55:35 +0000148 // errors will already be set by validate_upload_path() so just return FALSE
Derek Allardd2df9bc2007-04-15 17:41:17 +0000149 return FALSE;
150 }
Rick Ellis2f26ba92008-10-04 01:38:01 +0000151
Derek Allardd2df9bc2007-04-15 17:41:17 +0000152 // Was the file able to be uploaded? If not, determine the reason why.
Derek Jones0b59f272008-05-13 04:22:33 +0000153 if ( ! is_uploaded_file($_FILES[$field]['tmp_name']))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000154 {
Derek Jones0b59f272008-05-13 04:22:33 +0000155 $error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];
Derek Allardd2df9bc2007-04-15 17:41:17 +0000156
157 switch($error)
158 {
Derek Jonesc4c0ac42008-01-18 20:45:28 +0000159 case 1: // UPLOAD_ERR_INI_SIZE
160 $this->set_error('upload_file_exceeds_limit');
Derek Allardd2df9bc2007-04-15 17:41:17 +0000161 break;
Derek Jonesc4c0ac42008-01-18 20:45:28 +0000162 case 2: // UPLOAD_ERR_FORM_SIZE
163 $this->set_error('upload_file_exceeds_form_limit');
Derek Allardd2df9bc2007-04-15 17:41:17 +0000164 break;
Derek Jonesc4c0ac42008-01-18 20:45:28 +0000165 case 3: // UPLOAD_ERR_PARTIAL
166 $this->set_error('upload_file_partial');
167 break;
168 case 4: // UPLOAD_ERR_NO_FILE
169 $this->set_error('upload_no_file_selected');
170 break;
171 case 6: // UPLOAD_ERR_NO_TMP_DIR
172 $this->set_error('upload_no_temp_directory');
173 break;
174 case 7: // UPLOAD_ERR_CANT_WRITE
175 $this->set_error('upload_unable_to_write_file');
176 break;
177 case 8: // UPLOAD_ERR_EXTENSION
178 $this->set_error('upload_stopped_by_extension');
Derek Allardd2df9bc2007-04-15 17:41:17 +0000179 break;
180 default : $this->set_error('upload_no_file_selected');
181 break;
182 }
183
184 return FALSE;
185 }
186
187 // Set the uploaded data as class variables
188 $this->file_temp = $_FILES[$field]['tmp_name'];
Derek Jones6ef8b692008-03-17 19:09:12 +0000189 $this->file_name = $this->_prep_filename($_FILES[$field]['name']);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000190 $this->file_size = $_FILES[$field]['size'];
191 $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
192 $this->file_type = strtolower($this->file_type);
193 $this->file_ext = $this->get_extension($_FILES[$field]['name']);
194
195 // Convert the file size to kilobytes
196 if ($this->file_size > 0)
197 {
198 $this->file_size = round($this->file_size/1024, 2);
199 }
200
201 // Is the file type allowed to be uploaded?
Derek Jones0b59f272008-05-13 04:22:33 +0000202 if ( ! $this->is_allowed_filetype())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000203 {
204 $this->set_error('upload_invalid_filetype');
205 return FALSE;
206 }
207
208 // Is the file size within the allowed maximum?
Derek Jones0b59f272008-05-13 04:22:33 +0000209 if ( ! $this->is_allowed_filesize())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000210 {
211 $this->set_error('upload_invalid_filesize');
212 return FALSE;
213 }
214
215 // Are the image dimensions within the allowed size?
216 // Note: This can fail if the server has an open_basdir restriction.
Derek Jones0b59f272008-05-13 04:22:33 +0000217 if ( ! $this->is_allowed_dimensions())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000218 {
219 $this->set_error('upload_invalid_dimensions');
220 return FALSE;
221 }
222
223 // Sanitize the file name for security
224 $this->file_name = $this->clean_file_name($this->file_name);
Rick Ellis2f26ba92008-10-04 01:38:01 +0000225
226 // Truncate the file name if it's too long
227 if ($this->max_filename > 0)
228 {
229 $this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);
230 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000231
232 // Remove white spaces in the name
233 if ($this->remove_spaces == TRUE)
234 {
235 $this->file_name = preg_replace("/\s+/", "_", $this->file_name);
236 }
237
238 /*
239 * Validate the file name
240 * This function appends an number onto the end of
241 * the file if one with the same name already exists.
242 * If it returns false there was a problem.
243 */
244 $this->orig_name = $this->file_name;
245
246 if ($this->overwrite == FALSE)
247 {
248 $this->file_name = $this->set_filename($this->upload_path, $this->file_name);
249
250 if ($this->file_name === FALSE)
251 {
252 return FALSE;
253 }
254 }
255
256 /*
257 * Move the file to the final destination
258 * To deal with different server configurations
259 * we'll attempt to use copy() first. If that fails
260 * we'll use move_uploaded_file(). One of the two should
261 * reliably work in most environments
262 */
Derek Jones0b59f272008-05-13 04:22:33 +0000263 if ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000264 {
Derek Jones0b59f272008-05-13 04:22:33 +0000265 if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000266 {
267 $this->set_error('upload_destination_error');
268 return FALSE;
269 }
270 }
271
272 /*
273 * Run the file through the XSS hacking filter
274 * This helps prevent malicious code from being
275 * embedded within a file. Scripts can easily
276 * be disguised as images or other file types.
277 */
278 if ($this->xss_clean == TRUE)
279 {
280 $this->do_xss_clean();
281 }
282
283 /*
284 * Set the finalized image dimensions
285 * This sets the image width/height (assuming the
286 * file was an image). We use this information
287 * in the "data" function.
288 */
289 $this->set_image_properties($this->upload_path.$this->file_name);
290
291 return TRUE;
292 }
293
294 // --------------------------------------------------------------------
295
296 /**
297 * Finalized Data Array
298 *
299 * Returns an associative array containing all of the information
300 * related to the upload, allowing the developer easy access in one array.
301 *
302 * @access public
303 * @return array
304 */
305 function data()
306 {
307 return array (
308 'file_name' => $this->file_name,
309 'file_type' => $this->file_type,
310 'file_path' => $this->upload_path,
311 'full_path' => $this->upload_path.$this->file_name,
312 'raw_name' => str_replace($this->file_ext, '', $this->file_name),
313 'orig_name' => $this->orig_name,
314 'file_ext' => $this->file_ext,
315 'file_size' => $this->file_size,
316 'is_image' => $this->is_image(),
317 'image_width' => $this->image_width,
318 'image_height' => $this->image_height,
319 'image_type' => $this->image_type,
320 'image_size_str' => $this->image_size_str,
321 );
322 }
323
324 // --------------------------------------------------------------------
325
326 /**
327 * Set Upload Path
328 *
329 * @access public
330 * @param string
331 * @return void
332 */
333 function set_upload_path($path)
334 {
Rick Ellis2f26ba92008-10-04 01:38:01 +0000335 // Make sure it has a trailing slash
336 $this->upload_path = rtrim($path, '/').'/';
Derek Allardd2df9bc2007-04-15 17:41:17 +0000337 }
338
339 // --------------------------------------------------------------------
340
341 /**
342 * Set the file name
343 *
344 * This function takes a filename/path as input and looks for the
345 * existence of a file with the same name. If found, it will append a
346 * number to the end of the filename to avoid overwriting a pre-existing file.
347 *
348 * @access public
349 * @param string
350 * @param string
351 * @return string
352 */
353 function set_filename($path, $filename)
354 {
355 if ($this->encrypt_name == TRUE)
356 {
357 mt_srand();
Rick Ellis2f26ba92008-10-04 01:38:01 +0000358 $filename = md5(uniqid(mt_rand())).$this->file_ext;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000359 }
360
Derek Jones0b59f272008-05-13 04:22:33 +0000361 if ( ! file_exists($path.$filename))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000362 {
363 return $filename;
364 }
365
366 $filename = str_replace($this->file_ext, '', $filename);
367
368 $new_filename = '';
369 for ($i = 1; $i < 100; $i++)
370 {
Derek Jones0b59f272008-05-13 04:22:33 +0000371 if ( ! file_exists($path.$filename.$i.$this->file_ext))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000372 {
373 $new_filename = $filename.$i.$this->file_ext;
374 break;
375 }
376 }
377
378 if ($new_filename == '')
379 {
380 $this->set_error('upload_bad_filename');
381 return FALSE;
382 }
383 else
384 {
385 return $new_filename;
386 }
387 }
388
389 // --------------------------------------------------------------------
390
391 /**
392 * Set Maximum File Size
393 *
394 * @access public
395 * @param integer
396 * @return void
397 */
398 function set_max_filesize($n)
399 {
Derek Jones0b59f272008-05-13 04:22:33 +0000400 $this->max_size = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000401 }
402
403 // --------------------------------------------------------------------
404
405 /**
Rick Ellis2f26ba92008-10-04 01:38:01 +0000406 * Set Maximum File Name Length
407 *
408 * @access public
409 * @param integer
410 * @return void
411 */
412 function set_max_filename($n)
413 {
414 $this->max_filename = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
415 }
416
417 // --------------------------------------------------------------------
418
419 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000420 * Set Maximum Image Width
421 *
422 * @access public
423 * @param integer
424 * @return void
425 */
426 function set_max_width($n)
427 {
Derek Jones0b59f272008-05-13 04:22:33 +0000428 $this->max_width = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000429 }
430
431 // --------------------------------------------------------------------
432
433 /**
434 * Set Maximum Image Height
435 *
436 * @access public
437 * @param integer
438 * @return void
439 */
440 function set_max_height($n)
441 {
Derek Jones0b59f272008-05-13 04:22:33 +0000442 $this->max_height = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000443 }
444
445 // --------------------------------------------------------------------
446
447 /**
448 * Set Allowed File Types
449 *
450 * @access public
451 * @param string
452 * @return void
453 */
454 function set_allowed_types($types)
455 {
456 $this->allowed_types = explode('|', $types);
457 }
458
459 // --------------------------------------------------------------------
460
461 /**
462 * Set Image Properties
463 *
464 * Uses GD to determine the width/height/type of image
465 *
466 * @access public
467 * @param string
468 * @return void
469 */
470 function set_image_properties($path = '')
471 {
Derek Jones0b59f272008-05-13 04:22:33 +0000472 if ( ! $this->is_image())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000473 {
474 return;
475 }
476
477 if (function_exists('getimagesize'))
478 {
479 if (FALSE !== ($D = @getimagesize($path)))
480 {
481 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
482
483 $this->image_width = $D['0'];
484 $this->image_height = $D['1'];
Derek Jones0b59f272008-05-13 04:22:33 +0000485 $this->image_type = ( ! isset($types[$D['2']])) ? 'unknown' : $types[$D['2']];
Derek Allardd2df9bc2007-04-15 17:41:17 +0000486 $this->image_size_str = $D['3']; // string containing height and width
487 }
488 }
489 }
490
491 // --------------------------------------------------------------------
492
493 /**
494 * Set XSS Clean
495 *
496 * Enables the XSS flag so that the file that was uploaded
497 * will be run through the XSS filter.
498 *
499 * @access public
500 * @param bool
501 * @return void
502 */
503 function set_xss_clean($flag = FALSE)
504 {
505 $this->xss_clean = ($flag == TRUE) ? TRUE : FALSE;
506 }
507
508 // --------------------------------------------------------------------
509
510 /**
511 * Validate the image
512 *
513 * @access public
514 * @return bool
515 */
516 function is_image()
517 {
paulburdick2f35c4b2007-06-24 20:29:09 +0000518 // IE will sometimes return odd mime-types during upload, so here we just standardize all
519 // jpegs or pngs to the same file type.
520
521 $png_mimes = array('image/x-png');
522 $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');
523
524 if (in_array($this->file_type, $png_mimes))
525 {
526 $this->file_type = 'image/png';
527 }
528
529 if (in_array($this->file_type, $jpeg_mimes))
530 {
531 $this->file_type = 'image/jpeg';
532 }
533
Derek Allardd2df9bc2007-04-15 17:41:17 +0000534 $img_mimes = array(
535 'image/gif',
Derek Allardd2df9bc2007-04-15 17:41:17 +0000536 'image/jpeg',
Derek Allardd2df9bc2007-04-15 17:41:17 +0000537 'image/png',
Derek Allardd2df9bc2007-04-15 17:41:17 +0000538 );
539
Derek Allardd2df9bc2007-04-15 17:41:17 +0000540 return (in_array($this->file_type, $img_mimes, TRUE)) ? TRUE : FALSE;
541 }
542
543 // --------------------------------------------------------------------
544
545 /**
546 * Verify that the filetype is allowed
547 *
548 * @access public
549 * @return bool
550 */
551 function is_allowed_filetype()
552 {
Derek Jones0b59f272008-05-13 04:22:33 +0000553 if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000554 {
555 $this->set_error('upload_no_file_types');
556 return FALSE;
557 }
558
559 foreach ($this->allowed_types as $val)
560 {
561 $mime = $this->mimes_types(strtolower($val));
562
563 if (is_array($mime))
564 {
565 if (in_array($this->file_type, $mime, TRUE))
566 {
567 return TRUE;
568 }
569 }
570 else
571 {
572 if ($mime == $this->file_type)
573 {
574 return TRUE;
575 }
576 }
577 }
578
579 return FALSE;
580 }
581
582 // --------------------------------------------------------------------
583
584 /**
585 * Verify that the file is within the allowed size
586 *
587 * @access public
588 * @return bool
589 */
590 function is_allowed_filesize()
591 {
592 if ($this->max_size != 0 AND $this->file_size > $this->max_size)
593 {
594 return FALSE;
595 }
596 else
597 {
598 return TRUE;
599 }
600 }
601
602 // --------------------------------------------------------------------
603
604 /**
605 * Verify that the image is within the allowed width/height
606 *
607 * @access public
608 * @return bool
609 */
610 function is_allowed_dimensions()
611 {
Derek Jones0b59f272008-05-13 04:22:33 +0000612 if ( ! $this->is_image())
Derek Allardd2df9bc2007-04-15 17:41:17 +0000613 {
614 return TRUE;
615 }
616
617 if (function_exists('getimagesize'))
618 {
619 $D = @getimagesize($this->file_temp);
620
621 if ($this->max_width > 0 AND $D['0'] > $this->max_width)
622 {
623 return FALSE;
624 }
625
626 if ($this->max_height > 0 AND $D['1'] > $this->max_height)
627 {
628 return FALSE;
629 }
630
631 return TRUE;
632 }
633
634 return TRUE;
635 }
636
637 // --------------------------------------------------------------------
638
639 /**
640 * Validate Upload Path
641 *
642 * Verifies that it is a valid upload path with proper permissions.
643 *
644 *
645 * @access public
646 * @return bool
647 */
648 function validate_upload_path()
649 {
650 if ($this->upload_path == '')
651 {
652 $this->set_error('upload_no_filepath');
653 return FALSE;
654 }
655
656 if (function_exists('realpath') AND @realpath($this->upload_path) !== FALSE)
657 {
658 $this->upload_path = str_replace("\\", "/", realpath($this->upload_path));
659 }
660
Derek Jones0b59f272008-05-13 04:22:33 +0000661 if ( ! @is_dir($this->upload_path))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000662 {
663 $this->set_error('upload_no_filepath');
664 return FALSE;
665 }
666
Derek Jones0b59f272008-05-13 04:22:33 +0000667 if ( ! is_really_writable($this->upload_path))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000668 {
669 $this->set_error('upload_not_writable');
670 return FALSE;
671 }
672
673 $this->upload_path = preg_replace("/(.+?)\/*$/", "\\1/", $this->upload_path);
674 return TRUE;
675 }
676
677 // --------------------------------------------------------------------
678
679 /**
680 * Extract the file extension
681 *
682 * @access public
683 * @param string
684 * @return string
685 */
686 function get_extension($filename)
687 {
688 $x = explode('.', $filename);
689 return '.'.end($x);
690 }
691
692 // --------------------------------------------------------------------
693
694 /**
695 * Clean the file name for security
696 *
697 * @access public
698 * @param string
699 * @return string
700 */
701 function clean_file_name($filename)
702 {
703 $bad = array(
704 "<!--",
705 "-->",
706 "'",
707 "<",
708 ">",
709 '"',
710 '&',
711 '$',
712 '=',
713 ';',
714 '?',
715 '/',
716 "%20",
717 "%22",
718 "%3c", // <
719 "%253c", // <
720 "%3e", // >
721 "%0e", // >
722 "%28", // (
723 "%29", // )
724 "%2528", // (
725 "%26", // &
726 "%24", // $
727 "%3f", // ?
728 "%3b", // ;
729 "%3d" // =
730 );
731
Derek Jonesefb5a0d2008-07-13 21:31:56 +0000732 $filename = str_replace($bad, '', $filename);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000733
Derek Allarda6657432008-01-26 15:26:33 +0000734 return stripslashes($filename);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000735 }
Rick Ellis2f26ba92008-10-04 01:38:01 +0000736
737 // --------------------------------------------------------------------
Derek Allardd2df9bc2007-04-15 17:41:17 +0000738
Rick Ellis2f26ba92008-10-04 01:38:01 +0000739 /**
740 * Limit the File Name Length
741 *
742 * @access public
743 * @param string
744 * @return string
745 */
746 function limit_filename_length($filename, $length)
747 {
748 if (strlen($filename) < $length)
749 {
750 return $filename;
751 }
752
753 $ext = '';
754 if (strpos($filename, '.') !== FALSE)
755 {
756 $parts = explode('.', $filename);
757 $ext = '.'.array_pop($parts);
758 $filename = implode('.', $parts);
759 }
760
761 return substr($filename, 0, ($length - strlen($ext))).$ext;
762 }
763
Derek Allardd2df9bc2007-04-15 17:41:17 +0000764 // --------------------------------------------------------------------
765
766 /**
767 * Runs the file through the XSS clean function
768 *
769 * This prevents people from embedding malicious code in their files.
770 * I'm not sure that it won't negatively affect certain files in unexpected ways,
771 * but so far I haven't found that it causes trouble.
772 *
773 * @access public
774 * @return void
775 */
776 function do_xss_clean()
777 {
778 $file = $this->upload_path.$this->file_name;
779
780 if (filesize($file) == 0)
781 {
782 return FALSE;
783 }
Rick Ellis63966df2007-06-11 04:44:11 +0000784
paulburdick3c5e3732007-06-24 20:27:42 +0000785 if (($data = @file_get_contents($file)) === FALSE)
Rick Ellis64bbd042007-06-11 04:35:52 +0000786 {
787 return FALSE;
788 }
789
Derek Jones0b59f272008-05-13 04:22:33 +0000790 if ( ! $fp = @fopen($file, FOPEN_READ_WRITE))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000791 {
792 return FALSE;
793 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000794
Derek Allardd2df9bc2007-04-15 17:41:17 +0000795 $CI =& get_instance();
796 $data = $CI->input->xss_clean($data);
Rick Ellis64bbd042007-06-11 04:35:52 +0000797
798 flock($fp, LOCK_EX);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000799 fwrite($fp, $data);
800 flock($fp, LOCK_UN);
801 fclose($fp);
802 }
803
804 // --------------------------------------------------------------------
805
806 /**
807 * Set an error message
808 *
809 * @access public
810 * @param string
811 * @return void
812 */
813 function set_error($msg)
814 {
815 $CI =& get_instance();
816 $CI->lang->load('upload');
817
818 if (is_array($msg))
819 {
820 foreach ($msg as $val)
821 {
822 $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
823 $this->error_msg[] = $msg;
824 log_message('error', $msg);
825 }
826 }
827 else
828 {
829 $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
830 $this->error_msg[] = $msg;
831 log_message('error', $msg);
832 }
833 }
834
835 // --------------------------------------------------------------------
836
837 /**
838 * Display the error message
839 *
840 * @access public
841 * @param string
842 * @param string
843 * @return string
844 */
845 function display_errors($open = '<p>', $close = '</p>')
846 {
847 $str = '';
848 foreach ($this->error_msg as $val)
849 {
850 $str .= $open.$val.$close;
851 }
852
853 return $str;
854 }
855
856 // --------------------------------------------------------------------
857
858 /**
859 * List of Mime Types
860 *
861 * This is a list of mime types. We use it to validate
862 * the "allowed types" set by the developer
863 *
864 * @access public
865 * @param string
866 * @return string
867 */
868 function mimes_types($mime)
869 {
Derek Allardd9d379c2008-05-14 21:26:35 +0000870 global $mimes;
871
Derek Allardd2df9bc2007-04-15 17:41:17 +0000872 if (count($this->mimes) == 0)
873 {
Derek Allardd9d379c2008-05-14 21:26:35 +0000874 if (@require_once(APPPATH.'config/mimes'.EXT))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000875 {
876 $this->mimes = $mimes;
877 unset($mimes);
878 }
879 }
880
Derek Jones0b59f272008-05-13 04:22:33 +0000881 return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime];
Derek Allardd2df9bc2007-04-15 17:41:17 +0000882 }
883
Rick Ellis2f26ba92008-10-04 01:38:01 +0000884 // --------------------------------------------------------------------
885
Derek Jones6ef8b692008-03-17 19:09:12 +0000886 /**
887 * Prep Filename
888 *
889 * Prevents possible script execution from Apache's handling of files multiple extensions
Derek Allard993925b2008-08-21 12:43:31 +0000890 * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
Derek Jones6ef8b692008-03-17 19:09:12 +0000891 *
892 * @access private
893 * @param string
894 * @return string
895 */
896 function _prep_filename($filename)
897 {
898 if (strpos($filename, '.') === FALSE)
899 {
900 return $filename;
901 }
902
903 $parts = explode('.', $filename);
904 $ext = array_pop($parts);
905 $filename = array_shift($parts);
906
907 foreach ($parts as $part)
908 {
909 if ($this->mimes_types(strtolower($part)) === FALSE)
910 {
911 $filename .= '.'.$part.'_';
912 }
913 else
914 {
915 $filename .= '.'.$part;
916 }
917 }
918
919 $filename .= '.'.$ext;
920
921 return $filename;
922 }
923
924 // --------------------------------------------------------------------
925
Derek Allardd2df9bc2007-04-15 17:41:17 +0000926}
927// END Upload Class
Derek Jones0b59f272008-05-13 04:22:33 +0000928
929/* End of file Upload.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000930/* Location: ./system/libraries/Upload.php */