converted to unix-style eol
[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, 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                 foreach ($this->allowed_types as $val)
561                 {
562                         $mime = $this->mimes_types(strtolower($val));
563                 
564                         if (is_array($mime))
565                         {
566                                 if (in_array($this->file_type, $mime, TRUE))
567                                 {
568                                         return TRUE;
569                                 }
570                         }
571                         else
572                         {
573                                 if ($mime == $this->file_type)
574                                 {
575                                         return TRUE;
576                                 }       
577                         }               
578                 }
579                 
580                 return FALSE;
581         }
582         
583         // --------------------------------------------------------------------
584         
585         /**
586          * Verify that the file is within the allowed size
587          *
588          * @access      public
589          * @return      bool
590          */     
591         function is_allowed_filesize()
592         {
593                 if ($this->max_size != 0  AND  $this->file_size > $this->max_size)
594                 {
595                         return FALSE;
596                 }
597                 else
598                 {
599                         return TRUE;
600                 }
601         }
602         
603         // --------------------------------------------------------------------
604         
605         /**
606          * Verify that the image is within the allowed width/height
607          *
608          * @access      public
609          * @return      bool
610          */     
611         function is_allowed_dimensions()
612         {
613                 if ( ! $this->is_image())
614                 {
615                         return TRUE;
616                 }
617
618                 if (function_exists('getimagesize'))
619                 {
620                         $D = @getimagesize($this->file_temp);
621
622                         if ($this->max_width > 0 AND $D['0'] > $this->max_width)
623                         {
624                                 return FALSE;
625                         }
626
627                         if ($this->max_height > 0 AND $D['1'] > $this->max_height)
628                         {
629                                 return FALSE;
630                         }
631
632                         return TRUE;
633                 }
634
635                 return TRUE;
636         }
637         
638         // --------------------------------------------------------------------
639         
640         /**
641          * Validate Upload Path
642          *
643          * Verifies that it is a valid upload path with proper permissions.
644          *
645          *
646          * @access      public
647          * @return      bool
648          */     
649         function validate_upload_path()
650         {
651                 if ($this->upload_path == '')
652                 {
653                         $this->set_error('upload_no_filepath');
654                         return FALSE;
655                 }
656                 
657                 if (function_exists('realpath') AND @realpath($this->upload_path) !== FALSE)
658                 {
659                         $this->upload_path = str_replace("\\", "/", realpath($this->upload_path));
660                 }
661
662                 if ( ! @is_dir($this->upload_path))
663                 {
664                         $this->set_error('upload_no_filepath');
665                         return FALSE;
666                 }
667
668                 if ( ! is_really_writable($this->upload_path))
669                 {
670                         $this->set_error('upload_not_writable');
671                         return FALSE;
672                 }
673
674                 $this->upload_path = preg_replace("/(.+?)\/*$/", "\\1/",  $this->upload_path);
675                 return TRUE;
676         }
677         
678         // --------------------------------------------------------------------
679         
680         /**
681          * Extract the file extension
682          *
683          * @access      public
684          * @param       string
685          * @return      string
686          */     
687         function get_extension($filename)
688         {
689                 $x = explode('.', $filename);
690                 return '.'.end($x);
691         }       
692         
693         // --------------------------------------------------------------------
694         
695         /**
696          * Clean the file name for security
697          *
698          * @access      public
699          * @param       string
700          * @return      string
701          */             
702         function clean_file_name($filename)
703         {
704                 $bad = array(
705                                                 "<!--",
706                                                 "-->",
707                                                 "'",
708                                                 "<",
709                                                 ">",
710                                                 '"',
711                                                 '&',
712                                                 '$',
713                                                 '=',
714                                                 ';',
715                                                 '?',
716                                                 '/',
717                                                 "%20",
718                                                 "%22",
719                                                 "%3c",          // <
720                                                 "%253c",        // <
721                                                 "%3e",          // >
722                                                 "%0e",          // >
723                                                 "%28",          // (
724                                                 "%29",          // )
725                                                 "%2528",        // (
726                                                 "%26",          // &
727                                                 "%24",          // $
728                                                 "%3f",          // ?
729                                                 "%3b",          // ;
730                                                 "%3d"           // =
731                                         );
732                                         
733                 $filename = str_replace($bad, '', $filename);
734
735                 return stripslashes($filename);
736         }
737
738         // --------------------------------------------------------------------
739         
740         /**
741          * Limit the File Name Length
742          *
743          * @access      public
744          * @param       string
745          * @return      string
746          */             
747         function limit_filename_length($filename, $length)
748         {
749                 if (strlen($filename) < $length)
750                 {
751                         return $filename;
752                 }
753         
754                 $ext = '';
755                 if (strpos($filename, '.') !== FALSE)
756                 {
757                         $parts          = explode('.', $filename);
758                         $ext            = '.'.array_pop($parts);
759                         $filename       = implode('.', $parts);
760                 }
761         
762                 return substr($filename, 0, ($length - strlen($ext))).$ext;
763         }
764
765         // --------------------------------------------------------------------
766         
767         /**
768          * Runs the file through the XSS clean function
769          *
770          * This prevents people from embedding malicious code in their files.
771          * I'm not sure that it won't negatively affect certain files in unexpected ways,
772          * but so far I haven't found that it causes trouble.
773          *
774          * @access      public
775          * @return      void
776          */     
777         function do_xss_clean()
778         {               
779                 $file = $this->upload_path.$this->file_name;
780                 
781                 if (filesize($file) == 0)
782                 {
783                         return FALSE;
784                 }
785
786                 if (($data = @file_get_contents($file)) === FALSE)
787                 {
788                         return FALSE;
789                 }
790                 
791                 if ( ! $fp = @fopen($file, FOPEN_READ_WRITE))
792                 {
793                         return FALSE;
794                 }
795
796                 $CI =& get_instance();  
797                 $data = $CI->input->xss_clean($data);
798                 
799                 flock($fp, LOCK_EX);
800                 fwrite($fp, $data);
801                 flock($fp, LOCK_UN);
802                 fclose($fp);
803         }
804         
805         // --------------------------------------------------------------------
806         
807         /**
808          * Set an error message
809          *
810          * @access      public
811          * @param       string
812          * @return      void
813          */     
814         function set_error($msg)
815         {
816                 $CI =& get_instance();  
817                 $CI->lang->load('upload');
818                 
819                 if (is_array($msg))
820                 {
821                         foreach ($msg as $val)
822                         {
823                                 $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);                         
824                                 $this->error_msg[] = $msg;
825                                 log_message('error', $msg);
826                         }               
827                 }
828                 else
829                 {
830                         $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
831                         $this->error_msg[] = $msg;
832                         log_message('error', $msg);
833                 }
834         }
835         
836         // --------------------------------------------------------------------
837         
838         /**
839          * Display the error message
840          *
841          * @access      public
842          * @param       string
843          * @param       string
844          * @return      string
845          */     
846         function display_errors($open = '<p>', $close = '</p>')
847         {
848                 $str = '';
849                 foreach ($this->error_msg as $val)
850                 {
851                         $str .= $open.$val.$close;
852                 }
853         
854                 return $str;
855         }
856         
857         // --------------------------------------------------------------------
858         
859         /**
860          * List of Mime Types
861          *
862          * This is a list of mime types.  We use it to validate
863          * the "allowed types" set by the developer
864          *
865          * @access      public
866          * @param       string
867          * @return      string
868          */     
869         function mimes_types($mime)
870         {
871                 global $mimes;
872         
873                 if (count($this->mimes) == 0)
874                 {
875                         if (@require_once(APPPATH.'config/mimes'.EXT))
876                         {
877                                 $this->mimes = $mimes;
878                                 unset($mimes);
879                         }
880                 }
881         
882                 return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime];
883         }
884
885         // --------------------------------------------------------------------
886         
887         /**
888          * Prep Filename
889          *
890          * Prevents possible script execution from Apache's handling of files multiple extensions
891          * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
892          *
893          * @access      private
894          * @param       string
895          * @return      string
896          */
897         function _prep_filename($filename)
898         {
899                 if (strpos($filename, '.') === FALSE)
900                 {
901                         return $filename;
902                 }
903                 
904                 $parts          = explode('.', $filename);
905                 $ext            = array_pop($parts);
906                 $filename       = array_shift($parts);
907                                 
908                 foreach ($parts as $part)
909                 {
910                         if ($this->mimes_types(strtolower($part)) === FALSE)
911                         {
912                                 $filename .= '.'.$part.'_';
913                         }
914                         else
915                         {
916                                 $filename .= '.'.$part;
917                         }
918                 }
919                 
920                 $filename .= '.'.$ext;
921                 
922                 return $filename;
923         }
924
925         // --------------------------------------------------------------------
926
927 }
928 // END Upload Class
929
930 /* End of file Upload.php */
931 /* Location: ./system/libraries/Upload.php */