upgrade to codeigniter 1.7.2 for f12
[www-register-wizard.git] / libraries / Upload.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 4.3.2 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008 - 2009, EllisLab, Inc.
10  * @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  */
27 class CI_Upload {
28         
29         var $max_size           = 0;
30         var $max_width          = 0;
31         var $max_height         = 0;
32         var $max_filename       = 0;
33         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                                                         'max_filename'          => 0,
85                                                         'allowed_types'         => "",
86                                                         'file_temp'                     => "",
87                                                         'file_name'                     => "",
88                                                         'orig_name'                     => "",
89                                                         'file_type'                     => "",
90                                                         'file_size'                     => "",
91                                                         'file_ext'                      => "",
92                                                         'upload_path'           => "",
93                                                         'overwrite'                     => FALSE,
94                                                         'encrypt_name'          => FALSE,
95                                                         'is_image'                      => FALSE,
96                                                         'image_width'           => '',
97                                                         'image_height'          => '',
98                                                         'image_type'            => '',
99                                                         'image_size_str'        => '',
100                                                         'error_msg'                     => array(),
101                                                         'mimes'                         => array(),
102                                                         'remove_spaces'         => TRUE,
103                                                         'xss_clean'                     => FALSE,
104                                                         'temp_prefix'           => "temp_file_"
105                                                 );      
106         
107         
108                 foreach ($defaults as $key => $val)
109                 {
110                         if (isset($config[$key]))
111                         {
112                                 $method = 'set_'.$key;
113                                 if (method_exists($this, $method))
114                                 {
115                                         $this->$method($config[$key]);
116                                 }
117                                 else
118                                 {
119                                         $this->$key = $config[$key];
120                                 }                       
121                         }
122                         else
123                         {
124                                 $this->$key = $val;
125                         }
126                 }
127         }
128         
129         // --------------------------------------------------------------------
130         
131         /**
132          * Perform the file upload
133          *
134          * @access      public
135          * @return      bool
136          */     
137         function do_upload($field = 'userfile')
138         {
139                 // Is $_FILES[$field] set? If not, no reason to continue.
140                 if ( ! isset($_FILES[$field]))
141                 {
142                         $this->set_error('upload_no_file_selected');
143                         return FALSE;
144                 }
145                 
146                 // Is the upload path valid?
147                 if ( ! $this->validate_upload_path())
148                 {
149                         // errors will already be set by validate_upload_path() so just return FALSE
150                         return FALSE;
151                 }
152
153                 // Was the file able to be uploaded? If not, determine the reason why.
154                 if ( ! is_uploaded_file($_FILES[$field]['tmp_name']))
155                 {
156                         $error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];
157
158                         switch($error)
159                         {
160                                 case 1: // UPLOAD_ERR_INI_SIZE
161                                         $this->set_error('upload_file_exceeds_limit');
162                                         break;
163                                 case 2: // UPLOAD_ERR_FORM_SIZE
164                                         $this->set_error('upload_file_exceeds_form_limit');
165                                         break;
166                                 case 3: // UPLOAD_ERR_PARTIAL
167                                    $this->set_error('upload_file_partial');
168                                         break;
169                                 case 4: // UPLOAD_ERR_NO_FILE
170                                    $this->set_error('upload_no_file_selected');
171                                         break;
172                                 case 6: // UPLOAD_ERR_NO_TMP_DIR
173                                         $this->set_error('upload_no_temp_directory');
174                                         break;
175                                 case 7: // UPLOAD_ERR_CANT_WRITE
176                                         $this->set_error('upload_unable_to_write_file');
177                                         break;
178                                 case 8: // UPLOAD_ERR_EXTENSION
179                                         $this->set_error('upload_stopped_by_extension');
180                                         break;
181                                 default :   $this->set_error('upload_no_file_selected');
182                                         break;
183                         }
184
185                         return FALSE;
186                 }
187
188                 // Set the uploaded data as class variables
189                 $this->file_temp = $_FILES[$field]['tmp_name'];         
190                 $this->file_name = $this->_prep_filename($_FILES[$field]['name']);
191                 $this->file_size = $_FILES[$field]['size'];             
192                 $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
193                 $this->file_type = strtolower($this->file_type);
194                 $this->file_ext  = $this->get_extension($_FILES[$field]['name']);
195                 
196                 // Convert the file size to kilobytes
197                 if ($this->file_size > 0)
198                 {
199                         $this->file_size = round($this->file_size/1024, 2);
200                 }
201
202                 // Is the file type allowed to be uploaded?
203                 if ( ! $this->is_allowed_filetype())
204                 {
205                         $this->set_error('upload_invalid_filetype');
206                         return FALSE;
207                 }
208
209                 // Is the file size within the allowed maximum?
210                 if ( ! $this->is_allowed_filesize())
211                 {
212                         $this->set_error('upload_invalid_filesize');
213                         return FALSE;
214                 }
215
216                 // Are the image dimensions within the allowed size?
217                 // Note: This can fail if the server has an open_basdir restriction.
218                 if ( ! $this->is_allowed_dimensions())
219                 {
220                         $this->set_error('upload_invalid_dimensions');
221                         return FALSE;
222                 }
223
224                 // Sanitize the file name for security
225                 $this->file_name = $this->clean_file_name($this->file_name);
226                 
227                 // Truncate the file name if it's too long
228                 if ($this->max_filename > 0)
229                 {
230                         $this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);
231                 }
232
233                 // Remove white spaces in the name
234                 if ($this->remove_spaces == TRUE)
235                 {
236                         $this->file_name = preg_replace("/\s+/", "_", $this->file_name);
237                 }
238
239                 /*
240                  * Validate the file name
241                  * This function appends an number onto the end of
242                  * the file if one with the same name already exists.
243                  * If it returns false there was a problem.
244                  */
245                 $this->orig_name = $this->file_name;
246
247                 if ($this->overwrite == FALSE)
248                 {
249                         $this->file_name = $this->set_filename($this->upload_path, $this->file_name);
250                         
251                         if ($this->file_name === FALSE)
252                         {
253                                 return FALSE;
254                         }
255                 }
256
257                 /*
258                  * Move the file to the final destination
259                  * To deal with different server configurations
260                  * we'll attempt to use copy() first.  If that fails
261                  * we'll use move_uploaded_file().  One of the two should
262                  * reliably work in most environments
263                  */
264                 if ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))
265                 {
266                         if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))
267                         {
268                                  $this->set_error('upload_destination_error');
269                                  return FALSE;
270                         }
271                 }
272                 
273                 /*
274                  * Run the file through the XSS hacking filter
275                  * This helps prevent malicious code from being
276                  * embedded within a file.  Scripts can easily
277                  * be disguised as images or other file types.
278                  */
279                 if ($this->xss_clean == TRUE)
280                 {
281                         $this->do_xss_clean();
282                 }
283
284                 /*
285                  * Set the finalized image dimensions
286                  * This sets the image width/height (assuming the
287                  * file was an image).  We use this information
288                  * in the "data" function.
289                  */
290                 $this->set_image_properties($this->upload_path.$this->file_name);
291
292                 return TRUE;
293         }
294         
295         // --------------------------------------------------------------------
296         
297         /**
298          * Finalized Data Array
299          *      
300          * Returns an associative array containing all of the information
301          * related to the upload, allowing the developer easy access in one array.
302          *
303          * @access      public
304          * @return      array
305          */     
306         function data()
307         {
308                 return array (
309                                                 'file_name'                     => $this->file_name,
310                                                 'file_type'                     => $this->file_type,
311                                                 'file_path'                     => $this->upload_path,
312                                                 'full_path'                     => $this->upload_path.$this->file_name,
313                                                 'raw_name'                      => str_replace($this->file_ext, '', $this->file_name),
314                                                 'orig_name'                     => $this->orig_name,
315                                                 'file_ext'                      => $this->file_ext,
316                                                 'file_size'                     => $this->file_size,
317                                                 'is_image'                      => $this->is_image(),
318                                                 'image_width'           => $this->image_width,
319                                                 'image_height'          => $this->image_height,
320                                                 'image_type'            => $this->image_type,
321                                                 'image_size_str'        => $this->image_size_str,
322                                         );
323         }
324         
325         // --------------------------------------------------------------------
326         
327         /**
328          * Set Upload Path
329          *
330          * @access      public
331          * @param       string
332          * @return      void
333          */     
334         function set_upload_path($path)
335         {
336                 // Make sure it has a trailing slash
337                 $this->upload_path = rtrim($path, '/').'/';
338         }
339         
340         // --------------------------------------------------------------------
341         
342         /**
343          * Set the file name
344          *
345          * This function takes a filename/path as input and looks for the
346          * existence of a file with the same name. If found, it will append a
347          * number to the end of the filename to avoid overwriting a pre-existing file.
348          *
349          * @access      public
350          * @param       string
351          * @param       string
352          * @return      string
353          */     
354         function set_filename($path, $filename)
355         {
356                 if ($this->encrypt_name == TRUE)
357                 {               
358                         mt_srand();
359                         $filename = md5(uniqid(mt_rand())).$this->file_ext;     
360                 }
361         
362                 if ( ! file_exists($path.$filename))
363                 {
364                         return $filename;
365                 }
366         
367                 $filename = str_replace($this->file_ext, '', $filename);
368                 
369                 $new_filename = '';
370                 for ($i = 1; $i < 100; $i++)
371                 {                       
372                         if ( ! file_exists($path.$filename.$i.$this->file_ext))
373                         {
374                                 $new_filename = $filename.$i.$this->file_ext;
375                                 break;
376                         }
377                 }
378
379                 if ($new_filename == '')
380                 {
381                         $this->set_error('upload_bad_filename');
382                         return FALSE;
383                 }
384                 else
385                 {
386                         return $new_filename;
387                 }
388         }
389         
390         // --------------------------------------------------------------------
391         
392         /**
393          * Set Maximum File Size
394          *
395          * @access      public
396          * @param       integer
397          * @return      void
398          */     
399         function set_max_filesize($n)
400         {
401                 $this->max_size = ((int) $n < 0) ? 0: (int) $n;
402         }
403         
404         // --------------------------------------------------------------------
405         
406         /**
407          * Set Maximum File Name Length
408          *
409          * @access      public
410          * @param       integer
411          * @return      void
412          */     
413         function set_max_filename($n)
414         {
415                 $this->max_filename = ((int) $n < 0) ? 0: (int) $n;
416         }
417
418         // --------------------------------------------------------------------
419         
420         /**
421          * Set Maximum Image Width
422          *
423          * @access      public
424          * @param       integer
425          * @return      void
426          */     
427         function set_max_width($n)
428         {
429                 $this->max_width = ((int) $n < 0) ? 0: (int) $n;
430         }
431         
432         // --------------------------------------------------------------------
433         
434         /**
435          * Set Maximum Image Height
436          *
437          * @access      public
438          * @param       integer
439          * @return      void
440          */     
441         function set_max_height($n)
442         {
443                 $this->max_height = ((int) $n < 0) ? 0: (int) $n;
444         }
445         
446         // --------------------------------------------------------------------
447         
448         /**
449          * Set Allowed File Types
450          *
451          * @access      public
452          * @param       string
453          * @return      void
454          */     
455         function set_allowed_types($types)
456         {
457                 $this->allowed_types = explode('|', $types);
458         }
459         
460         // --------------------------------------------------------------------
461         
462         /**
463          * Set Image Properties
464          *
465          * Uses GD to determine the width/height/type of image
466          *
467          * @access      public
468          * @param       string
469          * @return      void
470          */     
471         function set_image_properties($path = '')
472         {
473                 if ( ! $this->is_image())
474                 {
475                         return;
476                 }
477
478                 if (function_exists('getimagesize'))
479                 {
480                         if (FALSE !== ($D = @getimagesize($path)))
481                         {       
482                                 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
483
484                                 $this->image_width              = $D['0'];
485                                 $this->image_height             = $D['1'];
486                                 $this->image_type               = ( ! isset($types[$D['2']])) ? 'unknown' : $types[$D['2']];
487                                 $this->image_size_str   = $D['3'];  // string containing height and width
488                         }
489                 }
490         }
491         
492         // --------------------------------------------------------------------
493         
494         /**
495          * Set XSS Clean
496          *
497          * Enables the XSS flag so that the file that was uploaded
498          * will be run through the XSS filter.
499          *
500          * @access      public
501          * @param       bool
502          * @return      void
503          */
504         function set_xss_clean($flag = FALSE)
505         {
506                 $this->xss_clean = ($flag == TRUE) ? TRUE : FALSE;
507         }
508         
509         // --------------------------------------------------------------------
510         
511         /**
512          * Validate the image
513          *
514          * @access      public
515          * @return      bool
516          */     
517         function is_image()
518         {
519                 // IE will sometimes return odd mime-types during upload, so here we just standardize all
520                 // jpegs or pngs to the same file type.
521
522                 $png_mimes  = array('image/x-png');
523                 $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');
524                 
525                 if (in_array($this->file_type, $png_mimes))
526                 {
527                         $this->file_type = 'image/png';
528                 }
529                 
530                 if (in_array($this->file_type, $jpeg_mimes))
531                 {
532                         $this->file_type = 'image/jpeg';
533                 }
534
535                 $img_mimes = array(
536                                                         'image/gif',
537                                                         'image/jpeg',
538                                                         'image/png',
539                                                    );
540
541                 return (in_array($this->file_type, $img_mimes, TRUE)) ? TRUE : FALSE;
542         }
543         
544         // --------------------------------------------------------------------
545         
546         /**
547          * Verify that the filetype is allowed
548          *
549          * @access      public
550          * @return      bool
551          */     
552         function is_allowed_filetype()
553         {
554                 if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types))
555                 {
556                         $this->set_error('upload_no_file_types');
557                         return FALSE;
558                 }
559
560                 $image_types = array('gif', 'jpg', 'jpeg', 'png', 'jpe');
561
562                 foreach ($this->allowed_types as $val)
563                 {
564                         $mime = $this->mimes_types(strtolower($val));
565
566                         // Images get some additional checks
567                         if (in_array($val, $image_types))
568                         {
569                                 if (getimagesize($this->file_temp) === FALSE)
570                                 {
571                                         return FALSE;
572                                 }
573                         }
574
575                         if (is_array($mime))
576                         {
577                                 if (in_array($this->file_type, $mime, TRUE))
578                                 {
579                                         return TRUE;
580                                 }
581                         }
582                         else
583                         {
584                                 if ($mime == $this->file_type)
585                                 {
586                                         return TRUE;
587                                 }       
588                         }               
589                 }
590                 
591                 return FALSE;
592         }
593         
594         // --------------------------------------------------------------------
595         
596         /**
597          * Verify that the file is within the allowed size
598          *
599          * @access      public
600          * @return      bool
601          */     
602         function is_allowed_filesize()
603         {
604                 if ($this->max_size != 0  AND  $this->file_size > $this->max_size)
605                 {
606                         return FALSE;
607                 }
608                 else
609                 {
610                         return TRUE;
611                 }
612         }
613         
614         // --------------------------------------------------------------------
615         
616         /**
617          * Verify that the image is within the allowed width/height
618          *
619          * @access      public
620          * @return      bool
621          */     
622         function is_allowed_dimensions()
623         {
624                 if ( ! $this->is_image())
625                 {
626                         return TRUE;
627                 }
628
629                 if (function_exists('getimagesize'))
630                 {
631                         $D = @getimagesize($this->file_temp);
632
633                         if ($this->max_width > 0 AND $D['0'] > $this->max_width)
634                         {
635                                 return FALSE;
636                         }
637
638                         if ($this->max_height > 0 AND $D['1'] > $this->max_height)
639                         {
640                                 return FALSE;
641                         }
642
643                         return TRUE;
644                 }
645
646                 return TRUE;
647         }
648         
649         // --------------------------------------------------------------------
650         
651         /**
652          * Validate Upload Path
653          *
654          * Verifies that it is a valid upload path with proper permissions.
655          *
656          *
657          * @access      public
658          * @return      bool
659          */     
660         function validate_upload_path()
661         {
662                 if ($this->upload_path == '')
663                 {
664                         $this->set_error('upload_no_filepath');
665                         return FALSE;
666                 }
667                 
668                 if (function_exists('realpath') AND @realpath($this->upload_path) !== FALSE)
669                 {
670                         $this->upload_path = str_replace("\\", "/", realpath($this->upload_path));
671                 }
672
673                 if ( ! @is_dir($this->upload_path))
674                 {
675                         $this->set_error('upload_no_filepath');
676                         return FALSE;
677                 }
678
679                 if ( ! is_really_writable($this->upload_path))
680                 {
681                         $this->set_error('upload_not_writable');
682                         return FALSE;
683                 }
684
685                 $this->upload_path = preg_replace("/(.+?)\/*$/", "\\1/",  $this->upload_path);
686                 return TRUE;
687         }
688         
689         // --------------------------------------------------------------------
690         
691         /**
692          * Extract the file extension
693          *
694          * @access      public
695          * @param       string
696          * @return      string
697          */     
698         function get_extension($filename)
699         {
700                 $x = explode('.', $filename);
701                 return '.'.end($x);
702         }       
703         
704         // --------------------------------------------------------------------
705         
706         /**
707          * Clean the file name for security
708          *
709          * @access      public
710          * @param       string
711          * @return      string
712          */             
713         function clean_file_name($filename)
714         {
715                 $bad = array(
716                                                 "<!--",
717                                                 "-->",
718                                                 "'",
719                                                 "<",
720                                                 ">",
721                                                 '"',
722                                                 '&',
723                                                 '$',
724                                                 '=',
725                                                 ';',
726                                                 '?',
727                                                 '/',
728                                                 "%20",
729                                                 "%22",
730                                                 "%3c",          // <
731                                                 "%253c",        // <
732                                                 "%3e",          // >
733                                                 "%0e",          // >
734                                                 "%28",          // (
735                                                 "%29",          // )
736                                                 "%2528",        // (
737                                                 "%26",          // &
738                                                 "%24",          // $
739                                                 "%3f",          // ?
740                                                 "%3b",          // ;
741                                                 "%3d"           // =
742                                         );
743                                         
744                 $filename = str_replace($bad, '', $filename);
745
746                 return stripslashes($filename);
747         }
748
749         // --------------------------------------------------------------------
750         
751         /**
752          * Limit the File Name Length
753          *
754          * @access      public
755          * @param       string
756          * @return      string
757          */             
758         function limit_filename_length($filename, $length)
759         {
760                 if (strlen($filename) < $length)
761                 {
762                         return $filename;
763                 }
764         
765                 $ext = '';
766                 if (strpos($filename, '.') !== FALSE)
767                 {
768                         $parts          = explode('.', $filename);
769                         $ext            = '.'.array_pop($parts);
770                         $filename       = implode('.', $parts);
771                 }
772         
773                 return substr($filename, 0, ($length - strlen($ext))).$ext;
774         }
775
776         // --------------------------------------------------------------------
777         
778         /**
779          * Runs the file through the XSS clean function
780          *
781          * This prevents people from embedding malicious code in their files.
782          * I'm not sure that it won't negatively affect certain files in unexpected ways,
783          * but so far I haven't found that it causes trouble.
784          *
785          * @access      public
786          * @return      void
787          */     
788         function do_xss_clean()
789         {               
790                 $file = $this->upload_path.$this->file_name;
791                 
792                 if (filesize($file) == 0)
793                 {
794                         return FALSE;
795                 }
796
797                 if (($data = @file_get_contents($file)) === FALSE)
798                 {
799                         return FALSE;
800                 }
801                 
802                 if ( ! $fp = @fopen($file, FOPEN_READ_WRITE))
803                 {
804                         return FALSE;
805                 }
806
807                 $CI =& get_instance();  
808                 $data = $CI->input->xss_clean($data);
809                 
810                 flock($fp, LOCK_EX);
811                 fwrite($fp, $data);
812                 flock($fp, LOCK_UN);
813                 fclose($fp);
814         }
815         
816         // --------------------------------------------------------------------
817         
818         /**
819          * Set an error message
820          *
821          * @access      public
822          * @param       string
823          * @return      void
824          */     
825         function set_error($msg)
826         {
827                 $CI =& get_instance();  
828                 $CI->lang->load('upload');
829                 
830                 if (is_array($msg))
831                 {
832                         foreach ($msg as $val)
833                         {
834                                 $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);                         
835                                 $this->error_msg[] = $msg;
836                                 log_message('error', $msg);
837                         }               
838                 }
839                 else
840                 {
841                         $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
842                         $this->error_msg[] = $msg;
843                         log_message('error', $msg);
844                 }
845         }
846         
847         // --------------------------------------------------------------------
848         
849         /**
850          * Display the error message
851          *
852          * @access      public
853          * @param       string
854          * @param       string
855          * @return      string
856          */     
857         function display_errors($open = '<p>', $close = '</p>')
858         {
859                 $str = '';
860                 foreach ($this->error_msg as $val)
861                 {
862                         $str .= $open.$val.$close;
863                 }
864         
865                 return $str;
866         }
867         
868         // --------------------------------------------------------------------
869         
870         /**
871          * List of Mime Types
872          *
873          * This is a list of mime types.  We use it to validate
874          * the "allowed types" set by the developer
875          *
876          * @access      public
877          * @param       string
878          * @return      string
879          */     
880         function mimes_types($mime)
881         {
882                 global $mimes;
883         
884                 if (count($this->mimes) == 0)
885                 {
886                         if (@require_once(APPPATH.'config/mimes'.EXT))
887                         {
888                                 $this->mimes = $mimes;
889                                 unset($mimes);
890                         }
891                 }
892         
893                 return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime];
894         }
895
896         // --------------------------------------------------------------------
897         
898         /**
899          * Prep Filename
900          *
901          * Prevents possible script execution from Apache's handling of files multiple extensions
902          * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
903          *
904          * @access      private
905          * @param       string
906          * @return      string
907          */
908         function _prep_filename($filename)
909         {
910                 if (strpos($filename, '.') === FALSE)
911                 {
912                         return $filename;
913                 }
914
915                 $parts          = explode('.', $filename);
916                 $ext            = array_pop($parts);
917                 $filename       = array_shift($parts);
918
919                 foreach ($parts as $part)
920                 {
921                         if ($this->mimes_types(strtolower($part)) === FALSE)
922                         {
923                                 $filename .= '.'.$part.'_';
924                         }
925                         else
926                         {
927                                 $filename .= '.'.$part;
928                         }
929                 }
930
931                 // file name override, since the exact name is provided, no need to
932                 // run it through a $this->mimes check.
933                 if ($this->file_name != '')
934                 {
935                         $filename = $this->file_name;
936                 }
937
938                 $filename .= '.'.$ext;
939                 
940                 return $filename;
941         }
942
943         // --------------------------------------------------------------------
944
945 }
946 // END Upload Class
947
948 /* End of file Upload.php */
949 /* Location: ./system/libraries/Upload.php */