<?php

if(! defined('OT_ROOT')) {
	exit('Access Denied');
}


class File{
	/* ***** 目录 START ***** */

	// 创建目录；如果存在,不创建
	// $dir 可以是绝对路径或相对路径
	public static function CreateDir($dir){
		if (! is_dir($dir)){
			if (@mkdir($dir, 0755, true)){	// 第三参数true表示允许创建多级目录
				//创建index.html,目的防止列目录漏洞
				//fclose(fopen($dir.'/index.html', 'w'));
				@chmod($dir, 0755);
				return true;
			}else{
				return false;
			}
		}else{
			return true;
		}
	}

	// 创建多层目录；如果存在,不创建 $dir：绝对路径，CreateDir 函数就可以创建多层级目录，后期删除
	public static function CreateMoreDir($dir){
		/*
		return self::CreateDir($pathTemp);
		*/
		// 架设站点指定目录 D:/web/，程序放在 otcms/ 子目录下
		// 前台根目录路径（如：D:/web/otcms/）
		$siteROOT	= str_replace(array('//',"\\"), array('/','/'), OT_ROOT);
			if (substr($siteROOT,-1) != '/'){ $siteROOT .= '/'; }
		$siteArr	= explode('/',$siteROOT);
		$siteCount	= count($siteArr) - 1;

		// 站点根目录路径（如：D:/web）
		/*
		$siteDir	= rtrim(str_replace(array('//',"\\"), array('/','/'), $_SERVER['DOCUMENT_ROOT']), '/');
			if (substr($siteDir,-1) != '/'){ $siteDir .= '/'; }
		$siteArr	= explode('/',$siteDir);
		$siteCount	= count($siteArr) - 1;
		*/

		// 目标目录路径
		$pathDir = str_replace("\\",'/', $dir);
			if (substr($pathDir,-1) != '/'){ $pathDir .= '/'; }
		$pathArr	= explode('/',$pathDir);
		$pathCount	= count($pathArr)-1;

		// $pathTemp	= $siteDir;
		$pathTemp	= $siteROOT;
		for ($i=$siteCount; $i<$pathCount; $i++){
			if ($i==0){
				$pathTemp = $pathArr[0] .'/';
			}else{
				$pathTemp .= $pathArr[$i] .'/';
			}
			// echo('<div>'. $pathTemp .'</div>');
			// if (stripos($pathTemp,$siteROOT) !== false){
				if (! file_exists($pathTemp)){
					self::CreateDir($pathTemp);
					if (! file_exists($pathTemp)){
						error_log('File::CreateMoreDir 创建目录失败'. $pathTemp .'['. $pathDir .'].');
						// $errStr = '创建目录失败'. $pathTemp .'['. $pathDir .']';
						return false;
					}
				}
			// }
		}
		// echo('siteROOT：'. $siteROOT .'<br />siteDir：'. $siteDir .'<br />pathDir：'. $pathDir .'<br /><br />');

		return true;
	}


	// 目录的实际大小
	public static function DirSize($dir,$extArr='',$judIncDir=true){
		$judEmpty = empty($extArr);
		if (! is_array($extArr)){ $extArr = array($extArr); }

		$dh = @opendir($dir);
		$size = 0;
		if (substr($dir,-1) != '/'){ $dir .= '/'; }
		while ($file = @readdir($dh)){
			if ($file != '.' && $file != '..'){
				$path = $dir . $file;
				if (@is_dir($path) && $judIncDir){
					$size += self::DirSize($path);
				} else {
					if ($judEmpty || in_array(self::GetExt($path),$extArr)){
						$size += @filesize($path);
					}
				}
			}
		}
		@closedir($dh);
		return $size;
	}


	// 目录个数
	public static function DirCount($dir){
		$dh = @opendir($dir);
		$count = 0;
		if (substr($dir,-1) != '/'){ $dir .= '/'; }
		while ($file = @readdir($dh)){
			if ($file != '.' && $file != '..'){
				$path = $dir . $file;
				if (@is_dir($path)){
					$count++;
				}
			}
		}
		@closedir($dh);
		return $count;
	}


