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