Files
eletter-backup/plugins/jquery.filer/php/class.uploader.php
2024-05-31 14:18:00 +07:00

438 lines
16 KiB
PHP

<?php
# ======================================================================== #
#
# Title [PHP] Uploader
# Author: CreativeDream
# Website: https://github.com/CreativeDream/php-uploader
# Version: 0.2
# Date: 26-Aug-2015
# Purpose: Validate, Remove, Upload, Download files to server.
#
# ======================================================================== #
class Uploader {
protected $options = array(
'limit' => 10,
'maxSize' => 10,
'extensions' => null,
'required' => false,
'uploadDir' => 'uploads/',
'title' => array('auto', 10),
'removeFiles' => true,
'perms' => null,
'onCheck' => null,
'onError' => null,
'onSuccess' => null,
'onUpload' => null,
'onComplete' => null,
'onRemove' => null
);
public $error_messages = array(
1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini.",
2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.",
3 => "The uploaded file was only partially uploaded.",
4 => "No file was uploaded.",
6 => "Missing a temporary folder.",
7 => "Failed to write file to disk.",
8 => "A PHP extension stopped the file upload.",
'accept_file_types' => "Filetype not allowed",
'file_uploads' => "File uploading option in disabled in php.ini",
'post_max_size' => "The uploaded file exceeds the post_max_size directive in php.ini",
'max_file_size' => "File is too big",
'max_number_of_files' => "Maximum number of files exceeded",
'required_and_no_file' => "No file was choosed. Please select one.",
'no_download_content' => "File could't be download."
);
private $field = null;
private $data = array(
"hasErrors" => false,
"hasWarnings" => false,
"isSuccess" => false,
"isComplete" => false,
"data" => array(
"files" => array(),
"metas" => array()
)
);
public function __construct(){
// __construct function
$this->cache_data = $this->data;
}
/**
* upload method
*
* Return the initialize method
* @param $field {Array, String}
* @param $options {Array, null}
* @return array
*/
public function upload($field, $options = null){
$this->data = $this->cache_data;
return $this->initialize($field, $options);
}
/**
* initialize method
*
* Initialize field values and properties.
* Merge options
* Prepare files
* @param $field {Array, String}
* @param $options {Array, null}
* @return array
*/
private function initialize($field, $options){
if(is_array($field) && in_array($field, $_FILES)){
$this->field = $field;
$this->field['Field_Name'] = array_search($field, $_FILES);
$this->field['Field_Type'] = 'input';
if(!is_array($this->field['name'])){
$this->field = array_merge($this->field, array("name" => array($this->field['name']), "tmp_name"=>array($this->field['tmp_name']), "type"=>array($this->field['type']), "error"=>array($this->field['error']), "size"=>array($this->field['size'])));
}
foreach($this->field['name'] as $key=>$value){ if(empty($value)){ unset($this->field['name'][$key]); unset($this->field['type'][$key]); unset($this->field['tmp_name'][$key]); unset($this->field['error'][$key]); unset($this->field['size'][$key]); } }
$this->field['length'] = count($this->field['name']);
}elseif(is_string($field) && $this->isURL($field)){
$this->field = array("name" => array($field), "size"=>array(), "type"=>array(), "error"=>array());
$this->field['Field_Type'] = 'link';
$this->field['length'] = 1;
}else{
return false;
}
if($options != null){
$this->setOptions($options);
}
return $this->prepareFiles();
}
/**
* setOptions method
*
* Merge options
* @param $options {Array}
*/
private function setOptions($options){
if(!is_array($options)){return false;}
$this->options = array_merge($this->options, $options);
}
/**
* validation method
*
* Check the field and files
* @return boolean
*/
private function validate($file = null){
$field = $this->field;
$errors = array();
$options = $this->options;
if($file == null){
$ini = array(ini_get('file_uploads'),((int) ini_get('upload_max_filesize')),((int) ini_get('post_max_size')), ((int) ini_get('max_file_uploads')));
if(!isset($field) || empty($field)) return false;
if(!$ini[0]) $errors[] = $this->error_messages['file_uploads'];
if($options['required'] && $field['length'] == 0) $errors[] = $this->error_messages['required_and_no_file'];
if(($options['limit'] && $field['length'] > $options['limit']) || ($field['length']) > $ini[3]) $errors[] = $this->error_messages['max_number_of_files'];
if(!file_exists($options['uploadDir']) && !is_dir($options['uploadDir']) && mkdir($options['uploadDir'], 750, true)){
$this->data['hasWarnings'] = true;
$this->data['warnings'] = "A new directory was created in " . realpath($options['uploadDir']);
}
if(!is_writable($options['uploadDir'])) @chmod($options['uploadDir'], 750);
if($field['Field_Type'] == "input"){
$total_size = 0; foreach($this->field['size'] as $key=>$value){ $total_size += $value; } $total_size = $total_size/1048576;
if($options['maxSize'] && $total_size > $options['maxSize']) $errors[] = $this->error_messages['max_file_size'];
if($total_size > $ini[1]) $errors[] = $this->error_messages[1];
if($total_size > $ini[2]) $errors[] = $this->error_messages['post_max_size'];
}
}else{
if(@$field['error'][$file['index']] > 0 && array_key_exists($field['error'][$file['index']], $this->error_messages)) $errors[] = $this->error_messages[$field['error'][$file['index']]];
if($options['extensions'] && !in_array($file['extension'], $options['extensions'])) $errors[] = $this->error_messages['accept_file_types'];
if($file['type'][0] == "image" && @!is_array(getimagesize($file['tmp']))) $errors[] = $this->error_messages['accept_file_types'];
if($options['maxSize'] && $file['size'][0] > $options['maxSize']) $errors[] = $this->error_messages['max_file_size'];
if($field['Field_Type'] == 'link' && empty($this->cache_download_content)) $errors[] = "";
}
$custom = $this->_onCheck($file); if($custom) $errors = array_merge($errors, $custom);
if(!empty($errors)){
$this->data['hasErrors'] = true;
if(!isset($this->data['errors'])) $this->data['errors'] = array();
$this->data['errors'][] = $errors;
$custom = $this->_onError($errors, $file);
return false;
}else{
return true;
}
}
/**
* prepareFiles method
*
* Prepare files for upload/download and generate meta infos
* @return $this->data
*/
private function prepareFiles(){
$field = $this->field;
$validate = $this->validate();
if($validate){
$files = array();
$removed_files = $this->removeFiles();
for($i = 0; $i < count($field['name']); $i++){
$metas = array();
if($field['Field_Type'] == 'input'){
$tmp_name = $field['tmp_name'][$i];
}elseif($field['Field_Type'] == 'link'){
$link = $this->downloadFile($field['name'][0], false, true);
$tmp_name = $field['name'][0];
$field['name'][0] = pathinfo($field['name'][0], PATHINFO_BASENAME);
$field['type'][0] = $link['type'];
$field['size'][0] = $link['size'];
$field['error'][0] = 0;
}
$metas['extension'] = substr(strrchr(strtolower($field['name'][$i]), "."),1);
$metas['type'] = preg_split('[/]', $field['type'][$i]);
$metas['extension'] = $field['Field_Type'] == 'link' && empty($metas['extension']) ? $metas['type'][1] : $metas['extension'];
$metas['old_name'] = substr($field['name'][$i], 0, -(strlen(strrchr($field['name'][$i], $metas['extension']))+1));
$metas['size'] = $field['size'][$i];
$metas['size2'] = $this->formatSize($metas['size']);
$metas['name'] = $this->generateFileName($this->options['title'], array('name'=>$metas['old_name'], 'size'=>$metas['size'])) . (!empty($metas['extension']) ? "." . $metas['extension'] : "");
$metas['file'] = $this->options['uploadDir'] . $metas['name'];
$metas['replaced'] = file_exists($metas['file']);
$metas['date'] = date('r');
if(!in_array($field['name'][$i], $removed_files) && $this->validate(array_merge($metas, array('index'=>$i, 'tmp'=>$tmp_name))) && $this->uploadFile($tmp_name, $metas['file'])){
if($this->options['perms']) @chmod($metas['file'], $this->options['perms']);
$custom = $this->_onUpload($metas, $this->field); if($custom && is_array($custom)) $metas = array_merge($custom, $metas);
ksort($metas);
$files[] = $metas['file'];
$this->data['data']['metas'][] = $metas;
}
}
$this->data['isSuccess'] = count($field['name']) - count($removed_files) == count($files);
$this->data['data']['files'] = $files;
if($this->data['isSuccess']) $custom = $this->_onSuccess($this->data['data']['files'], $this->data['data']['metas']);
$this->data['isComplete'] = true;
$custom = $this->_onComplete($this->data['data']['files'], $this->data['data']['metas']);
}
return $this->data;
}
/**
* uploadFile method
*
* Upload/Download files to server
* @return boolean
*/
private function uploadFile($source, $destination){
if($this->field['Field_Type'] == 'input'){
return @move_uploaded_file($source, $destination);
}elseif($this->field['Field_Type'] == 'link'){
return $this->downloadFile($source, $destination);
}
}
/**
* removeFiles method
*
* Remove files or cancel upload for them
* @return array
*/
private function removeFiles(){
$removed_files = array();
if($this->options['removeFiles'] !== false){
foreach($_POST as $key=>$value){
preg_match((is_string($this->options['removeFiles']) ? $this->options['removeFiles'] : '/jfiler-items-exclude-'.$this->field['Field_Name'].'-(\d+)/'), $key, $matches);
if(isset($matches) && !empty($matches)){
$input = $_POST[$matches[0]];
if($this->isJson($input)) $removed_files = json_decode($input, true);
$custom = $this->_onRemove($removed_files, $this->field); if($custom && is_array($custom)) $removed_files = $custom;
}
}
}
return $removed_files;
}
/**
* downloadFile method
*
* Download file to server
* @return boolean
*/
private function downloadFile($source, $destination, $info = false){
set_time_limit(80);
$forInfo = array(
"size" => 1,
"type" => "text/plain"
);
if(!isset($this->cache_download_content)){
$file_content = file_get_contents($source);
if($info){
$headers = implode(" ", $http_response_header);
if(preg_match('/Content-Length: (\d+)/', $headers, $matches)) $forInfo['size'] = $matches[1];
if(preg_match('/Content-Type: (\w+\/\w+)/', $headers, $matches)) $forInfo['type'] = $matches[1];
$this->cache_download_content = $file_content;
return $forInfo;
}
}else{
$file_content = $this->cache_download_content;
}
$downloaded_file = @fopen($destination, 'w');
$written = @fwrite($downloaded_file, $file_content);
@fclose($downloaded_file);
return $written;
}
/**
* generateFileName method
*
* Generated a file name by uploading
* @return boolean
*/
private function generateFileName($conf, $file){
$type = is_array($conf) && isset($conf[0]) ? $conf[0] : $conf;
$type = $type ? $type : 'name';
$length = is_array($conf) && isset($conf[1]) ? $conf[1] : null;
$random_string = substr(str_shuffle("_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length ? $length : 10);
$string = "";
switch($type){
case "auto":
$string = $random_string;
break;
case "name":
$string = $file['name'];
break;
default:
$string = $type;
if(strpos($string, "{{random}}") !== false){
$string = str_replace("{{random}}", $random_string, $string);
}
if(strpos($string, "{{file_name}}") !== false){
$string = str_replace("{{file_name}}", $file['name'], $string);
}
if(strpos($string, "{{file_size}}") !== false){
$string = str_replace("{{file_size}}", $file['size'], $string);
}
if(strpos($string, "{{timestamp}}") !== false){
$string = str_replace("{{timestamp}}", time(), $string);
}
if(strpos($string, "{{date}}") !== false){
$string = str_replace("{{date}}", date('Y-n-d_H:i:s'), $string);
}
}
return $string;
}
/**
* isJson method
*
* Check if string is a valid json
* @return boolean
*/
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
/**
* isURL method
*
* Check if string $url is a link
* @return boolean
*/
private function isURL($url){
return preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url);
}
/**
* formatSize method
*
* Convert file size
* @return float
*/
private function formatSize($bytes){
if ($bytes >= 1073741824){
$bytes = number_format($bytes / 1073741824, 2) . ' GB';
}elseif ($bytes >= 1048576){
$bytes = number_format($bytes / 1048576, 2) . ' MB';
}elseif ($bytes > 0){
$bytes = number_format($bytes / 1024, 2) . ' KB';
}else{
$bytes = '0 bytes';
}
return $bytes;
}
private function _onCheck(){
$arguments = func_get_args();
return $this->options['onCheck'] != null && function_exists($this->options['onCheck']) ? $this->options['onCheck'](@$arguments[0]) : null;
}
private function _onSuccess(){
$arguments = func_get_args();
return $this->options['onSuccess'] != null && function_exists($this->options['onSuccess']) ? $this->options['onSuccess'](@$arguments[0], @$arguments[1]) : null;
}
private function _onError(){
$arguments = func_get_args();
return $this->options['onError'] && function_exists($this->options['onError']) ? $this->options['onError'](@$arguments[0], @$arguments[1]) : null;
}
private function _onUpload(){
$arguments = func_get_args();
return $this->options['onUpload'] && function_exists($this->options['onUpload']) ? $this->options['onUpload'](@$arguments[0], @$arguments[1]) : null;
}
private function _onComplete(){
$arguments = func_get_args();
return $this->options['onComplete'] != null && function_exists($this->options['onComplete']) ? $this->options['onComplete'](@$arguments[0], @$arguments[1]) : null;
}
private function _onRemove(){
$arguments = func_get_args();
return $this->options['onRemove'] && function_exists($this->options['onRemove']) ? $this->options['onRemove'](@$arguments[0], @$arguments[1]) : null;
}
}
?>