	// 复制目录以及目录下文件
	public static function CopyDir($source, $destination){
		$result = true;

		if(! is_dir($source)){
			trigger_error('Invalid Parameter', E_USER_ERROR);
		}
		if(! is_dir($destination)){
			if(! mkdir($destination, 0755)){
				trigger_error('Invalid Parameter', E_USER_ERROR);
			}
		}

		$handle = opendir($source);
		while(($file = readdir($handle)) !== false){
			if($file != '.' && $file != '..'){
				$src = $source . DIRECTORY_SEPARATOR . $file;
				$dtn = $destination . DIRECTORY_SEPARATOR . $file;
				if(is_dir($src)){
					self::CopyDir($src, $dtn);
				}else{
					if(! copy($src, $dtn)){
						$result = false;
						break;
					}
				}
			}
		}
		closedir($handle);

		return $result;
	}


	// 删除目录以及目录下文件
	public static function DelDir($dirName, $isDelDir=true){
		$result = false;

		if(! is_dir($dirName)){
			trigger_error('目录路径不存在 ('. $dirName .')', E_USER_ERROR);
		}

		$handle = opendir($dirName);
		while(($file = readdir($handle)) !== false){
			if($file != '.' && $file != '..'){
				$dir = $dirName . DIRECTORY_SEPARATOR . $file;
				is_dir($dir) ? self::DelDir($dir, $isDelDir) : unlink($dir);
			}
		}
		closedir($handle);

		if ($isDelDir){
			$result = rmdir($dirName) ? true : false;
		}else{
			$result = true;
		}

		return $result;
	}

	// 修改目录名
	public static function RevName($source, $destination){
		if ($source == $destination){ return true; }
		if (@rename($source,$destination)){
			return true;
		}else{
			return false;
		}
	}

	/*
	// 统计目录下的文件数量
	public static function Count($dir){
		$handle = opendir($dir);
		$i = 0;
		while($file=(readdir($handle)) !== false){
			if($file!=='.' || $file!='..'){
				$i++ ;
			}
		}
		closedir($handle);
		return $i;
	}
	*/

	// 统计目录下文件数 $dirPath 目录路径，$extArr 指定扩展名数组，$skipArr 要跳过忽略的文件名数组
	public static function Count($dirPath,$extArr='',$skipArr=array()){
		$fileArr = @scandir($dirPath);
		if ($fileArr){
			$judEmpty = empty($extArr);
			if (! is_array($extArr)){ $extArr = array($extArr); }

			if ($judEmpty){
				$count = count($fileArr)-2;	// 所有文件总数除./和../ 
			}else{
				$count = 0;
				foreach ($extArr as $ext){
					$count += count(preg_grep("/\.". $ext ."$/", $fileArr));
				}
			}
			if (! empty($skipArr)){
				if (! is_array($skipArr)){ $skipArr = array($skipArr); }
				foreach ($skipArr as $val){
					if (in_array($val,$fileArr)){
						$count --;
					}
				}
			}
		}else{
			$count = -1;
		}

		return $count;
	}


	// 获取路径下的目录列表
	public static function GetDirList($dirPath){
		$retArr = array();
		if (! is_dir($dirPath)){ return $retArr; }
		if ($handle = opendir($dirPath)) {
			if (substr($dirPath,-1) != '/'){ $dirPath .= '/'; }
			while (($file = readdir($handle)) !== false) {
				if ($file != '.' && $file != '..' && is_dir($dirPath . $file)) {
					$retArr[] = $file;
				}
			}
		}
		closedir($handle);
		//print_r($retArr);die();
		return $retArr;
	}

	// 获取路径下的文件列表 $dirPath 目录路径，$extArr 指定扩展名数组，$skipArr 要跳过忽略的文件名数组
	public static function GetFileList($dirPath, $extArr='', $skipArr=array()){
		$judEmpty = empty($extArr);
		if (! is_array($extArr)){ $extArr = array($extArr); }

		$retArr = array();
		if ($handle = opendir($dirPath)) {
			if (substr($dirPath,-1) != '/'){ $dirPath .= '/'; }
			while (($file = readdir($handle)) !== false) {
				if ($file != '.' && $file != '..' && (! is_dir($dirPath . $file)) && ($judEmpty || in_array(self::GetExt($file),$extArr))) {
					$retArr[] = $file;
				}
			}
		}
		closedir($handle);

		if (! empty($skipArr)){
			if (! is_array($skipArr)){ $skipArr = array($skipArr); }
			$retArr = array_merge(array_diff($retArr, $skipArr));
		}

		//print_r($retArr);die();
		return $retArr;
	}

