= 5.3.0 if (!function_exists('array_replace_recursive')) { function array_replace_recursive($array, $array1) { function recurse($array, $array1) { foreach ($array1 as $key => $value) { // create new key in $array, if it is empty or not an array if (!isset($array[ $key ]) || (isset($array[ $key ]) && !is_array($array[ $key ]))) { $array[ $key ] = array(); } // overwrite the value in the base array if (is_array($value)) { $value = recurse($array[ $key ], $value); } $array[ $key ] = $value; } return $array; } // handle the arguments, merge one by one $args = func_get_args(); $array = $args[ 0 ]; if (!is_array($array)) { return $array; } for ($i = 1; $i < count($args); $i++) { if (is_array($args[ $i ])) { $array = recurse($array, $args[ $i ]); } } return $array; } } class ResourceUploadHandler { private $options; function __construct($options = null) { $this->options = array( 'script_url' => $_SERVER[ 'PHP_SELF' ], 'upload_dir' => dirname(__FILE__) . '/files/', 'upload_url' => dirname($_SERVER[ 'PHP_SELF' ]) . '/files/', 'param_name' => 'files', // The php.ini settings upload_max_filesize and post_max_size // take precedence over the following max_file_size setting: 'max_file_size' => null, 'min_file_size' => 1, 'accept_file_types' => '/.+$/i', 'max_number_of_files' => null, 'discard_aborted_uploads' => true, 'image_versions' => array( // Uncomment the following version to restrict the size of // uploaded images. You can also add additional versions with // their own upload directories: /* 'large' => array( 'upload_dir' => dirname(__FILE__).'/files/', 'upload_url' => dirname($_SERVER['PHP_SELF']).'/files/', 'max_width' => 1920, 'max_height' => 1200 ), */ 'thumbnail' => array( 'upload_dir' => dirname(__FILE__) . '/thumbnails/', 'upload_url' => dirname($_SERVER[ 'PHP_SELF' ]) . '/thumbnails/', 'max_width' => 80, 'max_height' => 80 ) ) ); if ($options) { $this->options = array_replace_recursive($this->options, $options); } } private function get_file_object($file_name) { $file_path = $this->options[ 'upload_dir' ] . $file_name; if (is_file($file_path) && $file_name[ 0 ] !== '.') { $file = new stdClass(); $file->name = $file_name; $file->size = filesize($file_path); $file->url = $this->options[ 'upload_url' ] . rawurlencode($file->name); foreach ($this->options[ 'image_versions' ] as $version => $options) { if (is_file($options[ 'upload_dir' ] . $file_name)) { $file->{$version . '_url'} = $options[ 'upload_url' ] . rawurlencode($file->name); } } $file->delete_url = $this->options[ 'script_url' ] . '?file=' . rawurlencode($file->name); $file->delete_type = 'DELETE'; return $file; } return null; } private function get_file_objects() { return array_values(array_filter(array_map( array( $this, 'get_file_object' ), scandir($this->options[ 'upload_dir' ]) ))); } private function create_scaled_image($file_name, $options) { $file_path = $this->options[ 'upload_dir' ] . $file_name; $new_file_path = $options[ 'upload_dir' ] . $file_name; list($img_width, $img_height) = @getimagesize($file_path); if (!$img_width || !$img_height) { return false; } $scale = min( $options[ 'max_width' ] / $img_width, $options[ 'max_height' ] / $img_height ); if ($scale > 1) { $scale = 1; } $new_width = $img_width * $scale; $new_height = $img_height * $scale; $new_img = @imagecreatetruecolor($new_width, $new_height); switch (strtolower(substr(strrchr($file_name, '.'), 1))) { case 'jpg': case 'jpeg': $src_img = @imagecreatefromjpeg($file_path); $write_image = 'imagejpeg'; break; case 'gif': @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); $src_img = @imagecreatefromgif($file_path); $write_image = 'imagegif'; break; case 'png': @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); @imagealphablending($new_img, false); @imagesavealpha($new_img, true); $src_img = @imagecreatefrompng($file_path); $write_image = 'imagepng'; break; default: $src_img = $image_method = null; } $success = $src_img && @imagecopyresampled( $new_img, $src_img, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height ) && $write_image($new_img, $new_file_path); // Free up memory (imagedestroy does not delete files): @imagedestroy($src_img); @imagedestroy($new_img); return $success; } private function has_error($uploaded_file, $file, $error) { if ($error) { return $error; } if (!preg_match($this->options[ 'accept_file_types' ], $file->name)) { return 'acceptFileTypes'; } if ($uploaded_file && is_uploaded_file($uploaded_file)) { $file_size = filesize($uploaded_file); } else { $file_size = $_SERVER[ 'CONTENT_LENGTH' ]; } if ($this->options[ 'max_file_size' ] && ( $file_size > $this->options[ 'max_file_size' ] || $file->size > $this->options[ 'max_file_size' ]) ) { return 'maxFileSize'; } if ($this->options[ 'min_file_size' ] && $file_size < $this->options[ 'min_file_size' ] ) { return 'minFileSize'; } if (is_int($this->options[ 'max_number_of_files' ]) && ( count($this->get_file_objects()) >= $this->options[ 'max_number_of_files' ]) ) { return 'maxNumberOfFiles'; } return $error; } private function handle_file_upload($uploaded_file, $name, $size, $type, $error) { $file = new stdClass(); // Remove path information and dots around the filename, to prevent uploading // into different directories or replacing hidden system files. // Also remove control characters and spaces (\x00..\x20) around the filename: $name = $name == '' ? 'UnknownFile' : $name; $name = str_replace(" ", "_", stripslashes($name)); // basename removes first part of filename like тест_архив.zip (with non-latin characters). Basename of that name will be _архив.zip if ($this->strpos_array($name, array( '/', '\'' )) !== false) { $name = basename($name); } else { $res = strrpos($name, '/'); if ($res !== false) { $name = substr($name, $res + 1); } $res = strrpos($name, '\''); if ($res !== false) { $name = substr($name, $res + 1); } } $file->name = trim($name, ".\x00..\x20"); $file->size = intval($size); $file->type = $type; // error check if($error){ $error = getTextUploadError($error); } $error = $this->has_error($uploaded_file, $file, $error); if (!$error && $file->name) { if (!is_dir(DIR_RESOURCE . $this->options[ 'upload_dir' ])) { $path = ''; $directories = explode('/', str_replace('../', '', $this->options[ 'upload_dir' ])); foreach ($directories as $directory) { $path = $path . '/' . $directory; if (!is_dir(DIR_RESOURCE . $path)) { @mkdir(DIR_RESOURCE . $path, 0777); chmod(DIR_RESOURCE . $path, 0777); } } } if (!is_dir(DIR_RESOURCE . $this->options[ 'upload_dir' ]) || !is_writeable(DIR_RESOURCE . $this->options[ 'upload_dir' ])) { $error = "Please check 'resources' folder permissions."; } } if (!$error && $file->name) { $file_path = DIR_RESOURCE . $this->options[ 'upload_dir' ] . $file->name; $append_file = !$this->options[ 'discard_aborted_uploads' ] && is_file($file_path) && $file->size > filesize($file_path); clearstatcache(); if ($uploaded_file && is_uploaded_file($uploaded_file)) { // multipart/formdata uploads (POST method uploads) if ($append_file) { file_put_contents( $file_path, fopen($uploaded_file, 'r'), FILE_APPEND ); } else { $result = move_uploaded_file($uploaded_file, $file_path); if($result===false){ $file->error = 'Failed! Check error log for details.'; $error = new AError('Error! Tryed to move uploaded file from '.$uploaded_file.' to '.$file_path); $error->toLog(); } } } else { // Non-multipart uploads (PUT method support) file_put_contents( $file_path, fopen('php://input', 'r'), $append_file ? FILE_APPEND : 0 ); } $file_size = filesize($file_path); if ($file_size === $file->size) { $file->url = $this->options[ 'upload_url' ] . rawurlencode($file->name); chmod($file_path, 0777); } else if ($this->options[ 'discard_aborted_uploads' ]) { unlink($file_path); $file->error = 'Failed! Check error log for details.'; } $file->size = $file_size; $file->delete_url = $this->options[ 'script_url' ] . '&resource_id=%ID%'; $file->delete_type = 'DELETE'; } else { $file->error = $error; } return $file; } public function get() { $file_name = isset($_REQUEST[ 'file' ]) ? basename(stripslashes($_REQUEST[ 'file' ])) : null; if ($file_name) { $info = $this->get_file_object($file_name); } else { $info = $this->get_file_objects(); } return $info; } public function post() { $upload = isset($_FILES[ $this->options[ 'param_name' ] ]) ? $_FILES[ $this->options[ 'param_name' ] ] : array( 'tmp_name' => null, 'name' => null, 'size' => null, 'type' => null, 'error' => 'emptyResult' ); $info = array(); if (is_array($upload[ 'tmp_name' ])) { foreach ($upload[ 'tmp_name' ] as $index => $value) { $info[ ] = $this->handle_file_upload( $upload[ 'tmp_name' ][ $index ], isset($_SERVER[ 'HTTP_X_FILE_NAME' ]) ? $_SERVER[ 'HTTP_X_FILE_NAME' ] : $upload[ 'name' ][ $index ], isset($_SERVER[ 'HTTP_X_FILE_SIZE' ]) ? $_SERVER[ 'HTTP_X_FILE_SIZE' ] : $upload[ 'size' ][ $index ], isset($_SERVER[ 'HTTP_X_FILE_TYPE' ]) ? $_SERVER[ 'HTTP_X_FILE_TYPE' ] : $upload[ 'type' ][ $index ], $upload[ 'error' ][ $index ] ); } } else { $info[ ] = $this->handle_file_upload( $upload[ 'tmp_name' ], isset($_SERVER[ 'HTTP_X_FILE_NAME' ]) ? $_SERVER[ 'HTTP_X_FILE_NAME' ] : $upload[ 'name' ], isset($_SERVER[ 'HTTP_X_FILE_SIZE' ]) ? $_SERVER[ 'HTTP_X_FILE_SIZE' ] : $upload[ 'size' ], isset($_SERVER[ 'HTTP_X_FILE_TYPE' ]) ? $_SERVER[ 'HTTP_X_FILE_TYPE' ] : $upload[ 'type' ], $upload[ 'error' ] ); } return $info; } public function delete() { $file_name = isset($_REQUEST[ 'file' ]) ? basename(stripslashes($_REQUEST[ 'file' ])) : null; $file_path = $this->options[ 'upload_dir' ] . $file_name; $success = is_file($file_path) && $file_name[ 0 ] !== '.' && unlink($file_path); return $success; } public function strpos_array($haystack, $needle) { if (!is_array($needle)) { $needle = array( $needle ); } foreach ($needle as $what) { if (($pos = strpos($haystack, $what)) !== false) { return $pos; } } return false; } }