Posted By

cristianogois on 03/05/11


Tagged

php upload swfupload swfu


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

tux-world


Upload Class


 / Published in: PHP
 

URL: www.cristianogois.com.br

This class has the purpose of ease and secure the upload of files for SWFUpload and other applications.

  1. <?php
  2.  
  3. /**
  4.  *
  5.  * Class Upload
  6.  *
  7.  * This class has the purpose of ease and secure the upload of files for SWFUpload and other applications.
  8.  *
  9.  * This script is based on the upload_save.php code of SWFUpload widget
  10.  *
  11.  * @author Cristiano Gois <[email protected]>
  12.  * @version 1.8
  13.  * @copyright Freeware
  14.  * @package Upload
  15.  * @since 03/2011
  16. **/
  17.  
  18. class Upload{
  19.  
  20. private $file_name;
  21.  
  22. private $tmp_name;
  23.  
  24. private $file_extension;
  25.  
  26. private $succeed_files_track;
  27.  
  28. private $fail_files_track;
  29.  
  30. private $max_file_size_in_bytes;
  31.  
  32. private $save_path;
  33.  
  34. private $upload_name;
  35.  
  36. private $file_perm;
  37.  
  38. private $valid_chars_regex;
  39.  
  40. private $extension_whitelist;
  41.  
  42. private $errors;
  43.  
  44. private $errtype; // returning type of method formatErrorMsg. // 0: String; 1: JSON
  45.  
  46. const MAX_FILENAME_LENGTH = 260;
  47.  
  48.  
  49. /**
  50.   * Constructor
  51.   *
  52.   * @access public
  53.   **/
  54. public function __construct($filename="", $save_path="./", $file_ext="", $upload_name="Filedata"){
  55.  
  56. $path_info = pathinfo($_FILES[$upload_name]['name']);
  57.  
  58. $this->file_name = ((!isset($filename) || trim($filename)==='')) ?
  59. basename($_FILES[$upload_name]['name'], '.'.$path_info["extension"]) : $filename;
  60. $this->tmp_name = $_FILES[$upload_name]["tmp_name"];
  61. $this->file_extension = (empty($file_ext)) ? $path_info["extension"] : $file_ext;
  62. $this->succeed_files_track = array();
  63. $this->fail_files_track = array();
  64. $this->save_path = $save_path;
  65. $this->upload_name = $upload_name;
  66. $this->file_perm = 0755; // don't use single quotes or double quotes
  67. $this->max_file_size_in_bytes = 10485760; // 10MB in bytes
  68. $this->valid_chars_regex = '.A-Z0-9_ !@#$%^&()+={}\[\]\',~`-'; // Characters allowed in the file name (in a Regular Expression format)
  69. $this->extension_whitelist = array("jpg", "png", "jpeg", "pdf"); // Allowed file extensions
  70. $this->errors = array( 0=>"There is no error, the file uploaded with success",
  71. 1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini",
  72. 2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
  73. 3=>"The uploaded file was only partially uploaded",
  74. 4=>"No file was uploaded",
  75. 6=>"Missing a temporary folder"
  76. );
  77. $this->errtype = 0; // 0: String; 1: JSON
  78. }
  79. // override magic method to retrieve properties
  80. public function __get($field){
  81. if($field == 'filename'){
  82. return $this->file_name;
  83. }else if($field == 'fullname'){
  84. return $this->file_name.".".$this->file_extension;
  85. }else{
  86. return $this->$field;
  87. }
  88. }
  89. // override magic method to set properties
  90. public function __set($field, $value){
  91. $this->$field = $value;
  92. }
  93.  
  94. public function getPostMaxSize(){
  95. return trim(ini_get('post_max_size'));
  96. }
  97.  
  98. /*
  99.   * Create directory structure
  100.   */
  101.  
  102. public function createDirectoryStructure(){
  103. $path = $this->save_path;
  104.  
  105. return is_dir($path) || @mkdir($path, (int)$this->file_perm, TRUE);
  106. }
  107.  
  108.  
  109. /*
  110.   * Save file
  111.   * uses createDiretoryStructure(), getPostMaxSize()
  112.   * @todo rearrange the conditionals to avoid the 'return $bool' repetition
  113.   */
  114.  
  115. public function save($force=false, $overwrite=false){
  116. $upload_name = $this->upload_name;
  117. $file_name = $this->file_name;
  118. $file_ext = $this->file_extension;
  119. $save_path = $this->save_path;
  120. $full_name = $this->fullname;
  121. $file_path = $save_path."/".$full_name;
  122. $bool = false;
  123.  
  124. $unit = strtoupper(substr($this->getPostMaxSize(), -1));
  125. $multiplier = ($unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1)));
  126.  
  127. if((int)$_SERVER['CONTENT_LENGTH'] > $multiplier*(int)$this->getPostMaxSize() && $this->getPostMaxSize()) {
  128. // header("HTTP/1.1 500 Internal Server Error"); // This will trigger an uploadError event in SWFUpload
  129. $this->formatErrorMsg(2, "POST exceeded maximum allowed size");
  130. return $bool;
  131. }
  132. // Validate the upload
  133. if(!isset($_FILES[$upload_name])){
  134. print $this->formatErrorMsg (4, "No upload found in \$_FILES for $upload_name");
  135. return $bool;
  136. }else if(isset($_FILES[$upload_name]["error"]) && $_FILES[$upload_name]["error"] != 0){
  137. $this->formatErrorMsg($_FILES[$upload_name]["error"], $this->errors[$_FILES[$upload_name]["error"]]);
  138. return $bool;
  139. }else if(!isset($_FILES[$upload_name]["tmp_name"]) || !@is_uploaded_file($_FILES[$upload_name]["tmp_name"])){
  140. $this->formatErrorMsg(7, "Upload failed is_uploaded_file test");
  141. return $bool;
  142. }else if(!isset($_FILES[$upload_name]['name'])){
  143. $this->formatErrorMsg(8, "File has no name");
  144. return $bool;
  145. }
  146.  
  147. // Validate the file size (Warning: the largest files supported by this code is 2GB)
  148. $file_size = @filesize($_FILES[$upload_name]["tmp_name"]);
  149. if (!$file_size || $file_size > $this->max_file_size_in_bytes) {
  150. //header("HTTP/1.1 500 Internal Server Error");
  151. $this->formatErrorMsg (2, "File exceeds the maximum allowed size");
  152. return $bool;
  153. }
  154.  
  155. if ($file_size <= 0) {
  156. $this->formatErrorMsg(9, "File size outside allowed lower bound");
  157. return $bool;
  158. }
  159.  
  160. // Validate file extension
  161. $is_valid_extension = false;
  162. foreach ($this->extension_whitelist as $extension) {
  163. if (strcasecmp($file_ext, $extension) == 0) {
  164. $is_valid_extension = true;
  165. break;
  166. }
  167. }
  168.  
  169. if (!$is_valid_extension) {
  170. $this->formatErrorMsg(10, "Invalid file extension: $file_ext");
  171. return $bool;
  172. }
  173.  
  174. // Validate file name (for our purposes we'll just remove invalid characters)
  175. $file_name = preg_replace('/[^'.$this->valid_chars_regex.']|\.+$/i', "", $file_name);
  176. if (strlen($file_name) == 0 || strlen($file_name) > self::MAX_FILENAME_LENGTH) {
  177. $this->formatErrorMsg(11, "Invalid file name");
  178. return $bool;
  179. }
  180.  
  181. // Validate that we won't overwrite an existing file
  182. if (file_exists($file_path) && !$overwrite) {
  183. $this->formatErrorMsg (12, "File with this name already exists");
  184. return $bool;
  185. }
  186.  
  187. if($force){
  188. if(!$this->createDirectoryStructure()){
  189. $this->formatErrorMsg (13, "Destination folder does not exist and could not be created");
  190. return $bool;
  191. }
  192. }
  193.  
  194. if(!@move_uploaded_file($_FILES[$upload_name]["tmp_name"], $file_path)){
  195. $this->formatErrorMsg (14, "File could not be saved");
  196. return $bool;
  197. }else{
  198. move_uploaded_file($file_path, "./".$full_name);
  199. $bool = true;
  200. }
  201.  
  202. return $bool;
  203. }
  204.  
  205. /**
  206.   * Error handling
  207.   *
  208.   * @access public
  209.   **/
  210. public function formatErrorMsg($errno, $errstr){
  211.  
  212. if($this->errtype == 0){ //plain text
  213. print $errstr;
  214. }else if($this->errtype == 1){ // JSON Format
  215. print "{ \"errno\": $errno, \"errmsg\": \"$errstr\" }";
  216. }
  217. }
  218.  
  219. /**
  220.   * Deconstructor
  221.   *
  222.   * @access public
  223.   **/
  224. public function __destruct() {}
  225. }
  226.  
  227. ?>

Report this snippet  

You need to login to post a comment.