	// 获取路径下的目录和文件列表
	public static function GetAllFileList($dirPath,$rootDir='',$extArr=''){
		$retArr = array();
		if (! is_dir($dirPath)){ return $retArr; }

		$judEmpty = empty($extArr);
		if (is_array($extArr)){ $ext2Arr = $extArr; }else{ $ext2Arr = array($extArr); }

		if ($handle = opendir($dirPath)) {
			if (substr($dirPath,-1) != '/'){ $dirPath .= '/'; }
			$dirArr = array();
			$dirListArr = array();
			$fileListArr = array();
			while (($file = readdir($handle)) !== false) {
				if ($file != '.' && $file != '..') {
					if (is_dir($dirPath . $file)){
						$dirArr[] = $file;
					}elseif ($file != 'thumbs.db' && ($judEmpty || in_array(self::GetExt($file),$ext2Arr))){
						$fileListArr[] = $rootDir . $file;
					}
				}
			}
			foreach ($dirArr as $dir){
				$dirListArr = array_merge($dirListArr,self::GetAllFileList($dirPath . $dir .'/', $rootDir . $dir .'/', $extArr));
			}
			$retArr = array_merge($dirListArr,$fileListArr);
		}
		closedir($handle);
		// print_r($retArr);die();
		// mb_convert_encoding($fileName,'UTF-8','GBK');
		return $retArr;
	}

	// 获取创建时间
	public static function GetCreateTime($filePath, $defVal=''){
		if (! file_exists($filePath)){
			return $defVal;
		}
		$a = filectime($filePath);
		if ($a === false){
			return $defVal;
		}else{
			return date('Y-m-d H:i:s',$a);
		}
	}

	// 获取修改时间
	public static function GetRevTime($filePath, $defVal=''){
		if (! file_exists($filePath)){
			return $defVal;
		}
		$a = filemtime($filePath);
		if ($a === false){
			return $defVal;
		}else{
			return date('Y-m-d H:i:s',$a);
		}
	}
	/* ***** 目录 END ***** */



	/* ***** 文件 START ***** */

	// 写文件
	public static function Write($source, $data, $isCreateDir=false, &$errStr=''){
		$judRes = true;
		$pathDir = str_replace("\\",'/',$source);
		if ($isCreateDir){
			$retRes = self::CreateMoreDir(pathinfo($source, PATHINFO_DIRNAME));
			if (! $retRes){
				$errStr = '创建目录失败['. $pathDir .']';
				return false;
			}
		}
		try{
			if($fp = @fopen($pathDir, 'wb')) {
				@fwrite($fp, $data);
				@fclose($fp);
				@chmod($pathDir, 0755);
			} else {
				$judRes = false;
				$errStr = '无法写入'. $pathDir;
				//echo('不能写入该缓存文件，请检查该目录 ./cache/js/ .');
				//exit;
			}
		}catch (Exception $e){
			$judRes = false;
			$errStr = '错误：'. $e;
		}
		return $judRes;
	}


	// 采用锁定方式写文件
	public static function CacheWrite($pageurl,$pagedata){
		if(! $fso=fopen($pageurl,'w')){
			//$this->warns('无法打开缓存文件.');
			return false;
		}
		if(!flock($fso,LOCK_EX)){		//LOCK_NB,排它型锁定
			//$this->warns('无法锁定缓存文件.');
			return false;
		}
		if(!fwrite($fso,$pagedata)){	//写入字节流,serialize写入其他格式
			//$this->warns('无法写入缓存文件.');
			return false;
		}
		flock($fso,LOCK_UN);	//释放锁定
		fclose($fso);
		return true;
	}


	// 复制文件
	public static function Copy($source, $filePath){
		if (file_exists($source) == false) {
			return false;
		}
		$result=@copy($source, $filePath);
		@chmod($filePath, 0644);
		return $result;
	}


