<?php
/*******************************************************************
 * 版权协议：2009-2019
 * 版权所有: PHP-北京金南曦网络技术有限公司旗下PHPWMS，PHP商城系统技术支持中心http://www.php188.net，并保留所有权利。 
* PHP商城系统网址: http://www.php188.com
 * PHPWMS系统网址：http://www.phpwms.com
 * 销售电话：010-87875088
 * 销售电话：010-87875188 
*------------------------------------------------------------------
 * 这不是一个完全免费软件！您只能在不用于商业目的的前提下对程序代码进
 * 行修改和使用；不允许对程序代码以任何形式任何目的的再发布。
 *------------------------------------------------------------------
 * 文件名称：upload.class.php
 * 摘    要：上传文件处理类
 * 适用范围：PHPWMS 1.0
 * 版    本：1.0
 *------------------------------------------------------------------
 * Script Written By phpwms项目组
 * 最后更新： 2009-09-24 phpwms 由PHP金南曦网络技术有限公司整理发布
 *******************************************************************/
error_reporting(E_ERROR||E_PARSE);
Class Upload{
	public $upload_main_path = '';//上传文件主路径
	public $upload_type = array('gif','jpg','png','7z','gz','tar','rar','zip','txt','xls','doc','pdf','swf','flv');//文件上传的格式
	private $_forbidden_type = array('php','js','html','shtml','jsp','asp','dhtml','phtml','tpl','inc','ini','dll','cgi','php3','php4','php5','exe','py','class','aspx');//禁止列表
	public $upload_maxsize = 20971520;//byte 20M 上传的文件大小
	public $upload_name = 'upload';//上传时表单file的name值
	public $upload_save_path = '';//上传文件保存路径
	public $is_rand_name = TRUE;//是否采用随机名
	public $upload_file_name = '';
	private $_full_path = '';
	public $return_obj = false;
	public $lang = array(
		'empty_error_file'=>'上传的文件为空或文件过大',
		'upload_filed'=>'文件上传失败.',
		'write_folder_error'=>'文件上传目录不可写.请联系服务器供应商.',
		'error_temp_file'=>"临时文件可能不是想要上传的文件.请确保临时目录可写,\n检查PHP.ini中upload_max_filesize的大小设置是否小于您当前上传的文件大小.",
		'too_big_file'=>'您上传文件太大.',
		'error_sufix'=>'系统中不允许该类类型的文件上传.',
		'empty_file'=>'请选择上要上传的文件.',
		'error_picuter_file'=>'请确保你传的图片是正确的图片文件.',
		'empty_file_error'=>'请检查您上传文件的表单数据是否正确或者是否太大.',
		'no_size'=>'请确保您上传的文件字节大于0.'
	);
	private $_msg = array();
	//设置文件post上传大小
	public function __construct(){
		$server_set = @ini_get('post_max_size');
		$upload_max_size = @ini_get('upload_max_filesize');
		//定义上传主路径
		$this->upload_main_path = empty($this->upload_main_path)?SYS_ROOT:$this->upload_main_path;
		//定义上传主路径后的分路径
		//如果没设置保存的文件路径 按照年/月/日保存
		if(substr(strtolower($server_set),-1,1)=='m')$post_max_size = 1024*1024*strtr($server_set,array('M'=>''));
		if(substr(strtolower($upload_max_size),-1,1)=='m')$upload_max_filesize = 1024*1024*strtr($upload_max_size,array('M'=>''));
		if($upload_max_filesize>$post_max_size){
			$size = $post_max_size;
		}elseif($upload_max_filesize<$post_max_size){
			$size = $upload_max_filesize;
		}
		$this->upload_maxsize = $size<$this->upload_maxsize?$size:$this->upload_maxsize;//如果服务器上设置的大小小于已设置的按服务器要求配
	}
/*
 * 上传文件
 */
	function up($var){
		return $this->_up($var);
	}
/**
 * 上传文件
 *
 * @param string $var 表单name值
 * @return mixed array|boolean
 */
	private function _up($var = ''){
		foreach ($this->upload_type as $k=>$type)if(in_array($type,$this->_forbidden_type))unset($this->upload_type[$k]);
	    $this->upload_save_path = empty($this->upload_save_path)?'files/'.date("Y").'/'.'attch_'.date("Ym").'/'.date("d").'/':$this->upload_save_path;
		$this->upload_main_path = substr($this->upload_main_path,-1,1)!='/'?$this->upload_main_path.'/':$this->upload_main_path;
		$this->upload_save_path = substr($this->upload_save_path,-1,1)!='/'?$this->upload_save_path.'/':$this->upload_save_path;
		$this->_full_path = $this->upload_main_path.$this->upload_save_path;
		if(!is_dir($this->_full_path))$this->_mkdirs($this->_full_path);
		$var = empty($var)?$this->upload_name:$var;
		if(empty($_FILES)){
			$this->_msg['msg'] = $this->lang['empty_error_file'];
			return FALSE;
		}
		if(empty($_FILES)){
			//屏蔽超大文件导致的浏览器错误问题
			$this->_msg['msg'] = $this->lang['too_big_file']; 
			@ob_start();
			ob_get_clean();
			ob_get_clean();
			ob_end_clean();
			return false;
		}
		if(empty($_FILES[$var]['name'])){
			$this->_msg['msg']=$this->lang['empty_file'];
			return false;
		}
		$is_one = false;
		if(!is_array($_FILES[$var]['name']))$is_one = TRUE;
		$old_name = array_filter(is_array($_FILES[$var]['name'])?$_FILES[$var]['name']:(array)$_FILES[$var]['name']);
		//全局检测
		if(!is_writable($this->_full_path)){
				$this->_msg['msg'] = $this->lang['write_folder_error'];
				return FALSE;
		}
		$file_size = array_sum($_FILES[$var]['size']);
		if($file_size > $this->upload_maxsize){
				$this->_msg['msg'] = $this->lang['too_big_file'];
				return FALSE;
		}
		if(!$sufixs = $this->_checkFileType($old_name))return FALSE;
		$upload_data = array();
		foreach ($sufixs as $k=>$s){
			$rand_name = time().'_'.strtolower($this->_rands(20)).'.'.$s;
			$end_file_name = '';
			if(!empty($this->upload_file_name)){
				$end_file_name = $this->upload_file_name;//自定义文件名 只针对单个文件
			}elseif($this->is_rand_name){
				$end_file_name = $rand_name; // 采用随机文件
			}else{
				$end_file_name = $old_name[$k];//采用文件自身的名字
			}
			$data = array(
						'rand_name' => $rand_name,
						'old_name' =>$old_name[$k],
						'temp_name' =>$is_one?$_FILES[$var]['tmp_name']:$_FILES[$var]['tmp_name'][$k],
						'type'=>$is_one?$_FILES[$var]['type']:$_FILES[$var]['type'][$k],
						'no_sufix_name'=>array_shift(explode('.',$rand_name)),
						'sufix'=>$s,//文件后缀
						'error'=>$is_one?$_FILES[$var]['error']:$_FILES[$var]['error'][$k],
						'size'=>$is_one?$_FILES[$var]['size']:$_FILES[$var]['size'][$k],
						'format_size'=>$this->_formatBytes($is_one?$_FILES[$var]['size']:$_FILES[$var]['size'][$k]),
						'upload_main_path'=>$this->upload_main_path,
						'upload_part'=>$this->upload_save_path.$end_file_name,
						'upload_full_path' =>$this->upload_main_path.$this->upload_save_path,
						'upload_maxsize'=>$this->_formatBytes($this->upload_maxsize),
						'user_set_name'=>$this->upload_file_name,
						'end_file'=>$this->_full_path.($end_file_name),
			);
			if(!is_uploaded_file($data['temp_name'])){
				$msg['msg'] = $this->lang['error_temp_file'];
				$msg['file'] = $data['old_name'];
				$this->_msg[] = $msg;
			}
			if($data['size']<=0){
				$msg['msg'] = $this->lang['no_size'];
				$msg['file'] = $data['old_name'];
				$this->_msg[] = $msg;
			}
				//检查文件是否是图片
			$file_type_array  = array('gif','jpg','png','bmp');
			if(in_array($data['sufix'],$file_type_array)){
				$check = @getimagesize($data['temp_name']);
				if((!$check)){
					$msg['msg'] = $this->lang['error_picuter_file'];
					$msg['file'] = $data['old_name'];
					$this->_msg[] = $msg;
				}
			}
			$upload_data[] = $data;
		}
		if(!empty($this->_msg))return FALSE;
		$upload_ok_data = array();
			foreach ($upload_data as $data){
				if(false!==(@move_uploaded_file($data['temp_name'],$data['end_file']))){
						$upload_ok_data[] = $data;
					}else{
						$msg['msg'] = $this->lang['upload_filed'];
						$msg['file'] = $data['old_name'];
						$this->_msg[] = $msg;
			}
		}
	$return = !empty($this->_msg)?$this->_msg:(count($upload_ok_data)==1?$upload_ok_data[0]:$upload_ok_data);
	return $this->return_obj?$this->array_to_object($return):$return;
}
	public function getMsg(){
		$msg =  isset($this->_msg[0])?$this->_msg[0]:$this->_msg;
		return $this->return_obj?$this->array_to_object($msg):$msg;
	}
/**
 * 格式化数字为计量单位
 * @param int $bytes 
 * @return string
 */
	private  function _formatBytes($bytes) {
	    $display = array('Byte', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
	    $level = 0;
	    while ($bytes > 1024) {
	        $bytes /= 1024;
	        $level++;
	    }
	    return round($bytes, 1) . ' ' . $display[$level];
	}
/**
 * 获得随机值
 * @param int $length 需要获得的随机值总数
 * @return string
 */
	private function _rands($length) {
			$hash = '';
			$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
			$max = strlen($chars) - 1;
			mt_srand((double)microtime() * 1000000);
			for($i = 0; $i < $length; $i++) {
				$hash .= $chars[mt_rand(0, $max)];
			}
			return $hash;
	}
	function array_to_object($array, $class = 'stdClass'){
		$array = !is_array($array)?array($array):$array;
		$obj = new $class();
		foreach ($array as $k => $v)$obj->$k = is_array($v)?$this->array_to_object($v,$class):$v;
		return $obj;
	}
/**
 * 批量创建目录
 *
 * @param string $path 需要创建的目录
 * @param int $mode
 */
private  function _mkdirs($path, $mode = 0777){ 
					$path = substr($path,-1,1)!='/'?$path.'/':$path;
					$dirs = explode('/',$path); 
					$subamount = FALSE=== strrpos($path, ".")?0:1;
					for ($c=0;$c < count($dirs) - $subamount; $c++) { 
					$thispath=""; 
					for ($cc=0; $cc <= $c; $cc++) { 
						$thispath.=$dirs[$cc].'/'; 
					} 
					if (!file_exists($thispath))@mkdir($thispath,$mode); 
					} 
				}
/**
 * 检查文件是否符合指定格式
 * @param string $file 需要检查的文件
 * @return mixed
 */
	private function _checkFileType($files=array()){
		if(empty($files)||!is_array($files))return false;
		foreach ($files as $file){
			$sufix = trim(strtolower(array_pop(explode('.',$file))));//后缀名
			//if(empty($this->upload_type))return $sufix;
			if(in_array($sufix,$this->upload_type)){
					$sufixs[] = $sufix;
				}else{
					$msg['msg'] = $this->lang['error_sufix'];
					$msg['file'] = $file;
					$this->_msg[] = $msg;
			}
		}
		return !empty($this->_msg)?FALSE:$sufixs;
	}
}
?>