	// 删除文件
	public static function Del($filePath){
		if (! empty($filePath)){
			@chmod ($filePath, 0755);
			if (@unlink($filePath)){
				return true;
			}else{
				return false;
			}
		}else{
			return false;
		}
	}


	// 删除目录下所有或者指定后缀的文件
	public static function MoreDel($path, $extArr=''){
		//给定的目录不是一个文件夹
		if(! is_dir($path)){
			return 0;
		}

		$delNum = 0;
		$judEmpty = empty($extArr);
		if (! is_array($extArr)){ $extArr = array($extArr); }
		$fh = opendir($path);
		while(($row = readdir($fh)) !== false){
			//过滤掉虚拟目录
			if($row == '.' || $row == '..'){ continue; }
			
			if (substr($path,-1) != '/'){ $path .= '/'; }
			if(! is_dir($path . $row)){
				if ($judEmpty){
					$extJud = true;
				}elseif ( in_array(self::GetExt($row),$extArr) ){
					$extJud = true;
				}else{
					$extJud = false;
				}
				if ($extJud){
					if (strlen($row) > 200){
						$tempName = md5($row) .'.'. self::GetExt($row);
						@rename($path . $row, $path . $tempName);
						unlink($path . $tempName);
					}else{
						unlink($path . $row);
					}
					$delNum ++;
				}
			}
			
		}
		// 关闭目录句柄，否则出Permission denied
		closedir($fh);

		return $delNum;
	}


	// 读取文件
	public static function Read($filePath, $mode=''){
		if (! file_exists($filePath)){
			if ($mode == 'det'){
				return '[noFile]';
			}else{
				return '';
			}
		}
		$fp = fopen($filePath,'r'); 
		$fsize = filesize($filePath);
			if ($fsize == 0){
				if ($mode == 'det'){
					return '[empty]';
				}else{
					return '';
				}
			}
		$content = fread($fp,$fsize);//读文件 
		fclose($fp);
			if (strlen($content) == 0){
				if ($mode == 'det'){
					return '[empty]';
				}else{
					return '';
				}
			}
		return $content;
	}


	// 读取文件一行
	public static function ReadOne($filePath, $mode=''){
		if (! file_exists($filePath)){
			if ($mode == 'det'){
				return '[noFile]';
			}else{
				return '';
			}
		}
		$fp= fopen($filePath,'r');
		if (! feof($fp)){
			return fgets($fp);
		}else{
			if ($mode == 'det'){
				return '[empty]';
			}else{
				return '';
			}
		}
		fclose($fp);
	}


	/*
	获取大文件最后$num行 
	原理：首先通过fseek找到文件的最后一位EOF，然后找最后一行的起始位置，取这一行的数据，再找次一行的起始位置， 再取这一行的位置，依次类推，直到找到了$num行。
	*/
	public static function ReadEnd($filePath, $num, $mode=''){
		if (! file_exists($filePath)){
			if ($mode == 'det'){
				return '[noFile]';
			}else{
				return '';
			}
		}

		$fp = fopen($filePath,"r");
		if (feof($fp)){
			if ($mode == 'det'){
				return '[empty]';
			}else{
				return '';
			}
		}
	
		$pos = -2;
		$eof = "";
		$head = false;	// 当总行数小于Num时，判断是否到第一行了
		$lines = array();
		while($num>0){
			while($eof != "\n"){
				if(fseek($fp, $pos, SEEK_END)==0){	// fseek成功返回0，失败返回-1
					$eof = fgetc($fp);
					$pos --;
				}else{								// 当到达第一行，行首时，设置$pos失败
					fseek($fp, 0, SEEK_SET);
					$head = true;					// 到达文件头部，开关打开
					break;
				}
			}
			array_unshift($lines,fgets($fp));
			if($head){ break; }						// 这一句，只能放上一句后，因为到文件头后，把第一行读取出来再跳出整个循环
			$eof = "";
			$num--;
		}
		fclose($fp);

		return implode('', $lines);
	}


	// 获取文件属性
	public static function Attri($filePath){
		if (file_exists($filePath) == false) {
			return false;
		}

		$result=array();
		$result['size']=filesize($filePath);

		return $result;
	}


	// 字节级转换成相应级单位
	public static function SizeUnit($fileSize, $dzStr=' '){
		if (! is_numeric($fileSize)){ return $fileSize; }

		if ($fileSize >= 1073741824){
			$fileSize = round($fileSize / 1073741824 * 100) / 100 . $dzStr .'GB';

		} elseif ($fileSize >= 1048576){
			$fileSize = round($fileSize / 1048576 * 100) / 100 . $dzStr .'MB';

		} elseif ($fileSize >= 1024){
			$fileSize = round($fileSize / 1024 * 100) / 100 . $dzStr .'KB';

		} else {
			$fileSize = $fileSize . $dzStr .'字节';
		}

		return $fileSize;
	}


	// 获得新文件名
	public static function GetNewName($ext){
		return date('YmdHis') . rand(1000,9999) .'.'. $ext;
	}


	// 获得文件扩展名
	public static function GetExt($fileName){
		/*
		如：/otcmscom/idccms/test.txt
		PATHINFO_DIRNAME - 只返回 dirname	如 /otcmscom/idccms
		PATHINFO_BASENAME - 只返回 basename	如 test.txt
		PATHINFO_EXTENSION - 只返回 extension	如 txt
		PATHINFO_FILENAME - 只返回 filename	如 test
		*/
		return strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
	}


	// 获得远程文件扩展名，目前仅支持图片类扩展名
	public static function GetRemoteExt($fileUrl, $fileType){
		$ext = strtolower(self::GetExt($fileUrl));
		if ($fileType == 'image'){
			$typeArr = array('bmp','gif','jpg','jpeg','png','ico','webp');
			$mimeArr = array(
				'image/bmp'	=> 'bmp',
				'image/gif'	=> 'gif',
				'image/jpeg'=> 'jpg',
				'image/png'	=> 'png',
				'image/ico'	=> 'ico',
				'image/webp'=> 'webp',
				);

		}else{
			// text/html
			return $ext;
		}
		if (strlen($ext) == 0){
			$ext = '';
			// 获取响应头
			if(( $headers = get_headers($fileUrl, 1) ) !== false){
				// 获取响应的类型
				$type = $headers['Content-Type'];
				// 如果符合我们要的类型
				if(isset($mimeArr[$type])){
					$ext = $mimeArr[$type];
				 }
			}
		}
		if (! in_array($ext, $typeArr)){
			$ext = '';
		}
		return $ext;
	}


	// 获取远程文件并把它保存到本地
	/*
	$fileUrl 是远程图片的完整URL地址，不能为空。
	$fileDir 可选变量；存放目录路径，如为空即为当前目录
	$fileName 是可选变量: 如果为空，本地文件名将基于时间自动生成
	*/
	public static function Remote($fileUrl, $fileDir, $fileName){
		$fp = @fopen($fileDir . $fileName, 'w+');
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'); 
		curl_setopt($ch, CURLOPT_URL, $fileUrl);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 80);
		curl_setopt($ch ,CURLOPT_TIMEOUT, 360);			// 设置超时
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
		if (substr(strtolower($fileUrl),0,8) == 'https://'){
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);	// 跳过证书检查  
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);		// 从证书中检查SSL加密算法是否存在
		}
		curl_setopt($ch, CURLOPT_FILE, $fp);
		curl_exec($ch);
		$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);
		fclose($fp);
		if ($http_code == 200) {
			return true;
		} else {
			unlink($fileDir . $fileName);
			return false;
		}
	}

	public static function Download2($filePath, $downName, $charset='UTF-8', $mimeType='application/octet-stream'){  
		// 文件名乱码问题
		$ua = $_SERVER['HTTP_USER_AGENT'];
		if (preg_match('/MSIE/', $ua)) {
			$downName = rawurlencode($downName);
			$attHeader = 'Content-Disposition: attachment; filename="'. $downName .'"; charset='. $charset;
		}else if (preg_match('/Firefox/', $ua)) {
			$attHeader = 'Content-Disposition: attachment; filename*="utf8\'\''. $downName .'"' ;
		}else{
			$attHeader = 'Content-Disposition: attachment; filename="'. $downName .'"; charset='. $charset;
		}

		$filesize = filesize($filePath);

		//header('Pragma: public'); header('Expires: 0');
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
		header('Content-Type: application/force-download');
		header('Content-Type: '. $mimeType);
		header($attHeader);
		header('Pragma: cache');
		header('Cache-Control: public, must-revalidate, max-age=0');
		header('Content-Length: '. $filesize);
		readfile($filePath);
		exit;
	}

	// 限速下载  $filePath：文件路径； $downName：下载文件名； $downRate：设置下载速率(kb/s)
	public static function DownRate($filePath, $downName, $downRate = 10240){  
			$ua = $_SERVER['HTTP_USER_AGENT'];
			if (preg_match('/MSIE/', $ua)) {
				$downName = rawurlencode($downName);
				$attHeader = 'Content-Disposition: attachment; filename="'. $downName .'"; charset=UTF-8';
			}else if (preg_match('/Firefox/', $ua)) {
				$attHeader = 'Content-Disposition: attachment; filename*="utf8\'\''. $downName .'"' ;
			}else{
				$attHeader = 'Content-Disposition: attachment; filename="'. $downName .'"; charset=UTF-8';
			}

			// 发送 headers
			$fileSize = filesize($filePath);
			$downSize = round($downRate * 1024);
			// if ($fileSize < $downSize){ $downSize = $fileSize; }
			header('Cache-control: private');
			header('Content-Type: application/octet-stream');
			header('Content-Length: '. $fileSize);
			header($attHeader);
			// header('Content-Disposition: filename='. $downName);
			ob_clean();
			flush();
			// 打开文件流
			$file = fopen($filePath, "r");
			while (! feof($file)) {
				// 发送当前部分文件给浏览者
				print fread($file, $downSize);
				// flush 内容输出到浏览器端
				flush();
				ob_flush();  //防止PHP或web服务器的缓存机制影响输出
				// 终端1秒后继续
				sleep(1);
			}
			// 关闭文件流
			fclose($file);
	}

	/* ***** 文件 END ***** */



	/* ***** 文件权限 START ***** */

	// 是否可读
	public static function IsRead($fileName,$mode=''){
		$jud = is_readable($fileName);
		if ($mode=='cn'){
			if ($jud){
				$jud='<span style="color:green;">可读</span>';
			}else{
				if (file_exists($fileName)){
					$jud='<span style="color:red;">不可读</span>';
				}else{
					$jud='<span style="color:red;">不存在</span>';
				}
			}
		}
		return $jud;
	}

	// 是否可写
	public static function IsWrite($fileName,$mode=''){
		$jud = is_writable($fileName);
		if ($mode=='cn'){
			if ($jud){
				$jud='<span style="color:green;">可写</span>';
			}else{
				if (file_exists($fileName)){
					$jud='<span style="color:red;">不可写</span>';
				}else{
					$jud='<span style="color:red;">不存在</span>';
				}
			}
		}
		return $jud;
	}

	// 是否可改名
	public static function IsRev($fileName,$mode=''){
		if (substr($fileName,-1)=='/'){ $fileName = substr($fileName,0,-1); }
		if (! file_exists($fileName)){
			if ($mode=='cn'){
				return '<span style="color:red;">不存在</span>';
			}else{
				return $jud;
			}
		}
		try{
			$jud = @rename($fileName,$fileName .'Tmp');
			if ($jud){ @rename($fileName .'Tmp',$fileName); }
		}
		catch (Exception $e){
			$jud = false;
		}
		if ($mode=='cn'){
			if ($jud){
				$jud='<span style="color:green;">可改</span>';
			}else{
				$jud='<span style="color:red;">不可改</span>';
			}
		}
		return $jud;
	}

	// 获取文件权限（字符型，如-rw-rw-rw-）
	public static function LimitChar($fileName){
		$perms = fileperms($fileName);
		if (($perms & 0xC000) == 0xC000) { $info = 's'; }
		elseif (($perms & 0xA000) == 0xA000) { $info = 'l'; }
		elseif (($perms & 0x8000) == 0x8000) { $info = '-'; }
		elseif (($perms & 0x6000) == 0x6000) { $info = 'b'; }
		elseif (($perms & 0x4000) == 0x4000) { $info = 'd'; }
		elseif (($perms & 0x2000) == 0x2000) { $info = 'c'; }
		elseif (($perms & 0x1000) == 0x1000) { $info = 'p'; }
		else { $info = 'u'; }

		$info .= (($perms & 0x0100) ? 'r' : '-');
		$info .= (($perms & 0x0080) ? 'w' : '-');
		$info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));
		$info .= (($perms & 0x0020) ? 'r' : '-');
		$info .= (($perms & 0x0010) ? 'w' : '-');
		$info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));
		$info .= (($perms & 0x0004) ? 'r' : '-');
		$info .= (($perms & 0x0002) ? 'w' : '-');
		$info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));

		return $info;
	}

	// 获取文件权限（字符型，如-rw-rw-rw-）
	public static function LimitNum($fileName){
		return substr(sprintf("%o",fileperms($fileName)),-3);
	}

	// 检查目录下是否可创建目录
	public static function IsCreateDir($dir){
		if (substr($dir,-1) != '/'){ $dir .= '/'; }
		$dir .= 'OTCMS_test_v1.00';
		$txtPath = $dir .'/text.txt';
		if (@mkdir($dir, 0755)){
			fclose(fopen($txtPath, 'w'));
			@chmod($dir, 0755);
			self::DelDir($dir);
			return true;
		}else{
			return false;
		}
	}

	// 是否存在
	public static function IsExists($fileName,$mode=''){
		$jud = file_exists($fileName);
		if ($mode=='cn'){
			if ($jud){
				$jud='<span style="color:green;">存在</span>';
			}else{
				$jud='<span style="color:red;">不存在</span>';
			}
		}
		return $jud;
	}

	// 判断远程文件是否存在
	public static function IsRemoteExists($fileUrl){
		if (extension_loaded('curl')){
			$curl = curl_init($fileUrl); // 不取回数据
			curl_setopt($curl, CURLOPT_NOBODY, true);
			curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); // 发送请求
			$result = curl_exec($curl);
			$found = false; // 如果请求没有发送失败
			if ($result !== false) {
				// 再检查http响应码是否为200
				$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
				if ($statusCode == 200) {
					$found = true;
				}
			}
			curl_close($curl);

			return $found;
		}else{
			// 检测输入
			$fileUrl = trim($fileUrl);
			if (empty($fileUrl)) { return false; }
			$url_arr = parse_url($fileUrl);
			if (!is_array($url_arr) || empty($url_arr)){return false; }

			// 获取请求数据
			$host = $url_arr['host'];
			$path = $url_arr['path'] ."?".$url_arr['query'];
			$port = isset($url_arr['port']) ?$url_arr['port'] : "80";

			// 连接服务器
			$fp = fsockopen($host, $port, $err_no, $err_str,30);
			if (!$fp){ return false; }

			// 构造请求协议
			$request_str = "GET ".$path."HTTP/1.1";
			$request_str .= "Host:".$host."";
			$request_str .= "Connection:Close";

			// 发送请求
			fwrite($fp,$request_str);
			$first_header = fgets($fp, 1024);
			fclose($fp);

			//判断文件是否存在
			if (trim($first_header) == ""){ return false;}
			if (!preg_match("/200/", $first_header)){
				return false;
			}

			return true;
		}
	}


	// 清空File缓存
	// 受影响函数stat(),lstat(),file_exists(),is_writable(),is_readable(),is_executable(),is_file(),is_dir(),is_link(),filectime(),fileatime(),filemtime(),fileinode(),filegroup(),fileowner(),filesize(),filetype(),fileperms()
	public static function ClearCache($fileName){
		clearstatcache();
	}

	/* ***** 文件权限 END ***** */

	
	
	/* ***** 上传系列 START ***** */

	// 扩展上传文件参数
	// $fileArr:载入$_FILES[]
	public static function AddUploadPara($fileArr=array()){
		$fileArr['name'] = strtolower($fileArr['name']);
		//文件扩展名
		$fileArr['ext'] = self::GetExt($fileArr['name']);
		//生成新文件名
		srand();
		$fileArr['newName'] = self::GetNewName($fileArr['ext']);
	//	$fileArr['newName'] = md5(uniqid(microtime())) .'.'. $fileArr['ext'];
		return $fileArr;
	}


	// 上传文件
	public static function Upload($source, $target){
		// 如果一种函数上传失败，还可以用其他函数上传
		if (function_exists('move_uploaded_file') && @move_uploaded_file($source, $target)){
			@chmod($target, 0644);
			return $target;
		} elseif (@copy($source, $target)){
			@chmod($target, 0644);
			return $target;
		} elseif (@is_readable($source)){
			if ($fp = @fopen($source,'rb')){
				@flock($fp,2);
				$filedata = @fread($fp,@filesize($source));
				@fclose($fp);
			}
			if ($fp = @fopen($target, 'wb')){
				@flock($fp, 2);
				@fwrite($fp, $filedata);
				@fclose($fp);
				@chmod ($target, 0644);
				return $target;
			} else {
				return false;
			}
		}
	}


	// 判断文件是否是通过 HTTP POST 上传的
	public static function IsPostUpLoad($file){
		return function_exists('is_uploaded_file') && (is_uploaded_file($file) || is_uploaded_file(str_replace('\\\\', '\\', $file)));
	}


	// 判断上传文件类型
	public static function IsUploadType($fileExt,$fileType,$jud=true){
		if (empty($fileType)){
			if ($jud){
				return false;
			} else {
				die('<script language="javascript">alert("允许上传类型参数不能为空");history.back(-1);</script>');
			}
		} elseif (is_string($fileType)){
			switch ($fileType){
				case 'imageCommon':
					$fileTypeArr = array('gif','jpg','jpeg','png');
					break;
				case 'image':
					$fileTypeArr = array('bmp','gif','jpg','jpeg','png','ico','webp');
					break;
				case 'imageSwf':
					$fileTypeArr = array('bmp','gif','jpg','jpeg','png','ico','webp','swf');
					break;
				case 'html':
					$fileTypeArr = array('html','htm','txt');
					break;
				case 'office':
					$fileTypeArr = array('txt','doc','xls','ppt','docx','xlsx','pptx','wps','et','dps');
					break;
				case 'common':
					$fileTypeArr = array('bmp','jpg','jpeg','gif','png','ico','webp','tif','tiff','swf','txt','doc','xls','ppt','docx','xlsx','pptx','pdf','psd','rar','zip','avi','mp4','mpeg','mpg','ra','rm','rmvb','mov','qt','asf','wmv','iso','bin','img','flac','mp3','wma','wav','mod','cd','md','aac','mid','ogg','m4a','apk','ipa','torrent','epub','7z','wps','et','dps');
					break;
				case 'commonNoSwf':
					$fileTypeArr = array('bmp','jpg','jpeg','gif','png','ico','webp','tif','tiff','txt','doc','xls','ppt','docx','xlsx','pptx','pdf','psd','rar','zip','avi','mp4','mpeg','mpg','ra','rm','rmvb','mov','qt','asf','wmv','iso','bin','img','flac','mp3','wma','wav','mod','cd','md','aac','mid','ogg','m4a','apk','ipa','torrent','epub','7z','wps','et','dps');
					break;
				case 'noUpload':
					$fileTypeArr = array('asp','php','htm','html','exe','asa','cdx','cer','aspx');
					break;
				default :
					if ($jud){
						return false;
					} else {
						die('允许上传类型字符串参数值不存在（'. $fileType .'），请检查File_IsUpLoadType函数的参数。');
					}
					break;
			}
		} elseif (! is_array($fileTypeArr)){
			if ($jud){
				return false;
			} else {
				die('<script language="javascript">alert("参数值不正确");history.back(-1);</script>');
			}
		}

		if ($fileType=='noUpload'){
			if (in_array($fileExt,$fileTypeArr)){
				if ($jud){
					return false;
				} else {
					die('<script language="javascript">alert("不允许上传该文件类型。");history.back(-1);</script>');
				}
			} else {
				if ($jud){ return true; }
			}
		}else{
			if (! in_array($fileExt,$fileTypeArr)){
				if ($jud){
					return false;
				} else {
					die('<script language="javascript">alert("不允许上传该文件类型。");history.back(-1);</script>');
				}
			} else {
				if ($jud){ return true; }
			}
		}
	}

	/* ***** 上传系列 END ***** */

}

?>