PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

common.function.php
wget 'https://sme10.lists2.roe3.org/kodbox/app/function/common.function.php'
View Content
<?php
/*
* @link http://kodcloud.com/
* @author warlee | e-mail:kodcloud@qq.com
* @copyright warlee 2014.(Shanghai)Co.,Ltd
* @license http://kodcloud.com/tools/license/license.txt
*/

// 自动类加载路径添加;$addPath为false则不添加;
function import($path=false){
	static $_autoLoaderPath;
	if(empty($_autoLoaderPath)) {
		$_autoLoaderPath = array(
			MODEL_DIR,
			CORER_DIR,
			CLASS_DIR,
			SDK_DIR,
			CORER_DIR.'Cache/',
			CORER_DIR.'DB/',
			CORER_DIR.'IO/',
			CORER_DIR.'Task/',
			CORER_DIR.'Backup/',
		);
		if(!is_dir(MODEL_DIR)){
			$_autoLoaderPath = array(CLASS_DIR,SDK_DIR);
		}
	}
	if($path){
		if(is_dir($path)){
			$_autoLoaderPath[] = rtrim($path,'/').'/';
		}else if( is_file($path) ){		
			include_once $path;
			return array();
		}
	}	
	return $_autoLoaderPath;
}
// 类自动加载;通过autoLoaderPath的路径;
import(SDK_DIR.'archiveLib/');

function myAutoloader($name) {
	static $_cacheError = array();
	if(isset($_cacheError[$name])){
		return $_cacheError[$name];
	}
	$find   = import();
	$result = false;
	foreach ($find as $path) {
		$result = classPathAuto($path,$name);
		if($result) break;
	}
	if($result){
		include_once ($result);
		return true;
	}
	$_cacheError[$name] = false;
	// write_log(array($name,$result,$find),'test');
	return false;
}
spl_autoload_register('myAutoloader', true, true);

// 自动获取类文件名;兼容文件路径大小写敏感的情况(linux环境)
function classPathAuto($path,$name,$fileLast = '.class.php'){
	$path = rtrim($path,'/').'/';
	$nameUpper = strtoupper(substr($name,0,1)).substr($name,1);	
	$nameLower = strtolower($name);
	$result = false;
	// pr($path.$name.$fileLast);
	if(file_exists($path.$name.$fileLast)){
		$result = $path.$name.$fileLast;
	}else if(file_exists($path.$nameLower.$fileLast)){
		$result = $path.$nameLower.$fileLast;
	}else if(file_exists($path.$nameUpper.$fileLast)){
		$result = $path.$nameUpper.$fileLast;
	}
	return $result;
}

// 是否为控制台模式(控制台执行,或者curl请求)
function is_cli(){
	static $isFirst    = true;
	static $isCli 	   = false;
	if($isFirst){
		$isFirst = false;
		$isCli   = stristr(php_sapi_name(),'cli') ? true : false;
		if(strstr($_SERVER['HTTP_USER_AGENT'],'curl/')){$isCli = true;}
	}
	return $isCli;
}

/**
 * 文本字符串转换
 */
function mystr($str){
	$from = array("\r\n", " ");
	$to = array("<br/>", "&nbsp");
	return str_replace($from, $to, $str);
} 

// 清除多余空格和回车字符
function strip($str){
	return preg_replace('!\s+!', '', $str);
}
function timeFloat(){
	return microtime(true);
}

// 删除字符串两端的字符串
function str_trim($str,$remove){
	return str_rtrim(str_ltrim($str,$remove),$remove);
}
function str_ltrim($str,$remove){
	if(!$str || !$remove) return $str;
	while(substr($str,0,strlen($remove)) == $remove){
		$str = substr($str,strlen($remove));
	}
	return $str;
}
function str_rtrim($str,$remove){
	if(!$str || !$remove) return $str;
	while(substr($str,-strlen($remove)) == $remove){
		$str = substr($str,0,-strlen($remove));
	}
	return $str;
}

/**
 * 根据id获取短标识; 
 * 加入时间戳避免猜测;id不可逆
 * 
 * eg: 234==>4JdQ9Lgw;  100000000=>4LyUC2xQ
 */
function short_id($id){
	$id = intval($id) + microtime(true)*10000;
	$id = pack('H*',base_convert($id,10,16));
	$base64  = base64_encode($id);
    $replace = array('/'=>'_','+'=>'-','='=>'');
    return strtr($base64, $replace);
}

/**
 * 获取精确时间
 */
function mtime(){
	$t= explode(' ',microtime());
	$time = $t[0]+$t[1];
	return $time;
}

function guid(){
	return md5(microtime(true).rand_string(20));
}

/**
 * 过滤HTML
 * 
 * eg: </script><script>alert(1234)</script>
 * 允许url中字符;
 */
function clear_html($html, $br = true){
	$html = $html === null ? "" : $html;
	$replace = array('<','>','"',"'");
	$replaceTo = array('&lt;','&gt;','&quot;','&#39;');
	return str_replace($replace,$replaceTo,$html);
}
function clear_quote($html){
	$html = $html === null ? "" : $html;
	$replace = array('"',"'",'</script');
	$replaceTo = array('\\"',"\\'","<\/script");	
	return str_ireplace($replace,$replaceTo,$html);
}

// 反序列化攻击防护,不允许类对象;
function unserialize_safe($str){
	if(!$str) return false;
	if(preg_match("/O:(\d+):/",$str,$match)) return false;
	return unserialize($str);
}

/**
 * 过滤js、css等 
 */
function filter_html($html){
	$find = array(
		"/<(\/?)(script|i?frame|style|html|body|title|link|meta|\?|\%)([^>]*?)>/isU",
		"/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU",
		"/javascript\s*:/isU",
	);
	$replace = array("<\\1\\2\\3>","\\1\\2","");
	return preg_replace($find,$replace,$html);
}

function equal_not_case($str,$str2) {
	return strtolower($str) === strtolower($str2);
}
function in_array_not_case($needle, $haystack) {
	return in_array(strtolower($needle),array_map('strtolower',$haystack));
}

/**
 * 将obj深度转化成array
 * 
 * @param  $obj 要转换的数据 可能是数组 也可能是个对象 还可能是一般数据类型
 * @return array || 一般数据类型
 */
function obj2array($obj){
	if (is_array($obj)) {
		foreach($obj as &$value) {
			$value = obj2array($value);
		};unset($value);
		return $obj;
	} elseif (is_object($obj)) {
		$obj = get_object_vars($obj);
		return obj2array($obj);
	} else {
		return $obj;
	}
}


// 主动输出内容维持检测;(用户最终show_json情况; 文件下载情况不适用); 
// 没有输出时,php-fpm情况下,connection_aborted判断不准确
function check_abort_echo(){
	static $lastTime = 0;
	if(isset($GLOBALS['ignore_abort']) && $GLOBALS['ignore_abort'] == 1) return;
	
	// 每秒输出5次; 
	if(timeFloat() - $lastTime >= 0.2){
		ob_end_flush();echo str_pad('',1024*5);flush();
		$lastTime = timeFloat();
		// write_log(['check_abort_echo:'.ACTION,get_caller_msg()],'abort');
	}
	check_abort_now();
}
function check_abort(){
	if(isset($GLOBALS['ignore_abort']) && $GLOBALS['ignore_abort'] == 1) return;
	check_abort_now();
}
function check_abort_now(){
	if(connection_aborted()){write_log(get_caller_msg(),'abort');exit;}
}
function check_aborted(){
	// connection_aborted();
	exit;
}
function ignore_timeout(){
	$GLOBALS['ignore_abort'] = 1;
	@ignore_user_abort(true);
	set_timeout();
}

// 48 * 60 * 60  // 48h
function set_timeout($timeout=172800){
	static $firstRun = false;
	if($firstRun) return; //避免重复调用; 5000次100ms;
	$firstRun = true;
	
	@ini_set("max_execution_time",$timeout);
	@ini_set('request_terminate_timeout',$timeout);
	@set_time_limit($timeout);
	@ini_set('memory_limit', '4000M');//4G;
}


function check_code($code){
	ob_clean();
	header("Content-type: image/png");
	$width = 70;$height=27;
	$fontsize = 18;$len = strlen($code);
	$im = @imagecreatetruecolor($width, $height) or die("create image error!");
	$background_color = imagecolorallocate($im,255, 255, 255);
	imagefill($im, 0, 0, $background_color);  
	for ($i = 0; $i < 2000; $i++) {//获取随机淡色            
		$line_color = imagecolorallocate($im, mt_rand(180,255),mt_rand(160, 255),mt_rand(100, 255));
		imageline($im,mt_rand(0,$width),mt_rand(0,$height), //画直线
			mt_rand(0,$width), mt_rand(0,$height),$line_color);
		imagearc($im,mt_rand(0,$width),mt_rand(0,$height), //画弧线
			mt_rand(0,$width), mt_rand(0,$height), $height, $width,$line_color);
	}
	$border_color = imagecolorallocate($im, 160, 160, 160);   
	imagerectangle($im, 0, 0, $width-1, $height-1, $border_color);//画矩形,边框颜色200,200,200
	for ($i = 0; $i < $len; $i++) {//写入随机字串
		$text_color = imagecolorallocate($im,mt_rand(30, 140),mt_rand(30,140),mt_rand(30,140));
		imagechar($im,10,$i*$fontsize+6,rand(1,$height/3),$code[$i],$text_color);
	}
	imagejpeg($im);//显示图
	imagedestroy($im);//销毁图片
}

// 立即输出内容到页面; $replace 为true代表替换输出; 支持cli模式及cli下的curl请求;
function echoLog($log,$replace=false){
	if($GLOBALS['echoLogDisable']){return;}
	static $isFirst    = true;
	static $timeBefore = false;
	static $logOutBefore  = '';
	static $replaceID  = '';
	if($isFirst){
		ignore_timeout();
		@ob_end_clean();
		@header('X-Accel-Buffering: no');
		$isFirst = false;
	}
	
	$timeDelay  = 0.05;// 临时替换的输出内容, 50ms内只输出一次;
	$timeAt     = timeFloat();
	$replaceIdBefore = $replaceID;
	if(!$replace){$replaceID = '';}
	if($replace){
		$replaceID = $replaceID ? $replaceID:rand_string(10);
		if($timeBefore && ($timeAt - $timeBefore) < $timeDelay){$logOutBefore = $log;return;}
	}
	$timeBefore = $timeAt;
	$timeFloat 	= explode(".",mtime());
	$timeNow 	= date("H:i:s.",time()).sprintf("%03d",substr($timeFloat[1],0,3));
	if(is_cli()){
		// \b输出光标回退一个字符(并不清空,需要自行覆盖);\r输出光标回到行首; "\r\033[k";
		$chrPad = "\x01";$chrBack = "\x08";//$chrPad = "\x01" "\x06" "\x1b","\x18",""
		$padLen = $logOutBefore ? strlen(trim($logOutBefore,$chrPad)) : 0;
		$charReplace = array('<br/>'=>"\n",'&nbsp;'=>' ',"&quot;"=>'"');$append = "\n";
		if($replace){$charReplace = array('<br/>'=>"_|",'&nbsp;'=>' ',"&quot;"=>'"');$append = str_repeat($chrPad,2000);}
		
		$output = $timeNow.": ".str_replace(array_keys($charReplace),array_values($charReplace),$log);
		$padLenBefore = $padLen - strlen($output);// 填充到前一次长度,清除所有显示字符(比前一行短,前一行超出部分会出现残留)	
		$output = $output.str_pad("",$padLenBefore <= 0 ? 0 : $padLenBefore);
		$logOutBefore = $replace ? $output:'';
		// 最前面追加\r 兼容部分终端没有回退的情况;
		@ob_end_flush();echo "\r".str_repeat($chrBack,$padLen).$output.$append;@flush();
		return;
	}
	
	// write_log([$replace,$replaceIdBefore,$log,$logOutBefore,get_caller_msg()],'test');
	if(!$replace && $replaceIdBefore && !$log && $logOutBefore){$log = $logOutBefore;}
	if(!$log){return;} // 替换转不替换,log为空则保留前一次替换的内容;
	$logOutBefore = '';
	// 没有html标签时替换
	if(!strstr($log,'<') && !strstr($log,'>')){
		$log = str_replace(array(" "),array("&nbsp;"),$log);
		$log = str_replace(array('`',"\n"),array('`',"<br/>"),$log);
	}
	$timeStyle  = '<span style="display:inline-block;width:100px;font-size:12px;color:#888;font-family:monospace;padding-right:10px;">';
	$textStyle  = '<span style="display:inline-block;font-size:14px;color:#0084fe;font-family:monospace;">';
	$logNow 	= $timeStyle.$timeNow."</span>".$textStyle.$log.'</span>';
	$logOut		= "<div style='white-space:nowrap;' class='line' ".($replaceID ? 'id="line-'.$replaceID.'"':'').">".$logNow."</div>";

	// 替换输出: 针对上一次输出行进行替换; 当前不是替换输出且前一次为替换输出则移除前一行;  不干扰其他echo等输出的内容;
	if($replace){
		$script = 'var line=document.getElementById("line-'.$replaceID.'");';
		$script = $script.'if(!line){document.write(`'.$logOut.'`);}else{line.innerHTML=`'.$logNow.'`;}';
		$logOut = '<script>{'.$script.'}</script>';
	}else if(!$replace && $replaceIdBefore){
		$script = 'var line=document.getElementById("line-'.$replaceIdBefore.'");if(line){line.remove();}';
		$logOut = $logOut.'<script>{'.$script.'}</script>';
	}
	
	$jsNotify = '<script>{window.top.postMessage("logChange","*");}</script>';
	if(_get($GLOBALS['in'],'echoLogNotify') == '1'){$logOut .= $jsNotify;}
	@ob_end_flush();echo $logOut.str_pad('',2000);flush();
}


/**
 * 计算N次方根
 * @param  $num 
 * @param  $root 
 */
function croot($num, $root = 3){
	$root = intval($root);
	if (!$root) {
		return $num;
	} 
	return exp(log($num) / $root);
} 

function add_magic_quotes($array){
	foreach ((array) $array as $k => $v) {
		if (is_array($v)) {
			$array[$k] = add_magic_quotes($v);
		} else {
			$array[$k] = addslashes($v);
		} 
	} 
	return $array;
} 
// 字符串加转义
function add_slashes($string){
	if (!$GLOBALS['magic_quotes_gpc']) {
		if (is_array($string)) {
			foreach($string as $key => $val) {
				$string[$key] = add_slashes($val);
			} 
		} else {
			$string = addslashes($string);
		} 
	} 
	return $string;
} 

/**
 * hex to binary
 */
if (!function_exists('hex2bin')) {
	function hex2bin($hexdata)	{
		return pack('H*', $hexdata);
	}
}

if (!function_exists('gzdecode')) {
	function gzdecode($data){
		return gzinflate(substr($data,10,-8));
	}
}

function xml2json($decodeXml){
	$data = simplexml_load_string($decodeXml,'SimpleXMLElement', LIBXML_NOCDATA);
	return json_decode(json_encode($data),true);
}

/**
 * XML编码
 * @param mixed $data 数据
 * @param string $root 根节点名
 * @param string $item 数字索引的子节点名
 * @param string $attr 根节点属性
 * @param string $id   数字索引子节点key转换的属性名
 * @param string $encoding 数据编码
 * @return string
 */
function xml_encode($data, $root = 'think', $item = 'item', $attr = '', $id = 'id', $encoding = 'utf-8') {
    if (is_array($attr)) {
        $_attr = array();
        foreach ($attr as $key => $value) {
            $_attr[] = "{$key}=\"{$value}\"";
        }
        $attr = implode(' ', $_attr);
    }
    $attr = trim($attr);
    $attr = empty($attr) ? '' : " {$attr}";
    $xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
    $xml .= "<{$root}{$attr}>";
    $xml .= data_to_xml($data, $item, $id);
    $xml .= "</{$root}>";
    return $xml;
}

/**
 * 数据XML编码
 * @param mixed  $data 数据
 * @param string $item 数字索引时的节点名称
 * @param string $id   数字索引key转换为的属性名
 * @return string
 */
function data_to_xml($data, $item = 'item', $id = 'id') {
    $xml = $attr = '';
    foreach ($data as $key => $val) {
        if (is_numeric($key)) {
            $id && $attr = " {$id}=\"{$key}\"";
            $key = $item;
        }
        $xml .= "<{$key}{$attr}>";
        $xml .= (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
        $xml .= "</{$key}>";
    }
    return $xml;
}

/**
 * 数组key连接的值设置
 * $arr  data.list.order  <==> $arr['data']['list']['order']
 */
function array_set_value(&$array,$key,$value){
	if(!is_array($array)) {
		$array = array();
	}
	$keyArr  = explode(".",$key);
	$tempArr = &$array;
	$count   = count($keyArr);
	for ($i=0; $i < $count; $i++) {
		$k = $keyArr[$i];
		if($i+1 == $count ){
			$tempArr[$k] = $value;
			return true;
		}
		if(!isset($tempArr[$k])){
			$tempArr[$k] = array();
		}
		$tempArr = &$tempArr[$k];
		if(!is_array($tempArr)){//有值并且不是数组的情况
			return false;
		}
	}
	return false;
}

function _get($array,$key,$default=null){
	return array_get_value($array,$key,$default);
}

/**
 * 数组key连接的值获取
 * $arr  data.list.order  <==> $arr['data']['list']['order']
 */
function array_get_value(&$array,$key,$default=null){
	if(!is_array($array)) return $default;
	if(isset($array[$key])) return $array[$key];
	if(strpos($key,'.') === false){
		return isset($array[$key]) ? $array[$key] : $default;
	}
	
	$keyArr  = explode(".",$key);
	$tempArr = $array;
	$total   = count($keyArr);
	for ($i=0; $i < $total; $i++) {
		$k = $keyArr[$i];
		if(!isset($tempArr[$k])) return $default;
		if( $i+1 == $total ){
			return $tempArr[$k];
		}
		$tempArr = $tempArr[$k];
	}
	return $default; 
}

// 数组按照keyArr保持顺序;
function array_sort_keep($array,$key,$keyArr){
	$result   = array();
	$arrayNew = array_to_keyvalue($array,$key);
	foreach ($keyArr as $key){
		if(!isset($arrayNew[$key.''])){continue;}
		$result[] = $arrayNew[$key.''];
	}
	return $result;	
}

/**
 * 二维数组按照指定的键值进行排序,默认升序
 * 
 * @param  $field 排序字段; 为空时按一维数组排序;
 * @param  $type  升序降序 默认升序
 * @param  $fieldDefault 额外排序字段(当$field相等时的第二个排序字段)
 * 
 * @return array 
 * $array = array(
 * 		array('name'=>'手机','brand'=>'诺基亚','price'=>1050),
 * 		array('name'=>'手表','brand'=>'卡西欧','price'=>960)
 * );
 * $out = array_sort_by($array,'price');
 * $out = array_sort_by($array,'info.count');
 */
function array_sort_by($records, $field='', $orderDesc=false,$fieldMore=false){
	if(!is_array($records) || !$records) return array();
	if($fieldMore && $fieldMore == $field){$fieldMore = false;}
	if(count($records) == 1) return $records;
	$order   = $orderDesc ? SORT_DESC : SORT_ASC;
	$flag    = SORT_NATURAL | SORT_FLAG_CASE;//SORT_REGULAR; SORT_NATURAL | SORT_FLAG_CASE
	$sortBy1 = array();$sortBy2 = array();
	if(!$field){array_multisort($records,$order,$flag,$records);return $records;}

	foreach ($records as $item){
		$sortBy1[] = isset($item[$field]) ? $item[$field]: _get($item,$field,'');
		if($fieldMore){$sortBy2[] = isset($item[$fieldMore]) ? $item[$fieldMore]: _get($item,$fieldMore,'');}
	}
	if($fieldMore){ array_multisort($sortBy1,$order,$flag,  $sortBy2,$order,$flag,  $records);}
	if(!$fieldMore){array_multisort($sortBy1,$order,$flag,  $records);}
	return $records;
}

if (!function_exists('array_column')) {
    function array_column($array, $columnKey, $indexKey = null) {
        $result = array();
        foreach ($array as $subArray) {
            if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
                $result[] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
            } elseif (array_key_exists($indexKey, $subArray)) {
                if (is_null($columnKey)) {
                    $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
                    $result[$index] = $subArray;
                } elseif (array_key_exists($columnKey, $subArray)) {
                    $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
                    $result[$index] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
                }
            }
        }
        return $result;
    }
}


/**
 * 遍历数组,对每个元素调用 $callback,假如返回值不为假值,则直接返回该返回值;
 * 假如每次 $callback 都返回假值,最终返回 false
 * 
 * @param  $array 
 * @param  $callback 
 * @return mixed 
 */
function array_try($array, $callback){
	if (!$array || !$callback) {
		return false;
	} 
	$args = func_get_args();
	array_shift($args);
	array_shift($args);
	if (!$args) {
		$args = array();
	} 
	foreach($array as $v) {
		$params = $args;
		array_unshift($params, $v);
		$x = call_user_func_array($callback, $params);
		if ($x) {
			return $x;
		} 
	} 
	return false;
} 

// 取出数组中第n项
function array_get_index($array,$index){
	foreach($array as $k=>$v){
		$index--;
		if($index<0) return array($k,$v);
	}
}

/**
 * 根据数组子项去重
 */
function array_unique_by_key($array,$key){
	$array = array_to_keyvalue($array,$key);
	return array_values($array);
}

// 多条数组筛选子元素:获取多条数组中项的某个字段构成值数组
function array_field_values($array,$field){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	foreach ($array as $val) {
		if(is_array($val) && isset($val[$field])){
			$result[] = $val[$field];
		}		
	}
	return $result;
}

// 单条数据筛选key:只筛选返回数组中,指定key的部分
function array_field_key($array,$field){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	foreach ($field as $val) {
		if(isset($array[$val])){
			$result[$val] = $array[$val];
		}
	}
	return $result;
}

// 多条数组筛选:筛选项中key为$field,值为$field的部分;
function array_filter_by_field($array,$field,$value){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	foreach ($array as $key => $val){
		if($val[$field] != $value) continue;
		if(is_int($key)){
			$result[] = $val;
		}else{
			$result[$key] = $val;
		}
	}
	return $result;
}
function array_remove_by_field($array,$field,$value){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	foreach ($array as $key => $val) {
		if($val[$field] == $value) continue;
		if(is_int($key)){
			$result[] = $val;
		}else{
			$result[$key] = $val;
		}
	}
	return $result;
}

function array_find_by_field($array,$field,$value){
	if(!is_array($array) || !$array) return null;
	foreach ($array as $val) {
		if($val[$field] == $value) return $val;
	}
	return null;
}

function array_page_split($array,$page=false,$pageNum=false){
	$page 		= intval($page ? $page : $GLOBALS['in']['page']);
	$page		= $page <= 1 ? 1 : $page;
	$pageMax    = 5000;
	$pageNum 	= intval($pageNum ? $pageNum : $GLOBALS['in']['pageNum']);
	$pageNum	= $pageNum <= 5 ? 5 : ($pageNum > $pageMax ? $pageMax: $pageNum);
	
	$array 		= is_array($array) ? $array :array();
	$pageTotal	= ceil(count($array) / $pageNum);
	$page		= $page <= 1 ? 1  : ($page >= $pageTotal ? $pageTotal : $page);
	$result     = array(
		'pageInfo' => array(
			'totalNum'	=> count($array),
			'pageNum'	=> $pageNum,
			'page'		=> $page,
			'pageTotal'	=> $pageTotal,
		),
		'list' => array_slice($array,($page-1) * $pageNum,$pageNum)
	);
	return $result;	
}

/**
 * 删除数组子项的特定key的数据
 * $keyArray 单个key字符串,或多个key组成的数组;
 * eg: [{a:1,b:2},{a:33,b:44}]  ==> [{a:1},{a:33}]
 */
function array_remove_key(&$array, $keyArray){
	if(!is_array($array) || !$array) return array();
	if(!is_array($keyArray)) $keyArray = array($keyArray);
	foreach ($array as &$item) {
		foreach ($keyArray as $key) {
			if(isset($item[$key])){
				unset($item[$key]);
			}
		}
	};unset($item);
	return $array;
}

// 删除数组某个值
function array_remove_value($array, $value){
	if(!is_array($array) || !$array) return array();
	$isNumericArray = true;
	foreach ($array as $key => $item) {
		if ($item === $value) {
			if (!is_int($key)) {
				$isNumericArray = false;
			}
			unset($array[$key]);
		}
	}
	if ($isNumericArray) {
		$array = array_values($array);
	}
	return $array;
}

// 获取数组key最大的值
function array_key_max($array){
	if(count($array)==0){
		return 1;
	}
	$idArr = array_keys($array);
	rsort($idArr,SORT_NUMERIC);//id从高到底
	return intval($idArr[0]);
}

/**
 * 将纯数组的元素的某个key作为key生成新的数组
 * [{"id":34,"name":"dd"},{"id":78,"name":"dd"}]

 * (arr,'id')=>{34:{"id":34,"name":"dd"},78:{"id":78,"name":"dd"}}  //用元素key的值作为新数组的key
 * (arr,'id','name')=>{34:"dd",78:"name"}	//用元素key的值作为新数组的key,只取对应$contentKey的值作为内容;
 * (arr,'','name')=>["dd","name"]  			//只取数组元素的特定项构成新的数组
 */
function array_to_keyvalue($array,$key='',$contentKey=false,$hasSub=false){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	if(!$key){return array_column($array,$contentKey);}
	$contentKey = $contentKey ? $contentKey : null;
	if(!$hasSub){return array_column($array,$contentKey,$key);}

	// 支持取值的下层;
	foreach ($array as $item) {
		$theValue = $contentKey ? _get($item,$contentKey):$item;
		if($key){
			$theKey = _get($item,$key).'';
			$result[$theKey] = $theValue;
		}elseif(!is_null($theValue)){
			$result[] = $theValue;
		}
	}
	return $result;
}
function array_to_int($array){
	$result = array();
	foreach($array as $v){
		$result[] = intval($v);
	}
	return $result;
}

/**
 * 根据parentid获取家谱树列表
 * @param [type] $array
 * @param [type] $id
 * @param string $idKey		// id名称
 * @param string $pidKey	// pid名称
 * @return void
 */
function array_tree($array, $id, $idKey = 'id', $pidKey = 'parentid'){
	$tree = array();
	while($id != '0'){
		foreach ($array as $v) {
			if(!isset($v[$pidKey])) $v[$pidKey] = '0';
			if($v[$idKey] == $id){
				$tree[] = $v;
				$id = $v[$pidKey];
				break;
			}
		}
	}
	return $tree;
}

/**
 * 迭代获取子孙树——必须要有根部门(pid=空)
 * @param [type] $rows
 * @param string $pid
 * @return void
 */
function array_sub_tree($rows, $pid = 'parentid', $id = 'id') {
	$rows = array_column ( $rows, null, $id );
	foreach ( $rows as $key => $val ) {
		if ( $val[$pid] ) {
			if ( isset ( $rows[$val[$pid]] )) {
				$rows[$val[$pid]]['children'][$val[$id]] = &$rows[$key];
			}
		}
	}
	foreach ( $rows as $key => $val ) {
		if ( $val[$pid] ) unset ( $rows[$key] );	// 根元素的parentid需为空,以此删除其他项
	}
	return $rows;
}

/**
 * 将数组的元素的某个key作为key生成新的数组;值为数组形式;
 * [{"id":34,"type":1},{"id":78,"type":2},{"id":45,"type":1}]

 * (arr,'type')=>{1:[{"id":34,"name":"dd"},{"id":45,"type":1}],2:[{"id":78,"name":"dd"}]}
 * (arr,'name','name')=>{1:[34,45],2:[78]}	//保留对应可以的内容
 */
function array_to_keyvalue_group($array,$key='',$contentKey=false){
	$result = array();
	if(!is_array($array) || !$array) return $result;
	foreach ($array as $item) {
		$theValue = $item;
		if($contentKey){
			$theValue = $item[$contentKey];
		}
		if(!isset($result[$item[$key]])){
			$result[$item[$key]] = array();
		}
		$result[$item[$key]][] = $theValue;
	}
	return $result;
}

/**
 * 合并两个数组,保留索引信息;
 */
function array_merge_index($array,$array2){
	$result = $array;
	if(!is_array($array) || !$array) return $result;
	foreach ($array2 as $key => $value) {
		$result[$key] = $value;
	}
	return $result;
}

/**
 * 二维数组,根据键值向前、后移动
 * @param string $swap	prev next
 * @return void
 */
function array_swap_keyvalue($array, $key, $value, $swap = 'next'){
    foreach ($array as $idx => $item) {
        if(isset($item[$key]) && $item[$key] == $value){
            $index = $idx;
            break;
        }
    }
    if(!isset($index)) return $array;
    $swap == 'prev' && $index = $index -1;

    $before = array_slice($array,0,$index);
    $middle = array_reverse(array_slice($array,$index,2));
    $after = array_slice($array,$index + 2);
    return array_merge($before,$middle,$after);
}

//set_error_handler('errorHandler',E_ERROR|E_PARSE|E_CORE_ERROR|E_COMPILE_ERROR|E_USER_ERROR);
register_shutdown_function('fatalErrorHandler');
function errorHandler($err_type,$errstr,$errfile,$errline){
	if (($err_type & E_WARNING) === 0 && ($err_type & E_NOTICE) === 0) {
		return false;
	}
	$arr = array(
		$err_type,
		$errstr,
		//" in [".$errfile.']',
		" in [".get_path_this(get_path_father($errfile)).'/'.get_path_this($errfile).']',
		'line:'.$errline,
	);
	$str = implode("  ",$arr)."<br/>";
	show_tips($str);
}

//捕获fatalError
function fatalErrorHandler(){
	$e = error_get_last();
	if(!$e) return;
	switch($e['type']){
		case E_ERROR:
		case E_PARSE:
		case E_CORE_ERROR:
		case E_COMPILE_ERROR:
		case E_USER_ERROR:
			errorHandler($e['type'],$e['message'],$e['file'],$e['line']);
			break;
		case E_NOTICE:break;
		default:break;
	}
}

function show_tips($message,$url= '', $time = 3,$title = ''){
	$res = Hook::trigger("show_tips",$message,$url,$time,$title);
	if(!empty($res) && is_array($res)) {
		$vars = array('message', 'url', 'time', 'title');
		foreach ($vars as $key) {
			if (isset($res[$key])) $$key = $res[$key];
		}
    }
	if($title == ''){$title = "出错了! (warning!)";}
	if(isset($GLOBALS['SHOW_OUT_EXCEPTION']) && $GLOBALS['SHOW_OUT_EXCEPTION']){
		throw new Exception($title.': '.$message);
	}
	ob_get_clean();
	header('Content-Type: text/html; charset=utf-8');
	$goto = "content='$time;url=$url'";
	$info = "{$time}s 后自动跳转, <a href='$url'>立即跳转</a>";
	if ($url == "") {//是否自动跳转
		$goto = "";$info = "";
	}
	//移动端;报错输出
	if(isset($_REQUEST['HTTP_X_PLATFORM'])){
		show_json($message,false);
	}
	if(is_array($message) || is_object($message)){
		$message = json_encode_force($message);
		$message = htmlspecialchars($message);
		$message = str_replace(array('\n','\/'),array("<br/>",'/'),stripslashes($message));
		$message = "<pre>".$message.'</pre>';
	}else{
		$message = filter_html(nl2br($message));
	}
	$template = TEMPLATE.'common/showTips.html';
	if(file_exists($template)){
		include($template);exit;
	}
	echo<<<END
<html>
	<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover, shrink-to-fit=no" />
	<meta http-equiv='refresh' $goto charset="utf-8">

	<style>
	body{background: #f6f6f6;}
	#msgbox{box-shadow: 0px 10px 40px rgba(0, 0, 0, 0.1);border-radius: 5px;border-radius: 5px;background:#fff;
    font-family: "Lantinghei SC","Hiragino Sans GB","Microsoft Yahei",Helvetica,arial,sans-serif;line-height: 1.5em;
	color:888;margin:10% auto;width:500px;font-size:13px;color:#666;word-wrap: break-word;word-break: break-all;max-width: 90%;box-sizing: border-box;max-height:90%;overflow: auto;padding:30px 30px;position: relative;}
	#msgbox #info{margin-top: 10px;color:#aaa;}
	#msgbox #title{color: #333;border-bottom: 1px solid #eee;padding: 10px 0;margin:0 0 15px;font-size:22px;font-weight:200;}
	#msgbox #info a{color: #64b8fb;text-decoration: none;padding: 2px 0px;border-bottom: 1px solid;}
	#msgbox a{text-decoration:none;color:#2196F3;}
	#msgbox a:hover{color:#f60;border-bottom:1px solid}
	#msgbox .desc{color:#f60;font-weight: 600;padding: 10px 0 10px;}
	#msgbox pre{word-break: break-all;word-wrap: break-word;white-space: pre-wrap;
		background: #002b36;padding:1em;color: #839496;border-left: 6px solid #8e8e8e;border-radius: 3px;}
	</style>
	</head>
	
	<body>
	<div id="msgbox">
		<div id="title">$title</div>
		<div id="message">$message</div>
		<div id="info">$info</div>
	</div>
	</body>
</html>
END;
	exit;
}

function get_caller_trace($trace,$needArgs = true) {
	$trace = is_array($trace) ? $trace : array();
	$traceText = array();
	$maxLoad = 50; //数据过多自动丢失后面内容;
	if(count($trace) > $maxLoad){
		$trace = array_slice($trace,count($trace) - $maxLoad);
	}
	$trace = array_reverse($trace);
	$ignoreMethod = array('get_caller_info','think_exception','think_trace');
	$keepArgs     = array('Action','ActionApply','ActionCall');
	foreach($trace as $i => $call){
		$method = $call['function'] ? $call['function'] : '';
		if(in_array($method,$ignoreMethod)) continue;
		if(isset($call['class']) && $call['class'] == 'ClassBaseCall') continue;
		if(isset($call['object']) && is_object($call['object'])) {
			$call['object'] = get_class_name($call['object']); 
		}else if(isset($call['class'])){
			$call['object'] = $call['class'];
		}
		
		$file = isset($call['file']) ? get_path_this(get_path_father($call['file'])).'/'.get_path_this($call['file']) : '';
		$traceText[$i] = isset($call['line']) ? $file.'['.$call['line'].'] ' : $file;
		$traceText[$i].= empty($call['object'])? '': $call['object'].$call['type']; 
		if( $method =='show_json' || $method =='think_trace'){
			$traceText[$i].= $method.'(args)';
		}else{
			$temp  = (isset($call['args']) && is_array($call['args'])) ? array_values($call['args']) : array();
			$args  = array();	// 深拷贝,避免引用传参被修改
			$maxLength = 200;//参数最长长度
			foreach($temp as $j=>$value){
				if(!$needArgs && !in_array($method,$keepArgs)){
					$param = (is_string($value) || is_numeric($value) || !$value) ? $value.'':'[obj]';
					if(is_array($value)){
						$param = json_encode($value);
						if(strlen($param) >= 50){$param = substr($param,0,50)."...";}
					}
					if(strlen($param) > $maxLength){$param = mb_substr($param,0,$maxLength).'...';}
					$args[] = '"'.$param.'"';continue;
				}
				$value = @json_decode(@json_encode($value));
				$param = json_encode(array_parse_deep($value));
				$param = str_replace(array('\\/','\/','\\\\/','\"'),array('/','/','/',"'"),$param);
				if(substr($param,0,1) == '['){$param = substr($param,1,-1);}
				if(strlen($param) > $maxLength){$param = mb_substr($param,0,$maxLength).'...';}
				$args[] = $param;
			}
			$traceText[$i] .= $method ? $method.'('.implode(',',$args).')' : '';
		}
	}
	return array_values($traceText);
}

function get_caller_info($needArgs = true) { 
	$trace = debug_backtrace();
	return get_caller_trace($trace,$needArgs);
}
function get_caller_msg($trace = false) { 
	return get_caller_msg_parse(get_caller_info(),$trace);
}
function get_caller_msg_parse($msg,$trace = false) { 
	$msg = array_slice($msg,0,count($msg) - 1);
	$msg['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
	if($trace){
		$msg['trace']  = think_trace('[trace]');
	}
	$msg = json_encode_force($msg);
	$msg = str_replace(array('\\/','\/','\\\\/','\"'),array('/','/','/','"'),$msg);
	return $msg;
}



// 去除json中注释部分; json允许注释
// 支持 // 和 /*...*/注释 
function json_comment_clear($str){
	$result = '';
	$inComment = false;
	$commentType = '//';// /*,//
	$quoteCount  = 0;
	$str = str_replace(array('\"',"\r"),array("\\\0","\n"),$str);

	for ($i=0; $i < strlen($str); $i++) {
		$char = $str[$i];
		if($inComment){
			if($commentType == '//' && $char == "\n"){
				$result .= "\n";
				$inComment = false;
			}else if($commentType == '/*' && $char == '*' && $str[$i+1] == '/'){
				$i++;
				$inComment = false;
			}
		}else{
			if($str[$i] == '/'){
				if($quoteCount % 2 != 0){//成对匹配,则当前不在字符串内
					$result .= $char;
					continue;
				}	
				if($str[$i+1] == '*'){
					$inComment = true;
					$commentType = '/*';
					$i++;
					continue;
				}else if($str[$i+1] == '/'){
					$inComment = true;
					$commentType = '//';
					$i++;
					continue;
				}
			}else if($str[$i] == '"'){
				$quoteCount++;
			}
			$result .= $char;
		}
	}
	$result = str_replace("\\\0",'\"',$result);
	$result = str_replace("\n\n","\n",$result);
	return $result;
}
function json_space_clear($str){
	$result = '';
	$quoteCount  = 0;
	$str = str_replace(array('\"',"\r"),array("\\\0","\n"),$str);
	for ($i=0; $i < strlen($str); $i++) {
		$char = $str[$i];
		//忽略不在字符串中的空格 tab 和换行
		if( $quoteCount % 2 == 0 &&
			($char == ' ' || $char == '	' || $char == "\n") ){
			continue;
		}
		if($char == '"'){
			$quoteCount ++;
		}
		$result .= $char;
	}
	$result = str_replace("\\\0",'\"',$result);
	return $result;
}

function json_decode_force($str){
	$str = trim($str,'');
	$str = json_comment_clear($str);
	$str = json_space_clear($str);

	//允许最后一个多余逗号(todo:字符串内)
	$str = str_replace(array(',}',',]',"\n","\t"),array('}',']','',' '),$str);
	$result = json_decode($str,true);
	if(!$result){
		//show_json($result,false);
	}
	return $result;
}
function json_encode_force($json){
	if(defined('JSON_PRETTY_PRINT')){
		$jsonStr = json_encode($json,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
	}else{
		$jsonStr = json_encode($json);
	}
	if($jsonStr === false){
		$json = array_parse_deep($json);
		$parse = new Services_JSON();
		$jsonStr = $parse->encode($json);
	}
	return $jsonStr;
}

function array_parse_deep($arr){
	if(!is_array($arr)) return $arr;
	foreach ($arr as $key => $obj) {
		if(is_resource($obj) || is_object($obj)){ // 资源无法json_encode;
			$arr[$key] = get_class_name($obj);
		}else if(is_array($obj)){
			$arr[$key] = array_parse_deep($obj);
		}
	}
	return $arr;
}

function get_class_name($obj){
	if(is_resource($obj)){ // 资源无法json_encode;
		ob_start();echo $obj;$id = ob_get_clean();
		$id = str_replace('Resource id #','',$id);
		$result = '{'.$id."}@".get_resource_type($obj);
	}else if(is_object($obj)){
		$id = substr(md5(spl_object_hash($obj)),0,3);
		$result = '{'.$id."}#".get_class($obj);
	}
	return $result;
}


/**
 * 打包返回AJAX请求的数据
 * @params {int} 返回状态码, 通常0表示正常
 * @params {array} 返回的数据集合
 */
function show_json($data=false,$code = true,$info='',$infoMore=''){
	if(!isset($GLOBALS['showJsonTimeStart'])){
		$GLOBALS['showJsonTimeStart'] = TIME_FLOAT;
	}
	$result  = array(
		'code'		=> $code,
		'timeUse'	=> sprintf('%.4f',mtime() - $GLOBALS['showJsonTimeStart']),
		'timeNow'	=> sprintf('%.4f',mtime()),
		'data'	 	=> $data
	);
	if(isset($GLOBALS['SHOW_OUT_EXCEPTION']) && $GLOBALS['SHOW_OUT_EXCEPTION']){
		throw new Exception(json_encode_force($result));
	}
	
	if($info !== ''){$result['info'] = $info;}
	if($infoMore !== ''){$result['infoMore'] = $infoMore;}
	// 有值且为true则返回,清空输出并返回数据结果
	if(isset($GLOBALS['SHOW_JSON_NOT_EXIT']) && $GLOBALS['SHOW_JSON_NOT_EXIT']){
		// 保留第一个show_json调用输出;ob_get_clean 后该次置空; 
		if(isset($GLOBALS['SHOW_JSON_NOT_EXIT_DONE']) && $GLOBALS['SHOW_JSON_NOT_EXIT_DONE']){return;}
		$GLOBALS['SHOW_JSON_NOT_EXIT_DONE'] = 1;
		write_log(array('SHOW_JSON_NOT_EXIT',$result,'call'=>get_caller_info()));
		if(!ob_get_length()){echo json_encode_force($result);}
		return;
	}

	// 处理输出数据调用;
	if($GLOBALS['SHOW_JSON_RESULT_PARSE']){
		$resultNew = $GLOBALS['SHOW_JSON_RESULT_PARSE']($result);
		$result = is_array($resultNew) ? $resultNew:$result;
		$GLOBALS['SHOW_JSON_RESULT_PARSE'] = false;
	}
	
	$temp = Hook::trigger("show_json",$result);
	if(is_array($temp)){$result = $temp;}
	if(defined("GLOBAL_DEBUG") && GLOBAL_DEBUG==1){
		// $result['in']   = $GLOBALS['in'];
		$result['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
		$result['call']   = get_caller_info();
		$result['trace']  = think_trace('[trace]');
	}
	check_abort(); // hook之后检测处理; task缓存保持;
	
	@ob_get_clean();
	if(	isset($_SERVER['HTTP_ACCEPT_ENCODING']) && 
		strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip')){
		@ob_start('ob_gzhandler');// 自动开启gzip;
	}
	
	if(!headers_sent()){
		header("X-Powered-By: kodbox.");
		header('Content-Type: application/json; charset=utf-8');
		if(!$code){header("X-Request-Error: 1");}
	}
	$callback = _get($GLOBALS['in'],'callback','');
	$output   = json_encode_force($result);
	if($callback && $GLOBALS['config']['jsonpAllow']){
		if(!preg_match("/^[0-9a-zA-Z_.]+$/",$callback)){
			die("calllback error!");
		}
		$output = $callback.'('.$output.');';
	}
	echo $output;
	exit;
}

function show_trace(){
	echo '<pre>';
	echo json_encode_force(get_caller_info());
	echo '</pre>';
	exit;
}

function file_sub_str($file,$start=0,$len=0){
	$size = filesize_64($file);
	if($start < 0 ){
		$start = $size + $start;
		$len = $size - $start;
	}
	if($len <= 0) return '';
    $fp = fopen($file,'r');
    fseek_64($fp,$start);
    $res = fread($fp,$len);
    fclose($fp);
    return $res;
}
function str2hex($string){
	$hex='';
	for($i=0;$i<strlen($string);$i++){
		$hex .= sprintf('%02s ',dechex(ord($string[$i])));
	}
	$hex = strtoupper($hex);
	return $hex;
}

function hex2str($hex){
	$hex = str_replace(" ",'',$hex);
	$string='';
	for ($i=0; $i < strlen($hex)-1; $i+=2){
		$string .= chr(hexdec($hex[$i].$hex[$i+1]));
	}
	return $string;
}

// if(!function_exists('json_encode')){
// 	function json_encode($data){
// 		$json = new Services_JSON();
// 		return $json->encode($data);
// 	}
// 	function json_decode($json_data,$toarray =false) {
// 		$json = new Services_JSON();
// 		$array = $json->decode($json_data);
// 		if ($toarray) {
// 			$array = obj2array($array);
// 		}
// 		return $array;
// 	}
// }

/**
 * 去掉HTML代码中的HTML标签,返回纯文本
 * @param string $document 待处理的字符串
 * @return string 
 */
function html2txtClear($document){
	$search = array ("'<script[^>]*?>.*?</>'si", // 去掉 javascript
		"'<[\/\!]*?[^<>]*?>'si", // 去掉 HTML 标记
		"'([\r\n])[\s]+'", // 去掉空白字符
		"'&(quot|#34);'i", // 替换 HTML 实体
		"'&(amp|#38);'i",
		"'&(lt|#60);'i",
		"'&(gt|#62);'i",
		"'&(nbsp|#160);'i",
		"'&(iexcl|#161);'i",
		"'&(cent|#162);'i",
		"'&(pound|#163);'i",
		"'&(copy|#169);'i", 
		// "'&#(\d+);'e");
		"'&#(\d+);'"); // 作为 PHP 代码运行
	$replace = array ("",
		"",
		"",
		"\"",
		"&",
		"<",
		">",
		" ",
		chr(161),
		chr(162),
		chr(163),
		chr(169),
		"chr(\\1)");
	$text = preg_replace_callback ($search, function(){return $replace;}, $document);
	return $text;
}

function html2txt($str){  
	$str = preg_replace("/<style .*?<\/style>/is", "", $str);$str = preg_replace("/<script .*?<\/script>/is", "", $str);
	$str = preg_replace("/<br \s*\/?\/>/i", "\n", $str);
	$str = preg_replace("/<\/?p>/i", "\n\n", $str);
	$str = preg_replace("/<\/?td>/i", "\n", $str);
	$str = preg_replace("/<\/?div>/i", "\n", $str);
	$str = preg_replace("/<\/?blockquote>/i", "\n", $str);
	$str = preg_replace("/<\/?li>/i", "\n", $str);
	$str = preg_replace("/\&nbsp\;/i", " ", $str);
	$str = preg_replace("/\&nbsp/i", " ", $str);
	$str = preg_replace("/\&amp\;/i", "&", $str);
	$str = preg_replace("/\&amp/i", "&", $str);  
	$str = preg_replace("/\&lt\;/i", "<", $str);
	$str = preg_replace("/\&lt/i", "<", $str);
	$str = preg_replace("/\&ldquo\;/i", '"', $str);
	$str = preg_replace("/\&ldquo/i", '"', $str);
	$str = preg_replace("/\&lsquo\;/i", "'", $str);
	$str = preg_replace("/\&lsquo/i", "'", $str);
	$str = preg_replace("/\&rsquo\;/i", "'", $str);
	$str = preg_replace("/\&rsquo/i", "'", $str);
	$str = preg_replace("/\&gt\;/i", ">", $str); 
	$str = preg_replace("/\&gt/i", ">", $str); 
	$str = preg_replace("/\&rdquo\;/i", '"', $str); 
	$str = preg_replace("/\&rdquo/i", '"', $str); 
	$str = strip_tags($str);
	$str = html_entity_decode($str, ENT_QUOTES, $encode);
	$str = preg_replace("/\&\#.*?\;/i", "", $str); 
	return $str;
}


// 获取内容第一条
function match_text($content, $preg){
	$preg = "/" . $preg . "/isU";
	preg_match($preg, $content, $result);
	return is_array($result) ? $result[1]:false;
} 
// 获取内容,获取一个页面若干信息.结果在 1,2,3……中
function match_all($content, $preg){
	$preg = "/" . $preg . "/isU";
	preg_match_all($preg, $content, $result);
	return $result;
}

if(!function_exists('mb_substr')){
    function mb_substr($str,$start,$len,$charset='') {   
        return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$start.'}'.
			'((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s','$1',$str);
    }
}
if(!function_exists('mb_strlen')){
    function mb_strlen($str,$charset='') {   
        preg_match_all("/./u", $str, $ar); 
        return count($ar[0]); 
    }
}

/**
 * 字符串截取自动修复;(仅utf8 字符串); 去除前后不足一个字符的字节
 * 截取多余部分用replace替换;
 * 只处理头和尾;
 * 
 * $str = substr("我的中国心",1,-2); 
 * $str = utf8Repair($str);
 * 
 * 1 1-128
 * 2 192-223, 128-191
 * 3 224-239, 128-191, 128-191
 * 4 240-247, 128-191, 128-191, 128-191
 */
function utf8Repair($str,$replace=''){
	$start = 0;$char = ord($str[$start]);
	while($char >= 128 && $char <= 191 && $start <= 5){
		$start ++;$char = ord($str[$start]);
	}

	$length  = strlen($str);$charByte = 0;
	$endFrom = $length - 5 > 0 ? $length - 5 : 0;
	for($end = $endFrom; $end < $length; $end++){
		$char = ord($str[$end]);
		if ($char <= 128 || ($char >= 128 && $char <= 191)) continue;
		if ($char > 239) {$charByte = 4;}
		else if ($char > 223) {$charByte = 3;}
		else if ($char > 191) {$charByte = 2;}
		else {return $str;}

		if ($end + $charByte - 1 == $length - 1){$end = $length - 1;break;} // 头占用一个字节,需减去;
		if ($end + $charByte - 1 >  $length - 1){$end = $end - 1;break;}
		$end = $end + $charByte - 2;// -1,因为上面+1;
	}

	$charStart = '';$charEnd = '';$strLen = $end - $start + 1;
	if($start == 0 && $end == $length - 1) return $str;
	if($strLen <= 0) return $replace ? str_repeat($replace,$length) : '';
	if($replace && $start){$charStart = str_repeat($replace,$start);}
	if($replace && $end != $length){$charEnd = str_repeat($replace,$length - $end + 1);}
	
	// pr($start,$end,$length,$charStart,$charEnd);exit;
	return $charStart.substr($str,$start,$end - $start + 1).$charEnd;
}

/**
 * 字符串截取,支持中文和其他编码
 * 
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string 
 */
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true){
	if (function_exists("mb_substr")) {
		$i_str_len = mb_strlen($str);
		$s_sub_str = mb_substr($str, $start, $length, $charset);
		if ($length >= $i_str_len) {
			return $s_sub_str;
		} 
		return $s_sub_str . '...';
	} elseif (function_exists('iconv_substr')) {
		return iconv_substr($str, $start, $length, $charset);
	} 
	$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
	$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
	$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
	$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
	preg_match_all($re[$charset], $str, $match);
	$slice = join("", array_slice($match[0], $start, $length));
	if ($suffix) return $slice . "…";
	return $slice;
}

// -----------------变量调试-------------------
/**
 * 格式化输出变量,或者对象
 * 
 * @param args; 
 * 默认自动退出;最后一个参数为false时不退出
 */

function pr_replace_callback($matches){
	return "\n".str_repeat(" ",strlen($matches[1])*2).$matches[2];
}
function pr_trace(){
	$result = func_get_args();
	$result['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
	$result['call'] = get_caller_info();
	$result['trace']  = think_trace('[trace]');
	call_user_func('pr',$result);
}
function pr_trace_exit(){pr_trace();exit;}

function pr(){
	static $hasStyle = false;
	$arg = func_get_args();
	$num = func_num_args();
	if( !isset($GLOBALS['debugLastTime']) ){
		$time = mtime() - TIME_FLOAT;
	}else{
		$time = mtime() - $GLOBALS['debugLastTime'];
	}
	$GLOBALS['debugLastTime'] = mtime();
	if($num == 0 || ($num== 1 && is_null($arg[0]))) return;
	
	ob_start();
	$style = '<style>
	pre.debug{margin:2px 0;font-size:14px;color:#222;font-family:Consolas ;line-height:1.2em;background:#f6f6f6;
		border-left:5px solid #444;padding:5px;width:95%;word-break:break-all;white-space:pre-wrap;word-wrap: break-word;}
	pre.debug b{font-weight:400;}
	.debug .debug_keywords{font-weight:200;color:#888;}
	.debug .debug_tag{color:#222 !important;}
	.debug .debug_var{color:#f60;}
	.debug .debug_var_str,.debug #debug_var_str .debug_keywords{color:#f44336;}
	.debug .debug_set{color:#0C9CAE;}</style>';

	$trace = debug_backtrace();
	ob_start();
	
	$callFile = $trace[0];$callAt = $trace[1];
	if(isset($trace[2]) && $trace[2]['function'] == 'pr_trace'){
	    $callFile = $trace[2];$callAt = $trace[3];
	}
	$method = $callAt['function'];
	if(isset($callAt['class'])){
	    $method = $callAt['class'].'->'.$callAt['function'];
	}
	$fileInfo = get_path_this($callFile['file']).'; '.$method.'()';

	$time = sprintf("%.5fs",$time);
	$logInfo = "<i class='debug_keywords'>".$fileInfo.";[line-".$callFile['line']."];{$time}</i><br/>";
	for ($i=0; $i < $num; $i++) {
		var_dump($arg[$i]);
	}
	$out = ob_get_clean(); //缓冲输出给$out 变量
	$out = preg_replace('/=\>\n\s+/',' => ',$out); //高亮=>后面的值
	$out = preg_replace_callback('/\n(\s*)([\}\[])/','pr_replace_callback',$out); //高亮=>后面的值
	if(is_cli()){echo $time.': '.$fileInfo.";[line-".$callFile['line']."]   ".strip_tags($out);return;}

	$out = preg_replace('/"(.*)"/','<b class="debug_var_str">"\\1"</b>', $logInfo.$out); //高亮字符串变量
	$out = preg_replace('/\[(.*)\]/','<b class="debug_tag">[</b><b class="debug_var">\\1</b><b class="debug_tag">]</b>', $out); //高亮变量
	$out = str_replace(array('=>',"\n\n"), array('<b id="debug_set">=></b>',"\n"), $out);
	$keywords = array('array','int','string','object','null','float','bool'); //关键字高亮
	$keywords_to = $keywords;
	foreach($keywords as $key => $val) {
		$keywords_to[$key] = '<b class="debug_keywords">' . $val . '</b>';
	}
	$out = str_replace($keywords, $keywords_to, $out);
	// $out = stripslashes($out);
	$out = str_replace(array('\n','\/'),array("<br/>",'/'),$out);
	if($hasStyle){$style = "";}
	if(!$hasStyle){$hasStyle = true;}
	echo $style.'<pre class="debug">'.$out.'</pre>';
}
function dump(){call_user_func('pr',func_get_args());}
function debug_out(){call_user_func('pr',func_get_args());}

/**
 * 取$from~$to范围内的随机数,包含$from,$to;
 */
function rand_from_to($from, $to){
	return mt_rand($from,$to);
	// return $from + mt_rand(0, $to - $from);
} 

/**
 * 产生随机字串,可用来自动生成密码 默认长度6位 字母和数字混合
 * 
 * @param string $len 长度
 * @param string $type 字串类型:0 字母 1 数字 2 大写字母 3 小写字母  4 中文  
 * 其他为数字字母混合(去掉了 容易混淆的字符oOLl和数字01,)
 * @param string $addChars 额外字符
 * @return string 
 */
function rand_string($len = 4, $type='checkCode'){
	$str = '';
	switch ($type) {
		case 1://数字
			$chars = '0123456789';
			break;
		case 2://大写字母
			$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
			break;
		case 3://小写字母
			$chars = 'abcdefghijklmnopqrstuvwxyz';
			break;
		case 4://大小写中英文
			$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
			break;
		default: 
			// 默认去掉了容易混淆的字符oOLl和数字01,要添加请使用addChars参数
			$chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
			break;
	}
	if ($len > 10) { // 位数过长重复字符串一定次数
		$chars = $type == 1 ? str_repeat($chars, $len) : str_repeat($chars, 5);
	} 
	if ($type != 4) {
		$chars = str_shuffle($chars);
		$str = substr($chars, 0, $len);
	} else {
		// 中文随机字
		for($i = 0; $i < $len; $i ++) {
			$str .= msubstr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1);
		} 
	} 
	return $str;
} 

/**
 * 生成自动密码
 */
function make_password(){
	$temp = '0123456789abcdefghijklmnopqrstuvwxyz'.
			'ABCDEFGHIJKMNPQRSTUVWXYZ~!@#$^*)_+}{}[]|":;,.'.time();
	for($i=0;$i<10;$i++){
		$temp = str_shuffle($temp.substr($temp,-5));
	}
	return md5($temp);
}

/**
 * php DES解密函数
 * 
 * @param string $key 密钥
 * @param string $encrypted 加密字符串
 * @return string 
 */
function des_decode($key, $encrypted){
	$encrypted = base64_decode($encrypted);
	$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); //使用MCRYPT_DES算法,cbc模式
	$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
	$ks = mcrypt_enc_get_key_size($td);

	mcrypt_generic_init($td, $key, $key); //初始处理
	$decrypted = mdecrypt_generic($td, $encrypted); //解密
	
	mcrypt_generic_deinit($td); //结束
	mcrypt_module_close($td);
	return pkcs5_unpad($decrypted);
} 
/**
 * php DES加密函数
 * 
 * @param string $key 密钥
 * @param string $text 字符串
 * @return string 
 */
function des_encode($key, $text){
	$y = pkcs5_pad($text);
	$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); //使用MCRYPT_DES算法,cbc模式
	$ks = mcrypt_enc_get_key_size($td);

	mcrypt_generic_init($td, $key, $key); //初始处理
	$encrypted = mcrypt_generic($td, $y); //解密
	mcrypt_generic_deinit($td); //结束
	mcrypt_module_close($td);
	return base64_encode($encrypted);
} 
function pkcs5_unpad($text){
	$pad = ord($text[strlen($text)-1]);
	if ($pad > strlen($text)) return $text;
	if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return $text;
	return substr($text, 0, -1 * $pad);
} 
function pkcs5_pad($text, $block = 8){
	$pad = $block - (strlen($text) % $block);
	return $text . str_repeat(chr($pad), $pad);
} 
// 检测语言,只分中文、英语
function check_lang($word){
	$language = 'zh-cn';
	if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $word)) {
		$language = 'en';
	}
	return $language;
}
file.function.php
wget 'https://sme10.lists2.roe3.org/kodbox/app/function/file.function.php'
View Content
<?php
/*
* @link http://kodcloud.com/
* @author warlee | e-mail:kodcloud@qq.com
* @copyright warlee 2014.(Shanghai)Co.,Ltd
* @license http://kodcloud.com/tools/license/license.txt
*/

/**
 * 系统函数:				filesize(),file_exists(),pathinfo(),rname(),unlink(),filemtime(),is_readable(),is_wrieteable();
 * 获取文件详细信息		file_info($fileName)
 * 获取文件夹详细信息		path_info($dir)
 * 递归获取文件夹信息		path_info_more($dir,&$fileCount=0,&$pathCount=0,&$size=0)
 * 获取文件夹下文件列表	path_list($dir)
 * 路径当前文件[夹]名		get_path_this($path)
 * 获取路径父目录			get_path_father($path)
 * 删除文件				del_file($file)
 * 递归删除文件夹			del_dir($dir)
 * 递归复制文件夹			copy_dir($source, $dest)
 * 创建目录				mk_dir($dir, $mode = 0777)
 * 文件大小格式化			size_format($bytes, $precision = 2)
 * 判断是否绝对路径		path_is_absolute( $path )
 * 扩展名的文件类型		ext_type($ext)
 * 文件下载				file_download($file)
 * 文件下载到服务器		file_download_this($from, $fileName)
 * 获取文件(夹)权限		get_mode($file)  //rwx_rwx_rwx [文件名需要系统编码]
 * 上传文件(单个,多个)	upload($fileInput, $path = './');//
 * 获取配置文件项			get_config($file, $ini, $type="string")
 * 修改配置文件项			update_config($file, $ini, $value,$type="string")
 * 写日志到LOG_PATH下		write_log('dd','default|.自建目录.','log|error|warning|debug|info|db')
 */

// 传入参数为程序编码时,有传出,则用程序编码,
// 传入参数没有和输出无关时,则传入时处理成系统编码。
function iconv_app($str){
	global $config;
	$result = iconv_to($str,$config['systemCharset'], $config['appCharset']);
	return $result;
}
function iconv_system($str){
	//去除中文空格UTF8; windows下展示异常;过滤文件上传、新建文件等时的文件名
	//文件名已存在含有该字符时,没有办法操作.
	$char_empty = "\xc2\xa0";
	if(strpos($str,$char_empty) !== false){
		$str = str_replace($char_empty," ",$str);
	}

	global $config;
	$result = iconv_to($str,$config['appCharset'], $config['systemCharset']);
	$result = path_filter($result);
	return $result;
}
function iconv_to($str,$from,$to){
	if (strtolower($from) == strtolower($to)){
		return $str;
	}
	if (!function_exists('iconv')){
		return $str;
	}
	//尝试用mb转换;android环境部分问题解决
	if(function_exists('mb_convert_encoding')){
		$result = @mb_convert_encoding($str,$to,$from);
	}else{
		$result = @iconv($from, $to, $str);
	}
	if(strlen($result)==0){ 
		return $str;
	}
	return $result;
}
function path_filter($path){
	if(strtoupper(substr(PHP_OS, 0,3)) != 'WIN'){
		return $path;
	}
	$notAllow = array('*','?','"','<','>','|');//去除 : D:/
	return str_replace($notAllow,' ', $path);
}

//filesize 解决大于2G 大小问题
//http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2-gb-file-without-external-program
//32位系统; 修改编译php实现兼容支持;  https://demo.kodcloud.com/#s/735psg0g
//源码修改: zend_off_t(文件定位)修改为64位int64_t;  ftell返回值类型加宽; fseek传入值处理,校验类型处理; fstate处理;
function get_filesize($path){
	if(PHP_INT_SIZE >= 8 ) return @filesize($path);
	$fp = fopen($path,"r");
	if(!$fp) return 0;	
	if (fseek($fp, 0, SEEK_END) === 0) {
		$result = 0.0;
		$step = 0x7FFFFFFF;
		while ($step > 0) {
			if (fseek($fp, - $step, SEEK_CUR) === 0) {
				$result += floatval($step);
			} else {
				$step >>= 1;
			}
		}
	}else{
		static $iswin;
		if (!isset($iswin)) {
			$iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
		}
		static $exec_works;
		if (!isset($exec_works)) {
			$exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC');
		}
		if ($iswin && class_exists("COM")) {
			try {
				$fsobj = new COM('Scripting.FileSystemObject');
				$f = $fsobj->GetFile( realpath($path) );
				$size = $f->Size;
			} catch (Exception $e) {
				$size = null;
			}
			if (is_numeric($size)) {
				$result = $size;
			}
		}else if ($exec_works){
			$cmd = ($iswin) ? "for %F in (\"$path\") do @echo %~zF" : "stat -c%s \"$path\"";
			@exec($cmd, $output);
			if (is_array($output) && is_numeric($size = trim(implode("\n", $output)))) {
				$result = $size;
			}
		}else{
			$result = filesize($path);
		}
	}
	fclose($fp);
	return $result;
}

function filesize_64($file){
	return get_filesize($file);
}
function ftell_64($fp){
	return ftell($fp);
}
function fseek_64($fp,$pose=0,$from=SEEK_SET,$first=true){
    return fseek($fp,$pose,$from);// php 编译兼容支持;
    
	if(PHP_INT_SIZE >= 8){return fseek($fp,$pose,$first);}
	if($first) fseek($fp,0,SEEK_SET);
	$intMax = PHP_INT_MAX;
	$pos = floatval($pose);
	if($pos <= $intMax){
		fseek($fp,$pos,SEEK_CUR);
	}else {
		fseek($fp,$intMax,SEEK_CUR);
		$pos -= $intMax;
		fseek_64($fp,$pos,SEEK_CUR,false);
	}
}

// 文件复制,支持32位系统复制大于4G文件; 命令行调用,比fopen/fwrite快;
function copy_64($from,$dest){
	if(!$from || !$dest || !file_exists($from)) return false;
	if(!$GLOBALS['config']['settings']['bigFileForce']){
		// 改php源代码后影响copy的逻辑(循环,暂未适配); 使用命令行获取;
		$result = @copy($from,$dest);
		if($result) return true;
	}
	
	// 命令行调用复制;
	if(function_exists("shell_exec")){
		$command = 'cp ';
		if($GLOBALS['config']['systemOS'] == 'windows'){
			$command = 'COPY ';
		}
		$command .= escapeShell($from).' '.escapeShell($dest);
		@shell_exec($command);
	}else{
		/*
		$size   = filesize_64($from);
		$fromFp = @fopen($from,'r');
		$destFp = @fopen($dest,'w+');
		$chunk  = 1024*1024*5;$start = 0;
		while($start < $size && $size>= 0) {
			$read = fread($fromFp,$chunk);
			if(!strlen($read)){break;}
			fwrite($destFp,$read);
			$start += strlen($read);
		}
		fclose($fromFp);fclose($destFp);
		*/
	}
	return @file_exists($dest);
}

//文件是否存在,区分文件大小写
function file_exists_case( $fileName ){
	if(file_exists($fileName) === false){
		return false;
	}
	$status         = false;
	$directoryName  = dirname( $fileName );
	$fileArray      = glob( $directoryName . '/*', GLOB_NOSORT);
	if ( preg_match( "/\\\|\//", $fileName) ){
		$array    = preg_split("/\\\|\//", $fileName);
		$fileName = $array[ count( $array ) -1 ];
	}
	foreach($fileArray as $file ){
		if(preg_match("/{$fileName}/i", $file)){
			$output = "{$directoryName}/{$fileName}";
			$status = true;
			break;
		}
	}
	return $status;
}


function path_readable($path){
	$result = intval(is_readable($path));
	if($result){
		return $result;
	}
	$mode = get_mode($path);
	if( $mode && 
		strlen($mode) == 18 &&
		substr($mode,-9,1) == 'r'){// -rwx rwx rwx(0777)
		return true;
	}
	return false;
}
function path_writeable($path){
	$result = intval(is_writeable($path));
	if($result) return $result;

	$mode = get_mode($path);
	if( $mode && 
		strlen($mode) == 18 &&
		substr($mode,-8,1) == 'w'){// -rwx rwx rwx (0777)
		return true;
	}
	return false;
}

/**
 * 获取文件详细信息
 * 文件名从程序编码转换成系统编码,传入utf8,系统函数需要为gbk
 */
function file_info($path){
	$info = array(
		'name'			=> iconv_app(get_path_this($path)),
		'path'			=> iconv_app($path),
		'ext'			=> get_path_ext($path),
		'type' 			=> 'file',
		'mode'			=> get_mode($path),
		'atime'			=> @fileatime($path), //最后访问时间
		'ctime'			=> @filectime($path), //创建时间
		'mtime'			=> @filemtime($path), //最后修改时间
		'isReadable'	=> path_readable($path),
		'isWriteable'	=> path_writeable($path),
		'size'			=> get_filesize($path)
	);
	return $info;
}
/**
 * 获取文件夹细信息
 */
function folder_info($path){
	$info = array(
		'name'			=> iconv_app(get_path_this($path)),
		'path'			=> iconv_app(rtrim($path,'/').'/'),
		'type' 			=> 'folder',
		'mode'			=> get_mode($path),
		'atime'			=> @fileatime($path), //访问时间
		'ctime'			=> @filectime($path), //创建时间
		'mtime'			=> @filemtime($path), //最后修改时间
		'isReadable'	=> path_readable($path),
		'isWriteable'	=> path_writeable($path)
	);
	return $info;
}


/**
 * 获取一个路径(文件夹&文件) 当前文件[夹]名
 * test/11/ ==>11 test/1.c  ==>1.c
 */
function get_path_this($path){
	$path = str_replace('\\','/', rtrim($path,'/'));
	$pos = strrpos($path,'/');
	if($pos === false){return $path;}
	return substr($path,$pos+1);
}
/**
 * 获取一个路径(文件夹&文件) 父目录
 * /test/11/==>/test/   /test/1.c ==>/www/test/
 */
function get_path_father($path){
	$path = str_replace('\\','/', rtrim($path,'/'));
	$pos = strrpos($path,'/');
	if($pos === false){return $path;}
	return substr($path, 0,$pos+1);
}
/**
 * 获取扩展名
 */
function get_path_ext($path){
	$name = get_path_this($path);
	$pos  = strrpos($name,'.');
	$ext  = '';
	if($pos !== false){$ext = substr($name,$pos+1);}
	$isMatch = preg_match("/[0-9a-zA-Z_\-]+/",$ext,$match);// 只允许数字字母和下划线
	return ($isMatch && $match[0]) ? strtolower($match[0]):'';
}
function get_path_ext_name($path){
	$name = get_path_this($path);
	$ext  = get_path_ext($name);
	return $ext ? substr($name,0,strripos($name,'.'.$ext)):$name;
}



//自动获取不重复文件(夹)名
//如果传入$file_add 则检测存在则自定重命名  a.txt 为a{$file_add}.txt
function get_filename_auto($path,$file_add = "",$same_file_type='replace'){
	if (is_dir($path) && $same_file_type!=REPEAT_RENAME_FOLDER) {//文件夹则忽略
		return $path;
	}
	//重名处理
	if (file_exists($path)) {
		if ($same_file_type== REPEAT_REPLACE) {
			return $path;
		}else if($same_file_type==REPEAT_SKIP){
			return false;
		}
	}

	$i=1;
	$father = get_path_father($path);
	$name =  get_path_this($path);
	$ext = get_path_ext($name);
	if(is_dir($path)){
		$ext = '';
	}
	if (strlen($ext)>0) {
		$ext='.'.$ext;
		$name = substr($name,0,strlen($name)-strlen($ext));
	}
	while(file_exists($path)){
		if ($file_add != '') {
			$path = $father.$name.$file_add.$ext;
			$file_add.='-';
		}else{
			$path = $father.$name.'('.$i.')'.$ext;
			$i++;
		}
	}
	return $path;
}

/**
 * 获取文件夹详细信息,文件夹属性时调用,包含子文件夹数量,文件数量,总大小
 */
function path_info($path){
	if (!file_exists($path)) return false;
	$pathinfo = _path_info_more($path);//子目录文件大小统计信息
	$folderinfo = folder_info($path);
	return array_merge($pathinfo,$folderinfo);
}

/**
 * 检查名称是否合法
 */
function path_check($path){
	$check = array('/','\\',':','*','?','"','<','>','|');
	$path = rtrim($path,'/');
	$path = get_path_this($path);
	foreach ($check as $v) {
		if (strstr($path,$v)) {
			return false;
		}
	}
	return true;
}

/**
 * 递归获取文件夹信息: 子文件夹数量,文件数量,总大小
 */
function _path_info_more($dir, &$fileCount = 0, &$pathCount = 0, &$size = 0){
	if (!$dh = @opendir($dir)) return array('fileCount'=>0,'folderCount'=>0,'size'=>0);
	while (($file = readdir($dh)) !== false) {
		if ($file =='.' || $file =='..') continue;
		$fullpath = $dir . "/" . $file;
		if (!is_dir($fullpath)) {
			$fileCount ++;
			$size += get_filesize($fullpath);
		} else {
			_path_info_more($fullpath, $fileCount, $pathCount, $size);
			$pathCount ++;
		}
	}
	closedir($dh);
	$pathinfo['fileCount'] = $fileCount;
	$pathinfo['folderCount'] = $pathCount;
	$pathinfo['size'] = $size;
	return $pathinfo;
}


/**
 * 获取多选文件信息,包含子文件夹数量,文件数量,总大小,父目录权限
 */
function path_info_muti($list,$timeType){
	$list = is_array($list) ? $list : array();
	if (count($list) == 1) {
		if ($list[0]['type']=="folder"){
			return path_info($list[0]['path'],$timeType);
		}else{
			return file_info($list[0]['path'],$timeType);
		}
	}
	$pathinfo = array(
		'fileCount'		=> 0,
		'folderCount'	=> 0,
		'size'			=> 0,
		'father_name'	=> '',
		'mod'			=> ''
	);
	foreach ($list as $val){
		if ($val['type'] == 'folder') {
			$pathinfo['folderCount'] ++;
			$temp = path_info($val['path']);
			$pathinfo['folderCount']	+= $temp['folderCount'];
			$pathinfo['fileCount']	+= $temp['fileCount'];
			$pathinfo['size'] 		+= $temp['size'];
		}else{
			$pathinfo['fileCount']++;
			$pathinfo['size'] += get_filesize($val['path']);
		}
	}
	$father_name = get_path_father($list[0]['path']);
	$pathinfo['mode'] = get_mode($father_name);
	return $pathinfo;
}

/**
 * 获取文件夹下列表信息
 * dir 包含结尾/   d:/wwwroot/test/
 * 传入需要读取的文件夹路径,为程序编码
 */
function path_list($dir,$listFile=true,$checkChildren=false){
	$dir = rtrim($dir,'/').'/';
	if (!is_dir($dir) || !($dh = @opendir($dir))){
		return array('folderList'=>array(),'fileList'=>array());
	}
	$folderList = array();$fileList = array();//文件夹与文件
	while (($file = readdir($dh)) !== false) {
		if ($file =='.' || $file =='..' || $file == ".svn") continue;
		$fullpath = $dir . $file;
		if (is_dir($fullpath)) {
			$info = folder_info($fullpath);
			if($checkChildren){
				$info['isParent'] = path_haschildren($fullpath,$listFile);
			}
			$folderList[] = $info;
		} else if($listFile) {//是否列出文件
			$info = file_info($fullpath);
			if($checkChildren) $info['isParent'] = false;
			$fileList[] = $info;
		}
	}
	closedir($dh);
	return array('folderList' => $folderList,'fileList' => $fileList);
}

// 判断文件夹是否含有子内容【区分为文件或者只筛选文件夹才算】
function path_haschildren($dir,$checkFile=false){
	$dir = rtrim($dir,'/').'/';
	if (!$dh = @opendir($dir)) return false;
	while (($file = readdir($dh)) !== false){
		if ($file =='.' || $file =='..') continue;
		$fullpath = $dir.$file;
		if ($checkFile) {//有子目录或者文件都说明有子内容
			if(@is_file($fullpath) || is_dir($fullpath.'/')){
				closedir($dh);
				return true;
			}
		}else{//只检查有没有文件
			if(@is_dir($fullpath.'/')){//解决部分主机报错问题
				closedir($dh);
				return true;
			}
		}
	}
	closedir($dh);
	return false;
}

/**
 * 删除文件 传入参数编码为操作系统编码. win--gbk
 */
function del_file($fullpath){
	if (!file_exists($fullpath)) return true;
	if (!@unlink($fullpath)) { // 删除不了,尝试修改文件权限
		@chmod($fullpath, DEFAULT_PERRMISSIONS);
		if (!@unlink($fullpath)) {return false;}
	} else {
		return true;
	}
}

/**
 * 删除文件夹 传入参数编码为操作系统编码. win--gbk
 */
function del_dir($dir){
	if(!file_exists($dir) || !is_dir($dir)) return true;
	if (!$dh = opendir($dir)) return false;
	set_timeout();
	while (($file = readdir($dh)) !== false) {
		if ($file =='.' || $file =='..') continue;
		$fullpath = rtrim($dir, '/') . '/' . $file;
		if (!is_dir($fullpath)) {
			if (!@unlink($fullpath)) { // 删除不了,尝试修改文件权限
				@chmod($fullpath, DEFAULT_PERRMISSIONS);
				if (!@unlink($fullpath)) {return false;}
			}
		} else {
			if (!del_dir($fullpath)) {
				@chmod($fullpath, DEFAULT_PERRMISSIONS);
				if (!del_dir($fullpath)) return false;
			}
		}
	}
	closedir($dh);
	if (rmdir($dir)) {
		return true;
	} else {
		return false;
	}
}


/**
 * 复制文件夹
 * eg:将D:/wwwroot/下面wordpress复制到
 *	D:/wwwroot/www/explorer/0000/del/1/
 * 末尾都不需要加斜杠,复制到地址如果不加源文件夹名,
 * 就会将wordpress下面文件复制到D:/wwwroot/www/explorer/0000/del/1/下面
 * $from = 'D:/wwwroot/wordpress';
 * $to = 'D:/wwwroot/www/explorer/0000/del/1/wordpress';
 */

function copy_dir($source, $dest){
	if (!$dest) return false;
	if (is_dir($source) && $source == substr($dest,0,strlen($source))) return false;//防止父文件夹拷贝到子文件夹,无限递归

	set_timeout();
	$result = true;
	if (is_file($source)) {
		if ($dest[strlen($dest)-1] == '/') {
			$__dest = $dest . "/" . basename($source);
		} else {
			$__dest = $dest;
		}
		$result = copy_64($source,$__dest);
		@chmod($__dest, DEFAULT_PERRMISSIONS);
	}else if(is_dir($source)) {
		if ($dest[strlen($dest)-1] == '/') {
			$dest = $dest . basename($source);
		}
		if (!is_dir($dest)) {
			@mkdir($dest,DEFAULT_PERRMISSIONS);
		}
		if (!$dh = opendir($source)) return false;
		while (($file = readdir($dh)) !== false) {
			if ($file =='.' || $file =='..') continue;
			$result = copy_dir($source . "/" . $file, $dest . "/" . $file);
		}
		closedir($dh);
	}
	return $result;
}

function move_file($source,$dest,$repeat_add,$repeat_type){
	if($source == $dest) return true;
	if ($dest[strlen($dest)-1] == '/') {
		$dest = $dest . "/" . basename($source);
	}
	if(file_exists($dest)){
		$dest = get_filename_auto($dest,$repeat_add,$repeat_type);//同名文件处理规则
	}
	@chmod($source, DEFAULT_PERRMISSIONS);
	$result = intval(@rename($source,$dest));
	if (! $result) { // windows部分ing情况处理
		$result = intval(@copy_64($source,$dest));
		if ($result) {
			@unlink($source);
		}
	}
	return $result;
}
function move_path($source,$dest,$repeat_add='',$repeat_type='replace'){
	if (!$dest || !file_exists($source)) return false;
	if ( is_dir($source) ){
		//防止父文件夹拷贝到子文件夹,无限递归
		if($source == substr($dest,0,strlen($source))){
			return false;
		}
		//地址相同
		if(rtrim($source,'/') == rtrim($dest,'/')){
			return false;
		}
	}

	set_timeout();
	if(is_file($source)){
		return move_file($source,$dest,$repeat_add,$repeat_type);
	}
	recursion_dir($source,$dirs,$files,-1,0);

	@mkdir($dest);
	foreach($dirs as $f){
		$path = $dest.'/'.substr($f,strlen($source));
		if(!file_exists($path)){
			mk_dir($path);
		}
	}
	$file_success = 0;
	foreach($files as $f){
		$path = $dest.'/'.substr($f,strlen($source));
		$file_success += move_file($f,$path,$repeat_add,$repeat_type);
	}
	foreach($dirs as $f){
		rmdir($f);
	}
	@rmdir($source);
	if($file_success == count($files)){
		del_dir($source);
		return true;
	}
	return false;
}

/**
 * 创建目录
 *
 * @param string $dir
 * @param int $mode
 * @return bool
 */
function mk_dir($dir, $mode = 0755){
	if (!$dir) return false;
	if (is_dir($dir) || @mkdir($dir, $mode)){
		return true;
	}
	$pdir = dirname($dir);	// 避免根目录死循环
	if ($pdir != $dir) {
		if (!mk_dir($pdir, $mode)){
			return false;
		}
	}
	return @mkdir($dir, $mode);
}

/*
* 获取文件&文件夹列表(支持文件夹层级)
* path : 文件夹 $dir ——返回的文件夹array files ——返回的文件array
* $deepest 是否完整递归;$deep 递归层级
*/
function recursion_dir($path,&$dir,&$file,$deepest=-1,$deep=0){
	$path = rtrim($path,'/').'/';
	if (!is_array($file)) $file=array();
	if (!is_array($dir)) $dir=array();
	if (!is_dir($path)) return false;
	if (!$dh = opendir($path)) return false;
	while(($val=readdir($dh)) !== false){
		if ($val=='.' || $val=='..') continue;
		$value = strval($path.$val);
		if (is_file($value)){
			$file[] = $value;
		}else if(is_dir($value)){
			$dir[]=$value;
			if ($deepest==-1 || $deep<$deepest){
				recursion_dir($value."/",$dir,$file,$deepest,$deep+1);
			}
		}
	}
	closedir($dh);
	return true;
}
function dir_list($path){
	recursion_dir($path,$dirs,$files);
	return array_merge($dirs,$files);
}

/*
 * $search 为包含的字符串
 * is_content 表示是否搜索文件内容;默认不搜索
 * is_case  表示区分大小写,默认不区分
 */
function path_search($path,$search,$is_content=false,$file_ext='',$isCase=false){
	$result = array();
	$result['fileList'] = array();
	$result['folderList'] = array();
	if(!$path) return $result;

	$ext_arr = explode("|",$file_ext);
	recursion_dir($path,$dirs,$files,-1,0);
	$strpos = 'stripos';//是否区分大小写
	if ($isCase) $strpos = 'strpos';
	$result_num = 0;
	$result_num_max = 2000;//搜索文件内容,限制最多匹配条数
	foreach($files as $f){
		if($result_num >= $result_num_max){
			$result['error_info'] = $result_num_max;
			break;
		}
		
		//若指定了扩展名则只在匹配扩展名文件中搜索
		$ext = get_path_ext($f);
		if($file_ext != '' && !in_array($ext,$ext_arr)){
			continue;
		}

		//搜索内容则不搜索文件名
		if ($is_content) {
			if(!is_text_file($ext)) continue; //在限定中或者不在bin中
			$search_info = file_search($f,$search,$isCase);
			if($search_info !== false){
				$result_num += count($search_info['searchInfo']);
				$result['fileList'][] = $search_info;
			}
		}else{
			$path_this = get_path_this($f);
			if ($strpos($path_this,iconv_system($search)) !== false){//搜索文件名;
				$result['fileList'][] = file_info($f);
				$result_num ++;
			}
		}	
	}
	if (!$is_content && $file_ext == '' ) {//没有指定搜索文件内容,且没有限定扩展名,才搜索文件夹
		foreach($dirs as $f){
			$path_this = get_path_this($f);
			if ($strpos($path_this,iconv_system($search)) !== false){
				$result['folderList'][]= array(
					'name'  => iconv_app(get_path_this($f)),
					'path'  => iconv_app($f)
				);
			}
		}
	}
	return $result;
}

// 文件搜索;返回行及关键词附近行
function file_search($path,$search,$isCase){
	if(@filesize($path) >= 1024*1024*20) return false;
	$content = file_get_contents($path);
	$result  = content_search($content,$search,$isCase);
	unset($content);
	if(!$result) return false;

	$info = file_info($path);
	$info['searchInfo'] = $result;
	return $info;
}

// 文本搜索;返回行及关键词附近行
function content_search(&$content,$search,$isCase,$maxCount=1000,$isUtf8=false){
	$strpos = 'stripos';//是否区分大小写
	if( $isCase) $strpos = 'strpos';
	if( $strpos($content,"\0") > 0 ){return false;}// 不是文本文档
	if(!$isUtf8){
		//搜索关键字为纯英文则直接搜索;含有中文则转为utf8再搜索,为兼容其他文件编码格式
		$charset  = get_charset($content);
		$notAscii = preg_match("/[\x7f-\xff]/", $search);
		if($notAscii && !in_array($charset,array('utf-8','ascii'))){
			$content = iconv_to($content,$charset,'utf-8');
		}
	}
	//文件没有搜索到目标直接返回
	if ($strpos($content,$search) === false) return false;

	$fileSize   = strlen($content);
	$arrSearch  = array();$pose = 0;  // 匹配结果所在位置
	$searchLen  = strlen($search);
	// 通过分割方式快速得到数组,加速处理; 比一次strpos快(去除最后一项)
	$arraySplit = explode(strtolower($search),strtolower($content));
	$arraySplitCount = count($arraySplit);
	foreach ($arraySplit as $i => $chunk){
		if(count($arrSearch) >= $maxCount){break;}
		if($i == $arraySplitCount - 1){break;}
		$arrSearch[] = strlen($chunk) + $pose;
		$pose = $pose + strlen($chunk) + $searchLen;
	}
	
	// $arrSearch  = array();$pose = 0;
	// while ( $pose !== false) {
	// 	$pose = stripos($content,$search, $pose);
	// 	if($pose === false){break;}
	// 	$arrSearch[] = $pose;$pose ++;
	// 	if(count($arrSearch) >= $maxCount){break;}
	// }

	$arrLine = array();$pose = 0;
	while($pose !== false) {
		$pose = strpos($content, "\n", $pose);
		if($pose === false){break;}
		$arrLine[] = $pose;$pose ++;		
	}
	$arrLine[] = $fileSize;//文件只有一行而且没有换行,则构造虚拟换行
	$result = array();//  [2,10,22,45,60]  [20,30,40,50,55]
	$lenSearch = count($arrSearch);
	$lenLine   = count($arrLine);
	for ($i=0,$line=0; $i < $lenSearch && $line < $lenLine; $line++) {
		while ( $arrSearch[$i] <= $arrLine[$line]) {
			$curPose = $arrSearch[$i];//行截取字符串
			$lenLeft = 80;$lenRight = 120;$curFrom = $curPose + $searchLen;
			$curMin  = $curPose - $lenLeft <= 0 ? 0 : $curPose - $lenLeft;
			$curMax  = $curFrom + $lenRight >= $fileSize ? $fileSize : $curFrom + $lenRight;
			$from    = $curMin; $to = $curMax;
			
			//中文避免截断(向前 向后找到分隔符后终止) //  ',','、',
			$token = array("\r","\n",'。');
			$strLeft =  substr($content,$curMin,($curPose - $curMin));
			$strRight = substr($content,$curFrom,$lenRight);
			foreach($token as $char){
				$leftFind    = strrpos($strLeft,$char);
				$rightFind   = strpos($strRight,$char);
				if($leftFind  !== false){$from = max($from, $curMin + $leftFind + strlen($char));}
				if($rightFind !== false){$to   = min($to, $curFrom + $rightFind + strlen($char));}
			}
			
			// $lineStr = substr($content,$from,$to - $from);
			$lineStr = utf8Repair(substr($content,$from,$to - $from));
			$result[] = array('line'=>$line+1,'str'=>trim($lineStr));
			if(count($result) >= $maxCount) return $result;
			if(++$i >= $lenSearch ){break;}
		}
	}
	return $result;
}


/**
 * 修改文件、文件夹权限
 * @param  $path 文件(夹)目录
 * @return :string
 */
function chmod_path($path,$mod=0){
	$mod = $mod == 0 ? DEFAULT_PERRMISSIONS:$mod;
	if (!file_exists($path)) return false;
	if (is_file($path)) return @chmod($path,$mod);
	if (!$dh = @opendir($path)) return false;
	while (($file = readdir($dh)) !== false){
		if ($file =='.' || $file =='..') continue;
		$fullpath = $path . '/' . $file;
		chmod_path($fullpath,$mod);
		@chmod($fullpath,$mod);
	}
	closedir($dh);
	return @chmod($path,$mod);
}

/**
 * 文件大小格式化
 *
 * @param  $ :$bytes, int 文件大小
 * @param  $ :$precision int  保留小数点
 * @return :string
 */
function size_format($bytes, $precision = 2){
	if ($bytes == 0) return "0 B";
	$unit = array(
		'PB' => 1099511627776*1024,  // pow( 1024, 5)
		'TB' => 1099511627776,  	 // pow( 1024, 4)
		'GB' => 1073741824,			 // pow( 1024, 3)
		'MB' => 1048576,			 // pow( 1024, 2)
		'kB' => 1024,				 // pow( 1024, 1)
		'B ' => 1,					 // pow( 1024, 0)
	);
	foreach ($unit as $un => $mag) {
		if (doubleval($bytes) >= $mag)
			return round($bytes / $mag, $precision).' '.$un;
	}
}

/**
 * 判断路径是不是绝对路径
 * 返回true('/foo/bar','c:\windows').
 *
 * @return 返回true则为绝对路径,否则为相对路径
 */
function path_is_absolute($path){
	if (realpath($path) == $path)// *nux 的绝对路径 /home/my
		return true;
	if (strlen($path) == 0 || $path[0] == '.')
		return false;
	if (preg_match('#^[a-zA-Z]:\\\\#', $path))// windows 的绝对路径 c:\aaa\
		return true;
	return (bool)preg_match('#^[/\\\\]#', $path); //绝对路径 运行 / 和 \绝对路径,其他的则为相对路径
}


function is_text_file($ext){
	static $extArray = false;
	if(!$extArray){
		$extArray = array(
			'3dml,3ds,4th,_adb,a,abap,abc,ac,acl,ada,adb,adoc,ahk,aj,alda,am,anpa,apex,apl,app,apple-app-site-association',
			'applescript,access,aql,arcconfig,arclint,as,asc,asciidoc,asl,asm,asn,asn1,asp,aspx,ass,astylerc,atom,authors,aw,awk,apinotes',
			'b,babelrc,bak,bas,bash,bash_history,bash_logout,bash_profile,bashrc,bat,bf,bib,bowerrc,blade,brew_all_commands,bro,build,bzl',
			'c,c9search_results,cabal,cakefile,cbl,cc,cer,cert,certs,cf,cfg,cfm,cgi,changelog,changes,cid,cirru,cl,classpath,clj,cljc,cljs,cljx,cls,cmake,cmake.in',
			'cmd,cnf,cname,cob,codeowners,coffee,commit_editmsg,compile,component,conf,config,configure,container,contributing,copyright,copying,coveragerc,cpp,cpy,cql,cr',
			'credits,crontab,crt,cs,csd,cshrc,cshtml,cson,csproj,css,csslintrc,csv,ctp,curl,curly,cxx,cyp,cypher',
			'd,dae,darglint,dart,dcurl,de,def,default,defs,depcomp,deploy,description,desktop,di,diff,dist,dockerfile,dockerfile-dist,dockerfile-master,dockerignore',
			'dot,dox,drl,dsc,dsl,dtd,dummy,dxf,dxf-check,dxfb-check,dyalog,dyl,dylan',
			'e,ecl,edi,editorconfig,edn,eex,ejs,el,elm,empty,en,environment,epp,erb,erl,err,es,eslintrc,eslintignore,etx,euc-kr,ex,example,exclude,exp,exports,exs',
			'f,f77,f90,f95,factor,feature,fetch_head,filters,fingerprint,flx,fly,fm,for,forth,frag,frt,fs,fsi,fsl,fsscript,fsx,fth,ftl,fun,fx',
			'gbs,gcode,ge,gemfile,gemspec,gendocs_template,geojson,git,git-credentials,git-version-gen,gitattributes,gitconfig,gitflow_export,gitignore',
			'gitignore_global,gitkeep,gitlog-to-changelog,gitmodules,glsl,gltf,gnumakefile,go,gql,gradle,groovy,gss,guardfile,guess,gunmakefile,gv,gypi',
			'h,hacking,haml,handlebars,hbs,head,helmignore,hgignore_global,hh,hjson,hlean,hpp,hrl,hs,hta,htaccess,htgroups,htm,html,html.eex,html.erb,htpasswd,http,hx,hxml,hxx',
			'i,ics,idl,iml,in,inc,inf,ini,ino,install,install-sh,installversion,intr,inx,io,iso19139,itk',
			'j2,jack,jade,java,jexl,ji,jinja,jinja2,jl,jq,js,jsdtscope,jshintrc,jsm,json,json-check,json5,jsonld,jscsrc,jsp,jssm,jssm_state,jsx',
			'key,keys,kml,ksh,kt,kts,la,latex,latte,ldr,lean,less,lesshst,lgc,lhs,lic,license,license-gpl,license-mit',
			'lightbgcolor,liquid,lisp,list,lnk,local,localized,lock,log,logic,lp,lql,lrc,ls,lsl,lsp,ltx,lua,lucene',
			'm,m3,m3u8,m4,magnet,mailcap,make,makefile,manifest,map,markdown,mask,master,mathml,matlab,mbox,mc,mcurl,md,mdx',
			'mediawiki,mel,meta,mf,mht,mhtml,mime,missing,mixal,mjs,mkd,ml,mli,mll,mly,mm,mml,mo,mod,module,mps,msc,mscgen',
			'mscin,msgenny,mtl,mush,mustache,mvnw,mycli-history,myclirc,mymetadata,mysql,mysql_history,mz,modulemap',
			'name,nb,nc,ncx,netrwhist,news,nginx,nim,nix,nj,njk,nmf,node_repl_history,npmignore,npmrc,nq,nsh,nsi,nt,nunjs,nunjucks,nut,oak,obj,ocaml,ocamlmakefile,odin',
			'oexe,opf,opt,orc,orig_head,out,owners,oz',
			'p,p6,packed-refs,packs,page,pas,patch,pbxproj,pc,pch,pearrc,pem,pgp,pgsql,php,php3,php4,php5,php7,phpclass,phps,phpt,phtml,policy,pt-br',
			'pid,pig,pl,pl6,plantuml,plg,plist,plistpch,pls,plsql,plugins,ply,pm,pm6,po,pp,praat,praatscript,pre-commit,pre-update,prefs,prettierrc',
			'pri,prisma,pro,proc,project,prolog,properties,props,proto,ps1,psc,psd1,psm1,pub,pug,puml,pxd,pxi,py,pylintrc,pyw,pyx',
			'q,qml,qrc,r,rake,rakefile,raku,rakumod,rakutest,rb,rd,rdf,readme,red,rediscli_history,reds,refs,reg,rels,repo,rest,resx,rexx,rhtml,rkt,rng,robot,rq,rs,rss,rst,rtx,ru',
			's,sample,sas,sass,sbt,scad,scala,schema,scheme,scm,sco,scss,scurl,sed,servers,service,security,settings,sgml,sh,sh_history,sharedmimeinfo,shtml,sieve,sig,siv,stderr,stdout,stdin,sha,verification',
			'sjs,skim,slim,sln,sm,smackspec,smarty,smithy,sml,snippets,sourcetreeconfig,soy,space,sparql,spec,spot,sql',
			'sqlite_history,sqlserver,srt,ss,st,status,stcommitmsg,stl,storyboard,str,strings,styl,stylus,sub,sublime-project,sum,supp,sv,svg,svh,swift,swig',
			't,target,targets,tbd,tcl,template,tern-project,terragrunt,tex,texi,text,textile,tf,tfvars,tgr,tld,tmx,todo,toml,tpl,trigger,ts',
			'tsv,tsx,ttcn,ttcn3,ttcnpp,ttl,twig,txt,typed,types,typescript',
			'ui,uri,url,utf8,using_foreign_code,uu',
			'v,vala,values,vb,vbproj,vbs,vcf,vcproj,vcs,vcxproj,version,vert,vfp,vh,vhd,vhdl,viminfo,vm,vmx,vmxd,vmxf,vsixmanifest,vtl,vtt,vue',
			'wast,wat,we,webapp,webidl,webloc,wiki,wl,wlk,wls,wml,wmls,wpgm,wpy,wsdl,wtest',
			'x-classpath,x-gitattributes,x-gitmodules,x-magnet,x-readme,x-sublime-project,x-vbproj,x-vtt,x3d,xaml,xbl,xcscheme,xhtml,xib,xml,xq,xquery,xsd,xsl,xslt,xu,xul,xy',
			'y,yaml,yml,ys,z80,zeek,zsh,zsh-template,zsh-theme,zsh-update,zsh_history,zshrc,zshrc_self',
			);
		$extArray = explode(',',implode(',',$extArray));
	}
	
	if($ext === -1) return $extArray;
	return in_array($ext,$extArray);
}

/**
 * 远程文件下载到服务器
 * 支持fopen的打开都可以;支持本地、url
 */
function file_download_this($from, $fileName,$headerSize=0){
	set_timeout();
	$fileTemp = $fileName.'.downloading';
	if ($fp = @fopen ($from, "rb")){
		if(!$downloadFp = @fopen($fileTemp, "wb")){
			return false;
		}
		while(!feof($fp)){
			if(!file_exists($fileTemp)){//删除目标文件;则终止下载
				fclose($downloadFp);
				return false;
			}
			//对于部分fp不结束的通过文件大小判断
			clearstatcache();
			if( $headerSize>0 &&
				$headerSize==get_filesize(iconv_system($fileTemp))
				){
				break;
			}
			fwrite($downloadFp, fread($fp, 1024 * 200 ), 1024 * 200);
		}
		//下载完成,重命名临时文件到目标文件
		fclose($downloadFp);
		fclose($fp);
		if(!@rename($fileTemp,$fileName)){
			unlink($fileName);
			return rename($fileTemp,$fileName);
		}
		return true;
	}else{
		return false;
	}
}

/**
 * 获取文件(夹)权限 rwx_rwx_rwx
 */
function get_mode($file){
	$Mode = @fileperms($file);
	$theMode = ' '.decoct($Mode);
	$theMode = substr($theMode,-4);
	$Owner = array();$Group=array();$World=array();
	if ($Mode &0x1000) $Type = 'p'; // FIFO pipe
	elseif ($Mode &0x2000) $Type = 'c'; // Character special
	elseif ($Mode &0x4000) $Type = 'd'; // Directory
	elseif ($Mode &0x6000) $Type = 'b'; // Block special
	elseif ($Mode &0x8000) $Type = '-'; // Regular
	elseif ($Mode &0xA000) $Type = 'l'; // Symbolic Link
	elseif ($Mode &0xC000) $Type = 's'; // Socket
	else $Type = 'u'; // UNKNOWN
	// Determine les permissions par Groupe
	$Owner['r'] = ($Mode &00400) ? 'r' : '-';
	$Owner['w'] = ($Mode &00200) ? 'w' : '-';
	$Owner['x'] = ($Mode &00100) ? 'x' : '-';
	$Group['r'] = ($Mode &00040) ? 'r' : '-';
	$Group['w'] = ($Mode &00020) ? 'w' : '-';
	$Group['e'] = ($Mode &00010) ? 'x' : '-';
	$World['r'] = ($Mode &00004) ? 'r' : '-';
	$World['w'] = ($Mode &00002) ? 'w' : '-';
	$World['e'] = ($Mode &00001) ? 'x' : '-';
	// Adjuste pour SUID, SGID et sticky bit
	if ($Mode &0x800) $Owner['e'] = ($Owner['e'] == 'x') ? 's' : 'S';
	if ($Mode &0x400) $Group['e'] = ($Group['e'] == 'x') ? 's' : 'S';
	if ($Mode &0x200) $World['e'] = ($World['e'] == 'x') ? 't' : 'T';
	$Mode = $Type.$Owner['r'].$Owner['w'].$Owner['x'].' '.
			$Group['r'].$Group['w'].$Group['e'].' '.
			$World['r'].$World['w'].$World['e'];
	return $Mode.'('.$theMode.')';
}

function path_clear($path){
	$path = str_replace('\\','/',trim($path));
	$path = preg_replace('/\/+/', '/', $path);
	if (strstr($path,'../')) {
		$path = preg_replace('/\/\.+\//', '/', $path);
	}
	return $path;
}
function path_clear_name($path){
	$path = str_replace('\\','/',trim($path));
	$path = str_replace('/','.',trim($path));
	return $path;
}

/**
 * 写日志
 * @param string $log   日志信息
 * @param string $type  日志类型 [system|app|...]
 * @param string $level 日志级别
 * @return boolean
 */
function write_log($log, $type = 'default', $level = 'log'){
	if(!defined('LOG_PATH')) return;
	list($usec, $sec) = explode(' ', microtime());
	$now_time = date('[H:i:s.').substr($usec,2,3).' id-'.REQUEST_ID.']';
	$target   = LOG_PATH . strtolower($type) . '/';
	mk_dir($target);
	if (!path_writeable($target)){
		return;// 日志写入失败不处理;
		exit('path can not write! ['.$target.']');
	}
	$ext = '.php';//.php .log;
	$target .= date('Y_m_d').'__'.$level.$ext;
	//检测日志文件大小, 超过配置大小则重命名
	if (file_exists($target) && get_filesize($target) >= 1024*1024*5) {
		$fileName = substr(basename($target),0,strrpos(basename($target),$ext)).date('H-i-s').$ext;
		@rename($target, dirname($target) .'/'. $fileName);
	}
	if(!file_exists($target)){
		error_log("<?php exit;?>\n", 3,$target);
		@chmod($target,_get($GLOBALS,'config.DEFAULT_PERRMISSIONS',0777));
	}

	if(is_object($log) || is_array($log)){
		$log = json_encode_force($log);
		$log = str_replace(array('\\n','\\r','\\t','\\"','\\\'','\/'),array("\n","\r","\t",'"',"'",'/'),$log);
	}
	clearstatcache();
	return error_log("$now_time $log\n", 3, $target);
}
helper.function.php
wget 'https://sme10.lists2.roe3.org/kodbox/app/function/helper.function.php'
View Content
<?php

if(!function_exists('gzinflate')){
    show_tips("不支持gzinflate ,<br/>请安装php-zlib 扩展后再试");exit;
}
function allowCROS(){
	if(isset($GLOBALS['_allowCROS'])){return;} // 只调用一次;
	$GLOBALS['_allowCROS'] = true;
	
	$allowMethods = 'GET, POST, OPTIONS, DELETE, HEAD, MOVE, COPY, PUT, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK';
	$allerHeaders = 'ETag, Content-Type, Content-Length, Accept-Encoding, X-Requested-with, Origin, X-Kod-Cookie, Authorization, Access-Control-Request-Private-Network, Access-Control-Request-Credentials, Access-Control-Allow-Credentials, Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Max-Age';
	header('Access-Control-Allow-Origin: *');    				// 允许的域名来源;
	header('Access-Control-Allow-Methods: '.$allowMethods); 	// 允许请求的类型
	header('Access-Control-Allow-Headers: '.$allerHeaders);		// 允许请求时带入的header
	header('Access-Control-Allow-Private-Network: true');		// 允许私有网络
	header('Access-Control-Allow-Credentials: true'); 			// 设置是否允许发送 cookie; js需设置:xhr.withCredentials = true;
	header('Access-Control-Max-Age: 3600');	
}

//扩展名权限判断 有权限则返回1 不是true
function checkExt($file){return checkExtSafe($file);}
function checkExtSafe($file){
	if($file == '.htaccess' || $file == '.user.ini') return false;
	if(strstr($file,'<') || strstr($file,'>') || $file=='') return false;
	$disable  = 'php|phtml|phtm|pwml|asp|aspx|ascx|jsp|pl|html|htm|svg|shtml|shtm';
	$extArr = explode('|',$disable);
	foreach ($extArr as $ext) {
		if ($ext && stristr($file,'.'.$ext)) return false;
	}
	return true;
}

function linkHref($src,$dev=false){
	if($dev){echo STATIC_PATH.$src.'?v='.time(); return;}
	$static  = STATIC_PATH;
	$version = GLOBAL_DEBUG ? time() : KOD_VERSION.'.'.KOD_VERSION_BUILD;//debug;
	echo $static . $src . '?v='.$version;
}
function urlApi($api='',$param=''){
	$host = appHostGet(); $and = '';
	if($param === null ) return $host.$api;
	$and = !strstr($host,'?') ? '?' : '&';
	return $host.$api.$and.$param;
}
function appHostGet(){
	static $host = false;
	if($host) return $host;

	$appHost = rtrim(APP_HOST,'/').'/';
	$resultFile  = DATA_PATH .'system/rewrite.lock';
	if(file_exists($resultFile)){
		$split = @file_get_contents($resultFile);
	}else{
		//避免部分apache url该情况301跳转;
		$split    = 'index.php?';// 默认:'index.php?'; 省略入口:'?'; 伪静态:''; 指定:'i';
		$checkUrl = $appHost.'app/function/?sitemap/urlType&v=1';
		// 安装调用时,扩展可能还未安装
		if(ini_get('allow_url_fopen')) {
			$opts = array('http'=>array('method'=>'GET','timeout'=>0.5));
			$context = stream_context_create($opts);
			$data = file_get_contents($checkUrl, false, $context);
		}else if(function_exists('curl_init')) {
			$data = url_request($checkUrl,0,0,0,0,0,0.5);
			$data = !empty($data['data']) ? $data['data'] : '';
		}
		if(trim($data) == '[ok]') {$split = '?';}
		@file_put_contents($resultFile,$split);
	}
	$host = $appHost.$split;
	return $host;
}

//-----解压缩跨平台编码转换;自动识别编码-----
//压缩前,文件名处理;
//ACT=zip——压缩到当前
//ACT=zipDownload---打包下载[判断浏览器&UA——得到地区自动转换为目标编码];
function zip_pre_name($fileName,$toCharset=false){
	Hook::trigger('zip.nameParse',$fileName);
	if(get_path_this($fileName) == '.DS_Store') return '';//过滤文件
	if (!function_exists('iconv')){
		return $fileName;
	}
	$charset = $GLOBALS['config']['systemCharset'];
	if($toCharset == false){//默认从客户端和浏览器自动识别
		$toCharset = 'utf-8';
		$clientLanugage = I18n::defaultLang();
		$langType = I18n::getType();
		if( client_is_windows() && (
			$clientLanugage =='zh-CN' || 
			$clientLanugage =='zh-TW' || 
			$langType =='zh-CN' ||
			$langType =='zh-TW' )
		){
			$toCharset = "gbk";//压缩或者打包下载压缩时文件名采用的编码
		}
	}

	//write_log("zip:".$charset.';'.$toCharset.';'.$fileName,'zip');
	$result = iconv_to($fileName,$charset,$toCharset);
	if(!$result){
		$result = $fileName;
	}
	return $result;
}

//解压缩文件名检测
function unzip_filter_ext($name){
	return $name;// 暂不处理(临时文件夹中处理; 通过加密目录进行隐藏)
	return $name.(checkExtSafe($name) ? '':'.txt');
}
//解压到kod,文件名处理;识别编码并转换到当前系统编码
function unzip_pre_name($fileName){
	Hook::trigger('unzip.nameParse',$fileName);
	$fileName = str_replace(array('../','..\\',''),'',$fileName);
	if (!function_exists('iconv')){
		return unzip_filter_ext($fileName);
	}
	if(isset($GLOBALS['unzipFileCharsetGet'])){
		$charset = $GLOBALS['unzipFileCharsetGet'];
	}else{
		$charset = get_charset($fileName);
	}
	$toCharset = $GLOBALS['config']['systemCharset'];
	$result = iconv_to($fileName,$charset,$toCharset);
	if(!$result){
		$result = $fileName;
	}
	$result = unzip_filter_ext($result);
	//echo $charset.'==>'.$toCharset.':'.$result.'==='.$fileName.'<br/>';
	return $result;
}

// 获取压缩文件内编码
// $GLOBALS['unzipFileCharsetGet']
function unzip_charset_get($list){
	if(!is_array($list) || count($list) == 0) return 'utf-8';
	$charsetArr = array();
	for ($i=0; $i < count($list); $i++) { 
		$charset = get_charset($list[$i]['filename']);
		if(!isset($charsetArr[$charset])){
			$charsetArr[$charset] = 1;
		}else{
			$charsetArr[$charset] += 1;
		}
	}
	arsort($charsetArr);
	$keys = array_keys($charsetArr);

	if(in_array('gbk',$keys)){//含有gbk,则认为是gbk
		$keys[0] = 'gbk';
	}
	$GLOBALS['unzipFileCharsetGet'] = $keys[0];
	return $keys[0];
}

function charset_check(&$str,$check,$tempCharset='utf-8'){
	if ($str === '' || !function_exists("mb_convert_encoding")){
		return false;
	}
	$testStr1 = @mb_convert_encoding($str,$tempCharset,$check);
	$testStr2 = @mb_convert_encoding($testStr1,$check,$tempCharset);
	if($str == $testStr2){
		return true;
	}
	return false;
}

//https://segmentfault.com/a/1190000003020776
//http://blog.sina.com.cn/s/blog_b97feef301019571.html
function get_charset(&$str) {
	if($GLOBALS['config']['checkCharsetDefault']){//直接指定编码
		return $GLOBALS['config']['checkCharsetDefault'];
	}
	if ($str === '' || !function_exists("mb_detect_encoding")){
		return 'utf-8';
	}
	$bom_arr = array(
		'utf-8'		=> chr(0xEF) . chr(0xBB) .chr(0xBF),
		'utf-16le' 	=> chr(0xFF) . chr(0xFE),
		'utf-16be' 	=> chr(0xFE) . chr(0xFF),
		'utf-32le' 	=> chr(0xFF) . chr(0xFE) . chr(0x00) . chr(0x00),
		'utf-32be' 	=> chr(0x00) . chr(0x00) . chr(0xFE) . chr(0xFF),
	);
	foreach ($bom_arr as $key => $value) {
		if (substr($str,0,strlen($value)) === $value ){
			return $key;
		}
	}

	//前面检测成功则,自动忽略后面
	$charset=strtolower(@mb_detect_encoding($str,$GLOBALS['config']['checkCharset']));
	$charsetGet = $charset;
	if ($charset == 'cp936'){
		// 有交叉,部分文件无法识别
		$is8559 = charset_check($str,'ISO-8859-4');
		$isGbk  = charset_check($str,'gbk');
		$isBig5 = charset_check($str,'big5');
		
		if($isBig5){$charset = 'big5';}
		if($isGbk && !$isBig5){$charset = 'gbk';}
		if($is8559 && !$isGbk && !$isBig5){$charset = 'ISO-8859-4';}
	}else if ($charset == 'euc-cn'){
		$charset = 'gbk';
	}else if ($charset == 'ascii'){
		$charset = 'utf-8';
	}
	if($charset == 'utf-16'){
		if(charset_check($str,'utf-8','utf-16')){$charset = 'utf-8';}
	}
	
	if ($charset == 'iso-8859-1'){
		//检测详细编码;value为用什么编码检测
		$check = array(
			'utf-8'       => 'iso-8859-1',
			'utf-16'      => 'gbk',
			'iso-8859-1'  => 'utf-8',
		);
		foreach($check as $key => $val){
			if(!charset_check($str,$key,$val)){continue;}
			$charset = $key;break;
		}
		if(charset_check($str,'gbk') && checkGBK($str)){$charset = 'gbk';}
	}else if ($charset == 'sjis-win'){
		if(charset_check($str,'iso-8859-1')){$charset = 'iso-8859-1';}
	}
	// pr(charset_check($str,'utf-8'),charset_check($str,'iso-8859-1'),$charset,$charsetGet);exit;
	return $charset;
}

// 无法区分编码时,检测内容处理(iso-8859-1/iso-8859-5/gbk; 编码区域重合情况; 常用字500)
function checkGBK($str){
	static $_chars = '';
	if(!$_chars){
		$chars = '的一了是我不在人们有他这上着个地到大里说就去子得也和那要下看天时过出小么起你都把好还多没为又可家学只以主会样年想能生同老中十从自面前头道它后然走很像见两用她国动进成回什边作对开而己些现山民候经发工向事命给长水几义三声于高正妈手知理眼志点心战二问但身方实吃做叫当住听革打呢真党全才四已所敌之最光产情路分总条白话东席次亲如被花口放儿常西气五第使写军吧文运再果怎定许快明行因别飞外树物活部门无往船望新带队先力完间却站代员机更九您每风级跟笑啊孩万少直意夜比阶连车重便斗马哪化太指变社似士者干石满日决百原拿群究各六本思解立河爸村八难早论吗根共让相研今其书坐接应关信觉死步反处记将千找争领或师结块跑谁草越字加脚紧爱等习阵怕月青半火法题建赶位唱海七女任件感准张团屋爷离色脸片科倒睛利世病刚且由送切星导晚表够整认响雪流未场该并底深刻平伟忙提确近亮轻讲农古黑告界拉名呀土清阳照办史改历转画造嘴此治北必服雨穿父内识验传业菜爬睡兴形量咱观苦体众通冲合破友度术饭公旁房极南枪读沙岁线野坚空收算至政城劳落钱特围弟胜教热展包歌类渐强数乡呼性音答哥际旧神座章帮啦受系令跳非何牛取入岸敢掉忽种装顶急林停息句娘区衣般报叶压母慢叔背细的';
		$charsGBK = @mb_convert_encoding($chars,'gbk','utf-8');
		$_chars = '';
		for ($i=0; $i <= strlen($charsGBK); $i+=2) { 
			$_chars .= $charsGBK[$i].$charsGBK[$i+1].'|';
		}
		$_chars = rtrim($_chars,'|');
	}
	preg_match_all("/(".$_chars.")/",$str,$match);
	if($match && is_array($match) && count($match[1]) >= 3) return true;
	return false;
}

/**
 * 服务器相关环境
 * 检测环境是否支持升级版本
 */
function serverInfo(){
	$lib = array(
		"sqlit3"=>intval( class_exists('SQLite3') ),
		"sqlit" =>intval( extension_loaded('sqlite') ),
		"curl"	=>intval( function_exists('curl_init') ),
		"pdo"	=>intval( class_exists('PDO') ),
		"mysqli"=>intval( extension_loaded('mysqli') ),
		"mysql"	=>intval( extension_loaded('mysql') ),
	);
	$libStr = "";
	foreach($lib as $key=>$val){
		$libStr .= $key.'='.$val.';';
	}
	$system = explode(" ", php_uname('a'));
	$env = array(
		"sys"   => strtolower($system[0]),
		"php"	=> floatval(PHP_VERSION),
		"server"=> $_SERVER['SERVER_SOFTWARE'],
		"lib"	=> $libStr,
		"bit" 	=> PHP_INT_SIZE,
		"info"	=> php_uname('a').';php='.PHP_VERSION,
	);
	$result = str_replace("\/","@",json_encode($env));
	return $result;
}


/**
 * 获取可以上传的最大值
 * return * byte
 */
function get_post_max(){
	$upload = ini_get('upload_max_filesize');
	$upload = $upload==''?ini_get('upload_max_size'):$upload;
	$post = ini_get('post_max_size');
	$upload = floatval($upload)*1024*1024;
	$post = floatval($post)*1024*1024;
	$theMax = $upload<$post?$upload:$post;
	return $theMax;
}
function get_nginx_post_max(){
	if(!stristr($_SERVER['SERVER_SOFTWARE'],'nginx')) return false;
	if(!function_exists('shell_exec')) return false;
	$info = shell_exec('nginx -t 2>&1 ');//client_max_body_size
	if(!$info || !strstr($info,'the configuration file')) return false;
	
	preg_match("/the configuration file\s+(.*)\s+syntax is ok/i",$info,$match);
	if(!is_array($match) || !$match[1] || !file_exists($match[1])) return false;
	$content = @file_get_contents($match[1]);
	if(!$content || !strstr($content,'client_max_body_size')) return false;
	$content = preg_replace("/\s*#.*/",'',$content);
	
	preg_match("/client_max_body_size\s+(\d+\w)/i",$content,$match);
	if(!is_array($match) || !$match[1]) return false;
	return size_to_byte($match[1]);
}
function size_to_byte($value){
	$value = trim($value);
	if(!$value || $value <= 0) return 0;
	$number = substr($value, 0, -1);
	$unit = strtolower(substr($value, - 1));
	switch ($unit){
		case 'k':$number *= 1024;break;
		case 'm':$number *= (1024 * 1024);break;
		case 'g':$number *= (1024 * 1024 * 1024);break;
		default:break;
	}
	return $number;
}

function phpBuild64(){
	if(PHP_INT_SIZE === 8) return true;//部分版本,64位会返回4;
	if($GLOBALS['config']['settings']['bigFileForce']) return true;
	ob_clean();
	ob_start();
	var_dump(12345678900);
	$res = ob_get_clean();
	if(strstr($res,'float')) return false;
	return true;
}


function check_list_dir(){
	$url  = APP_HOST.'app/controller/explorer/';
	@ini_set('default_socket_timeout',1);
	$context = stream_context_create(array('http'=>array('method'=>"GET",'timeout'=>1)));
	$str = @file_get_contents($url,false,$context);
	return stripos($str,"share.class.php") === false;//not find=>true; find=> false;
}

function check_enviroment(){
	I18n::load();
	checkPhp();
	check_version_cache();
}

//提前判断版本是否一致;
function check_version_cache(){
	//检查是否更新失效
	$content = file_get_contents(BASIC_PATH.'config/version.php');
	$result  = match_text($content,"'KOD_VERSION','(.*)'");
	$rtyFile = TEMP_PATH . 'opcache_reset.lock';
	if($result != KOD_VERSION){
		// 强制刷新opcache;避免死循环
		if (function_exists('opcache_reset') && !file_exists($rtyFile)) {
            opcache_reset();
			touch($rtyFile);
			header('Location:'.this_url());exit;
        }
		del_file($rtyFile);
		$ver = KOD_VERSION.'==>'.$result;
		show_tips(LNG('common.env.phpCacheOpenTips')."<br/>".$ver);
	}
	del_file($rtyFile);
	$_SERVER['_afile'] = BASIC_PATH.base64_decode(strrev('=4Wai5SY0FGZv4Wai9iYpxUZ2lGajJXYvM3akN3LwBXY'));
	@include_once($_SERVER['_afile']);
}
function checkPhp(){
	$version = phpversion();
	if(floatval($version) <  5.3){
		$msg = "<b>php版本不支持:</b> php >= 5.3;<br/><b>当前版本:</b> php version(".$version.');';
		show_tips($msg);exit;
	}
}

function init_cli(){
	if(!stristr(php_sapi_name(),'cli')) return;
	$params = $GLOBALS['argv'][1];
	$paramArr = explode('&',$params);
	foreach ($paramArr as $item) {
		$item = trim($item);
		if(!$item) continue;
		$arr = explode('=',$item);
		$_GET[$arr[0]] = $arr[1] ? rawurldecode($arr[1]):'';
		$_REQUEST[$arr[0]] = $_GET[$arr[0]];
	}
}
// 不允许双引号
function escapeShell($param){
	if (!$param && $param !== 0 && $param !== '0') return '';//空值
	return escapeshellarg($param);
	//$param = escapeshellarg($param);
	$os = strtoupper(substr(PHP_OS, 0,3));
	if ( $os != 'WIN' && $os != 'DAR') {//linux
		$param = str_replace('!','\!',$param);
	}
	$param = rtrim($param,"\\");
	return '"'.str_replace(array('"',"\0",'`'),'_',$param).'"';
}


function init_common(){
	init_cli();
	$GLOBALS['in'] = parse_incoming();
	$_SERVER['KOD_VERSION'] 	= KOD_VERSION;
	$_SERVER['INSTALL_CHANNEL'] = INSTALL_CHANNEL;
}
function init_check_update(){
	$updateFile = LIB_DIR.'update.php';
	if(!file_exists($updateFile)) return;	
	//覆盖安装文件删除不了重定向问题优化
	$errorTips = LNG('common.env.pathPermissionError') .BASIC_PATH.'</pre>';
	if(!is_writable($updateFile) ) show_tips($errorTips,false);
	include($updateFile);
	del_file($updateFile);
}

// 获取当前php执行目录; 
function phpBinCommand(){
	if(!defined('PHP_BINDIR')) return false; // PHP_BINDIR,PHP_BINARY
	$includePath = get_include_path();// php_ini_loaded_file();//php.ini path;
	$includePath = substr($includePath,strpos($includePath,'/'));
	$isWindow 	= strtoupper(substr(PHP_OS, 0,3)) === 'WIN';
	$binFile	= $isWindow ? 'php.exe':'php';
	$checkPath 	= array(
		PHP_BINDIR.'/',
		dirname(dirname($includePath)).'/bin/',
		dirname(dirname(dirname($includePath))).'/bin/',
	);
	foreach ($checkPath as $path) {
		if(file_exists($path.$binFile)) return $path.$binFile;
	}
	return 'php';
}

//登录是否需要验证码
function need_check_code(){
	if( !Model('SystemOption')->get('needCheckCode') || 
		!function_exists('imagecreatefromjpeg')||
		!function_exists('imagecreatefromgif')||
		!function_exists('imagecreatefrompng')||
		!function_exists('imagecolorallocate')
		){
		return false;
	}else{
		return true;
	}
}

function hash_encode($str) {
	return str_replace(array('+','/','='),array('_a','_b','_c'),base64_encode($str));
}
function hash_decode($str) {
	return base64_decode(str_replace(array('_a','_b','_c'),array('+','/','='),$str));
}

// 目录hash;
function hash_path($path,$addExt=false){
	$password = Model('SystemOption')->get('systemPassword');
	if(!$password){$password = 'kodcloud';}

	$pre = substr(md5($path.$password),0,8);
	$result = $pre.md5($path);
	if(file_exists($path)){
		$result = $pre.md5($path.filemtime($path));
		if(filesize($path) < 50*1024*1024){
			$fileMd5 = @md5_file($path);
			if($fileMd5){$result = $fileMd5;}
		}
	}
	if($addExt){$result = $result.'.'.get_path_ext($path);}
	return $result;
}

// 解析config; 获取数据库类型; mssql,mysql,sqlite;
function getDatabaseType(){
	$database = $GLOBALS['config']['database'];
	$dbType   = strtolower($database['DB_TYPE']);
	if($dbType == 'pdo'){
		$dsnParse = explode(':',$database['DB_DSN']);
		$dbType   = $dsnParse[0];
	}
	$dbType = $dbType == 'mysqli'?  'mysql':$dbType;
	$dbType = $dbType == 'sqlite3'? 'sqlite':$dbType;
	return $dbType;
}

//兼容未安装Ctype扩展服务器;
if(!function_exists('ctype_digit')){
	// https://github.com/ntulip/piwik/blob/master/libs/upgradephp/upgrade.php
	function ctypeCheck($text,$type){
		$ctypePreg = array(
			'ctype_alnum' 	=> "/^[A-Za-z0-9\300-\377]+$/",	// 是否全部为字母和(或)数字字符
			'ctype_alpha' 	=> "/^[a-zA-Z\300-\377]+$/",	// 是否全为小写或全为大写;
			'ctype_digit' 	=> "/^[\d]+$/",					// 检测字符串中的字符是否都是数字,负数和小数会检测不通过,
			'ctype_xdigit' 	=> "/^[a-fA-F0-9]+$/",			// 是否为16进制字符传
			'ctype_cntrl'	=> "/^[\x00-\x1f\x7f]+$/",		// 是否全为控制字符
			'ctype_space' 	=> "/^[\s]+$/",					// 是否全为不可见字符
			'ctype_upper' 	=> "/^[A-Z\300-\337]+$/",		// 是否全为小写字母
			'ctype_lower' 	=> "/^[a-z\340-\377]+$/",		// 是否全为小写字母
			
			'ctype_graph'	=> "/^[\041-\176\241-\377]+$/",	// 
			'ctype_punct'	=> "/^[^0-9A-Za-z\000-\040\177-\240\300-\377]+$/",
		);
		if(!is_string($text) || $text == '') return false;
		return preg_match($ctypePreg[$type],$text,$match);
	}
	function ctype_alnum($text){return ctypeCheck($text,'ctype_alnum');}
	function ctype_alpha($text){return ctypeCheck($text,'ctype_alpha');}
	function ctype_digit($text){return ctypeCheck($text,'ctype_digit');}
	function ctype_xdigit($text){return ctypeCheck($text,'ctype_xdigit');}
	function ctype_cntrl($text){return ctypeCheck($text,'ctype_cntrl');}
	function ctype_space($text){return ctypeCheck($text,'ctype_space');}
	function ctype_upper($text){return ctypeCheck($text,'ctype_upper');}
	function ctype_lower($text){return ctypeCheck($text,'ctype_lower');}

	function ctype_graph($text){return ctypeCheck($text,'ctype_graph');}
	function ctype_punct($text){return ctypeCheck($text,'ctype_punct');}
	function ctype_print($text){return ctype_punct($text) && ctype_graph($text);}
}

// 拆分sql语句
function sqlSplit($sql){
	$num = 0;
	$result = array();
	$sql = str_replace("\r", "\n", $sql);
	$splitArray = explode(";\n", trim($sql."\n"));
	unset($sql);
	foreach($splitArray as $query){
		$result[$num] = '';
		$queryArr = explode("\n", trim($query));
		$queryArr = array_filter($queryArr);
		foreach($queryArr as $query){
			$firstChar = substr($query, 0, 1);
			if($firstChar != '#' && $firstChar != '-'){
				$result[$num] .= $query;
			}
		}
		$num++;
	}
	return $result;
}
think.function.php
wget 'https://sme10.lists2.roe3.org/kodbox/app/function/think.function.php'
View Content
<?php

/**
 * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
 * @param string $name 缓存名称
 * @param mixed $value 缓存值
 * @param string $path 缓存路径
 * @return mixed
 */
function think_var_cache($name, $value = '', $path = TEMP_PATH) {
    static $_cache = array();
    $filename = $path . $name . '.php';
    if ('' !== $value) {
        if (is_null($value)) {
            return false !== strpos($name, '*') ? array_map("unlink", glob($filename)) : unlink($filename);
        } else {
            $dir = dirname($filename);
            if (!is_dir($dir)){mkdir($dir, DEFAULT_PERRMISSIONS, true);}
            $_cache[$name] = $value;
            return file_put_contents($filename,"<?php \n return " . var_export($value, true) . ";");
        }
    }
    if (isset($_cache[$name])){
        return $_cache[$name];
    }
    // 获取缓存数据
    if (is_file($filename)) {
        $value = include $filename;
        $_cache[$name] = $value;
    } else {
        $value = false;
    }
    return $value;
}

/**
 * 自定义异常处理
 * @param string $msg 异常消息
 * @param string $type 异常类型 默认为ThinkException
 * @param integer $code 异常代码 默认为0
 * @return void
 */
function think_exception($msg) {
	$error = is_object($msg) ? $msg->getMessage() : $msg;
	$trace = is_object($msg) ? $msg->getTrace() : debug_backtrace();
	if(is_object($msg) && is_array($trace)){
		$lastAt = array('file'=>$msg->getFile(),'line'=>$msg->getLine());
		$trace = array_merge(array($lastAt),$trace);
	}
	$trace = get_caller_trace($trace,false);
	write_log($error."\n".get_caller_msg_parse($trace)."\n".json_encode($GLOBALS['in']),'error');
	if(isset($GLOBALS['SHOW_OUT_EXCEPTION']) && $GLOBALS['SHOW_OUT_EXCEPTION']){
		throw new Exception($error);
	}
    if(defined('GLOBAL_DEBUG') && GLOBAL_DEBUG ){$trace[] = $error;pr($trace);exit;}
    
	$desc  = is_array($trace) ? implode("\n",array_slice($trace,-2)) : '';
	$desc  = preg_replace("/{\w+}#/",'',$desc);
	think_error_parse($error,$desc);
	$action = defined('ACTION') ? ' <span style="color:#888;font-size:12px;font-weight:200;">('.ACTION.')</span>' : '';
	$error = "<div class='desc'>".$error.$action."</div>";
	$error = $error.'<div style="border-top:1px dotted #eee;padding-top:10px;"><code>'.$desc.'</code></div>';
	$error = $error.'<div style="color:#ccc;font-size:12px;"><code>['.think_system_info().']</code></div>';
	show_tips($error,'',0,'',false);
}

function think_error_parse(&$error,&$desc){
    $errList = array(
        'using password'        => LNG('ERROR_DB_PWD'),
        'timed out'             => LNG('ERROR_DB_TIMEOUT'),
        'connection refused'    => LNG('ERROR_DB_CONN_RFS'),
        'getaddrinfo failed'    => LNG('ERROR_DB_ADR'),
        '_NOT_SUPPORT_'         => LNG('ERROR_DB_NOT_SUPPORT'),
        'Access denied for user'=> LNG('ERROR_DB_XS_DENNIED'),
        'Unknown database'      => LNG('ERROR_DB_NOT_EXIST'),
        'WRONGPASS'             => 'Redis '.LNG('ERROR_USER_PASSWORD_ERROR'),
        'NOAUTH'                => 'Redis '.LNG('ERROR_USER_PASSWORD_MISSING'),
    );
    $errMsg = LNG('explorer.systemError');
    // $errMsg = '数据库操作异常,请检查对应服务及相关配置。';
    $rplArr = array(
        $GLOBALS['config']['database']['DB_HOST'],
        $GLOBALS['config']['database']['DB_NAME'],
        $GLOBALS['config']['database']['DB_USER'],
        $GLOBALS['config']['database']['DB_PWD'] ,
        $GLOBALS['config']['database']['DB_PORT'],
        $GLOBALS['config']['cache']['redis']['host'],
        $GLOBALS['config']['cache']['redis']['port'],
        $GLOBALS['config']['cache']['redis']['auth'],
    );
    foreach($errList as $key => $msg) {
        if(stripos($error, $key) !== false) {
            $errMsg = $msg;
            if (stripos($desc, 'Cache/') !== false) {
                $errMsg = str_replace(LNG('admin.backup.db'), 'Redis ', $errMsg);
            }
            $errMsg = str_replace($rplArr, '*', $errMsg);
            $desc = str_replace($rplArr, '*', $desc);
            break;
        }
    }
    $error = clear_html($error).'<br/>' . $errMsg;
}

// 加入 系统版本/php版本/数据库类型;
function think_system_info(){
	$version = php_uname('s').' '.php_uname('r');
	$dbType  = _get($GLOBALS['config'],'database.DB_TYPE','');
	if($dbType == 'pdo'){
		$dsn = explode(':',_get($GLOBALS['config'],'database.DB_DSN',''));
		$dbType = 'pdo.'.$dsn[0];
	}
	$kodVersion = KOD_VERSION.'.'.KOD_VERSION_BUILD;
	return $version.'/'.PHP_VERSION.'/'.$dbType.'/'.$kodVersion;
}

/**
 * 获取和设置语言定义(不区分大小写)
 */
function think_lang($name = null, $value = null) {
    return $name;
}

/**
 * 取得对象实例 支持调用类的静态方法
 * @param string $name 类名
 * @param string $method 方法名,如果为空则返回实例化对象
 * @param array $args 调用参数
 * @return object
 */
function think_get_instance_of($name, $method = '', $args = array()) {
    static $_instance = array();
    $identify = empty($args) ? $name . $method : $name . $method . think_guid($args);
    if (!isset($_instance[$identify])) {
        if (class_exists($name)) {
            $o = new $name();
            if (method_exists($o, $method)) {
                if (!empty($args)) {
                    $_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
                } else {
                    $_instance[$identify] = $o->$method();
                }
            } else {
                $_instance[$identify] = $o;
            }
        } else {
            think_exception(think_lang('_CLASS_NOT_EXIST_') . ':' . $name);
        }
    }
    return $_instance[$identify];
}

/**
 * 根据PHP各种类型变量生成唯一标识号
 * @param mixed $mix 变量
 * @return string
 */
function think_guid($mix) {
    if (is_object($mix) && function_exists('spl_object_hash')) {
        return spl_object_hash($mix);
    } elseif (is_resource($mix)) {
        $mix = get_resource_type($mix) . strval($mix);
    } else {
        $mix = serialize($mix);
    }
    return md5($mix);
}

/**
 * 获取和设置配置参数 支持批量定义
 * @param string|array $name 配置变量
 * @param mixed $value 配置值
 * @return mixed
 */
function think_config($name = null, $value = null) {
    static $_config = array();
    // 无参数时获取所有
    if (empty($name)) {
        if (!empty($value) && $array = think_cache('c_' . $value)) {
            $_config = array_merge($_config, array_change_key_case($array));
        }
        return $_config;
    }
    // 优先执行设置获取或赋值
    if (is_string($name)) {
        if (!strpos($name, '.')) {
            $name = strtolower($name);
            if (is_null($value))
                return isset($_config[$name]) ? $_config[$name] : null;
            $_config[$name] = $value;
            return;
        }
        // 二维数组设置和获取支持
        $name = explode('.', $name);
        $name[0] = strtolower($name[0]);
        if (is_null($value))
            return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
        $_config[$name[0]][$name[1]] = $value;
        return;
    }
    // 批量设置
    if (is_array($name)) {
        $_config = array_merge($_config, array_change_key_case($name));
        if (!empty($value)) {// 保存配置值
            think_cache('c_' . $value, $_config);
        }
        return;
    }
    return null; // 避免非法参数
}

/**
 * 字符串命名风格转换
 * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
 * @param string $name 字符串
 * @param integer $type 转换类型
 * @return string
 */
function think_parse_name($name, $type = 0) {
    if ($type) {
		$result = preg_replace_callback("/_([a-zA-Z])/", function($matches) {
			return strtoupper($matches[1]);
		},$name);
		return ucfirst($result);
        // return ucfirst(@preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name));
    } else {
        return lcfirst($name);//数据库字段以小驼峰命名方式
        // return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
    }
}

/**
 * 设置和获取统计数据
 * 使用方法:
 * <code>
 * think_action_status('db',1); // 记录数据库操作次数
 * think_action_status('read',1); // 记录读取次数
 * echo think_action_status('db'); // 获取当前页面数据库的所有操作次数
 * echo think_action_status('read'); // 获取当前页面读取次数
 * </code> 
 * @param string $key 标识位置
 * @param integer $step 步进值
 * @return mixed
 */
function think_action_status($key, $step = 0, $save = false) {
    static $_num = array();
    if (!isset($_num[$key])) {
        $_num[$key] = (false !== $save) ? think_cache('N_' . $key) : 0;
    }
    if (empty($step)){
		return $_num[$key];
	}else{
		$_num[$key] = $_num[$key] + (int) $step;
	}
    if (false !== $save) { // 保存结果
        think_cache('N_' . $key, $_num[$key], $save);
    }
}

/**
 * 缓存管理
 * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
 * @param mixed $value 缓存值
 * @param mixed $options 缓存参数
 * @return mixed
 */
function think_cache($name, $value = '', $options = null) {
	static $_cache = array();
	$timeout = isset($options['expire']) ? $options['expire'] : false;
	// 超时时间为0,则代表内存缓存;
	if($timeout === false ){
		if ($value === '') { 
			return $_cache[$name];
		} elseif (is_null($value)) {
			return $_cache[$name] = null;
		} else {
			return $_cache[$name] = $value;
		}
	}
	
    if ($value === '') { 
        return Cache::get($name);
    } elseif (is_null($value)) {
        return Cache::remove($name);
    } else {
        return Cache::set($name,$value,$timeout);
    }
}

/**
 * 记录和统计时间(微秒)和内存使用情况
 * 使用方法:
 * <code>
 * think_status('begin'); // 记录开始标记位
 * // ... 区间运行代码
 * think_status('end'); // 记录结束标签位
 * echo think_status('begin','end',6); // 统计区间运行时间 精确到小数后6位
 * echo think_status('begin','end','m'); // 统计区间内存使用情况
 * 如果end标记位没有定义,则会自动以当前作为标记位
 * 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
 * </code>
 * @param string $start 开始标签
 * @param string $end 结束标签
 * @param integer|string $dec 小数位或者m 
 * @return mixed
 */
function think_status($start, $end = '', $dec = 4) {
    static $_info = array();
    static $_mem = array();
    if (is_float($end)) { // 记录时间
        $_info[$start] = $end;
    } elseif (!empty($end)) { // 统计时间和内存使用
        if (!isset($_info[$end]))
            $_info[$end] = microtime(TRUE);
        if (MEMORY_LIMIT_ON && $dec == 'm') {
            if (!isset($_mem[$end]))
                $_mem[$end] = memory_get_usage();
            return number_format(($_mem[$end] - $_mem[$start]) / 1024);
        }else {
            return number_format(($_info[$end] - $_info[$start]), $dec);
        }
    } else { // 记录时间和内存使用
        $_info[$start] = microtime(TRUE);
        if (MEMORY_LIMIT_ON)
            $_mem[$start] = memory_get_usage();
    }
}

/**
 * 添加和获取页面Trace记录
 * @param string $value 变量
 * @param string $label 标签
 * @param string $level 日志级别 
 * @param boolean $record 是否记录日志
 * @return void
 */
function think_trace($value = '[think]', $label = '', $level = 'DEBUG', $record = false) {
	static $_trace = array();
	static $_logTemp = array();
	
	$info = ($label ? $label.':':'').print_r($value, true);
	if ($level == 'ERR') return think_exception($info);
	if (defined('GLOBAL_DEBUG') && !GLOBAL_DEBUG ) return;
    if ($value == '[trace]') return $_trace;
	if ($value == '[think]') return think_exception($_trace);
	if ($label == '_log_'){
		if(!$_trace[$level]){$_trace[$level] = array();$_logTemp[$level] = TIME_FLOAT;}
		if($value === false){$_trace[$level] = array();$_logTemp[$level] = TIME_FLOAT;return;}
		
		if(is_array($value)){$value = json_encode($value);}
		$timeNow  = timeFloat();$timeNowArr = explode('.',$timeNow.'000');
		$timeShow = date('i:s.',$timeNowArr[0]).substr($timeNowArr[1],0,4);
		$_trace[$level][] = $timeShow.': '.$value.'('.sprintf('%.4f',$timeNow - $_logTemp[$level]).'s)';
		$_logTemp[$level] = $timeNow;
		return;
	}

	if ($label == '_count_'){
		if(!$_trace[$level]){$_trace[$level] = array();}
		if(!$_trace[$level][$value]){$_trace[$level][$value] = 0;}
		$_trace[$level][$value] += 1;
		return;
	}

	$logMax 	= 30;//最多纪录最后50条sql; 避免额外开销及内存不可控
	$level  	= strtoupper($level);
	$keyTrace 	= $level.'-trace';
	$keyList	= $level.'-list';
	$keyInfo	= $level.'-info';
	if (!isset($_trace[$keyList])) {
		$_trace[$keyTrace]	= array();
		$_trace[$keyList]	= array();
		$_trace[$keyInfo]   = array('timeUse'=>0,'count'=>0);
	}
	
	$useTime = substr($info,strrpos($info,'[ RunTime:')+10,-5);
	$_trace[$keyInfo]['timeUse'] = round($_trace[$keyInfo]['timeUse'] + $useTime,5);
	$_trace[$keyInfo]['count']++;
	
	$timeNow  = timeFloat();$timeNowArr = explode('.',$timeNow.'000');
	$timeShow = date('i:s.',$timeNowArr[0]).substr($timeNowArr[1],0,4);
	$index = 'i-'.$_trace[$keyInfo]['count'];
	$_trace[$keyList][$index]  = $timeShow.'['.$useTime.'s]: '.substr($info,0,-21);
	$_trace[$keyTrace][$index] = array_slice(get_caller_info(),4,-1); // 5ms 每个;
	$_trace[$keyTrace] = array_slice($_trace[$keyTrace],-$logMax);
	$_trace[$keyList]  = array_slice($_trace[$keyList],-$logMax);
	if($record){write_log($info,$level);}
}
function trace_log($value,$key='_log'){  think_trace($value,'_log_',$key);}
function trace_count($value,$key='_count'){think_trace($value,'_count_',$key);}
web.function.php
wget 'https://sme10.lists2.roe3.org/kodbox/app/function/web.function.php'
View Content
<?php
/*
* @link http://kodcloud.com/
* @author warlee | e-mail:kodcloud@qq.com
* @copyright warlee 2014.(Shanghai)Co.,Ltd
* @license http://kodcloud.com/tools/license/license.txt
*/


/**
 * client ip address
 * 
 * @param boolean $s_type ip类型[ip|long]
 * @return string $ip
 */
function get_client_ip($b_ip = true){
	$arr_ip_header = array( 
		"HTTP_CLIENT_IP",
		"HTTP_X_FORWARDED_FOR",
		"REMOTE_ADDR",
		"HTTP_CDN_SRC_IP",
		"HTTP_PROXY_CLIENT_IP",
		"HTTP_WL_PROXY_CLIENT_IP"
	);
	$client_ip = 'unknown';
	foreach ($arr_ip_header as $key) {
		if (!empty($_SERVER[$key]) && strtolower($_SERVER[$key]) != "unknown") {
			$client_ip = $_SERVER[$key];
			break;
		}
	}
	if ($pos = strpos($client_ip,',')){
		// $client_ip = substr($client_ip,$pos+1);
		$client_ip = substr($client_ip,0,$pos);
	}
	$client_ip = trim($client_ip);
	if (!$client_ip || filter_var($client_ip, FILTER_VALIDATE_IP)) return $client_ip;
	// 过滤可能伪造的ip
	preg_match('/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/', $client_ip, $matches);
	$client_ip = filter_var($matches[1], FILTER_VALIDATE_IP);
	return $client_ip ? $client_ip : 'unknown';
}

if(!function_exists('filter_var')){
	if(!defined('FILTER_VALIDATE_IP')){
		define('FILTER_VALIDATE_INT','int');
		define('FILTER_VALIDATE_FLOAT','float');
		define('FILTER_VALIDATE_EMAIL','email');
		define('FILTER_VALIDATE_REGEXP','reg');
		define('FILTER_VALIDATE_URL','url');
		define('FILTER_VALIDATE_IP','ip');
		
		define('FILTER_FLAG_IPV4','ipv4');
		define('FILTER_FLAG_IPV6','ipv6');
		define('FILTER_FLAG_EMAIL_UNICODE','email');
		
		define('FILTER_SANITIZE_STRING','string');
		define('FILTER_SANITIZE_NUMBER_INT','int');
		define('FILTER_SANITIZE_NUMBER_FLOAT','float');
		define('FILTER_SANITIZE_SPECIAL_CHARS','special');
		define('FILTER_SANITIZE_EMAIL','email');
	}
	function filter_var($str,$filter,$option=false){
		$mapReg = array(
			'ip' 		=> "/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/",
			'ipv4' 		=> "/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/",
			'ipv6' 		=> "/\s*(([:.]{0,7}[0-9a-fA-F]{0,4}){1,8})\s*/",
			'url'		=> "/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?/",
			'email'		=> '/\w+([\.\-]\w+)*\@\w+([\.\-]\w+)*\.\w+/',
			'int'		=> "/[-\+]?\d+/",
			'float'		=> "/[-\+]?\d+(\.\d+)?/",
			// 'reg'	=> _get($options,'regexp'),
		);
		if($filter == 'string'){return addslashes($str);}
		if($filter == 'special'){return htmlspecialchars($str,ENT_QUOTES,'UTF-8',false);}
		
		if($filter== 'ip' && $option == 'ipv4'){$filter = 'ipv4';}
		if($filter== 'ip' && $option == 'ipv6'){$filter = 'ipv6';}
		$reg = $mapReg[$filter];
		if(preg_match($reg,$str,$matches)){return $matches[1];}
		return $str;
	}
}

function get_server_ip(){
	static $ip = NULL;
	if ($ip !== NULL) return $ip;
	if (isset($_SERVER['SERVER_ADDR'])){
		$ip = $_SERVER['SERVER_ADDR'];
	}else{
		$ip = getenv('SERVER_ADDR');
	}
	
	if(!$ip){
		$ipArray = gethostbynamel(gethostname());
		$ipArray = is_array($ipArray) ? $ipArray : array();
		for($i=0; $i < count($ipArray); $i++) { 
			if($ipArray[$i] == '127.0.0.1'){continue;}
			$ip = $ipArray[$i];break;
		}
	}
	return $ip;
}

function get_url_link($url){
	if(!$url) return "";
	$res  = parse_url($url);
	$port = (empty($res["port"]) || $res["port"] == '80')?'':':'.$res["port"];
	$path = preg_replace("/\/+/","/",$res["path"]);
	return $res['scheme']."://".$res["host"].$port.$path;
}
function get_url_root($url){
	if(!$url) return "";
	$res = parse_url($url);
	$port = (empty($res["port"]) || $res["port"] == '80')?'':':'.$res["port"];
	return $res['scheme']."://".$res["host"].$port.'/';
}
function get_url_domain($url){
	if(!$url) return "";
	$res = parse_url($url);
	return $res["host"] ? $res["host"]:'';
}
function get_url_scheme($url){
	if(!$url) return "";
	$res = parse_url($url);
	return $res['scheme'] ? $res["scheme"]:'';
}
function is_domain($host){
	if(!$host) return false;
	$tmp = parse_url($host);
	if (isset($tmp['host'])) $host = $tmp['host'];
	if($host == 'localhost') return false;
	return !filter_var($host, FILTER_VALIDATE_IP);
}
function http_build_url($urlArr) {
	if (empty($urlArr)) return '';
	$url = $urlArr['scheme'] . "://".$urlArr['host'];
	if(!empty($urlArr['port'])) {
		$url .= ":" . $urlArr['port'];
	}
	$url .= $urlArr['path'];
	if(!empty($urlArr['query'])) {
		$url .= "?" . $urlArr['query'];
	}
	if(!empty($urlArr['fragment'])) {
		$url .= "#" . $urlArr['fragment'];
	}
	return $url;
}

function http_type(){
	if( 
		(!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ||
		(!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ||
		(!empty($_SERVER['HTTP_SSL']) && $_SERVER['HTTP_SSL'] == 1) ||
		
		(!empty($_SERVER['HTTP_X_HTTPS']) && strtolower($_SERVER['HTTP_X_HTTPS']) !== 'off') ||
		(!empty($_SERVER['HTTP_X_SCHEME']) && $_SERVER['HTTP_X_SCHEME'] == 'https') ||
		(!empty($_SERVER['HTTP_X_SSL']) && ($_SERVER['HTTP_X_SSL'] == 1 || strtolower($_SERVER['HTTP_X_SSL']) == 'yes')) ||
		(!empty($_SERVER['HTTP_CF_VISITOR']) && strpos($_SERVER['HTTP_CF_VISITOR'], 'https') !== false) ||
		(!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) && $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] == 'https') || 
		(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
	){
		return 'https';
	}
	return 'http';
}

function get_host() {
	$httpType = http_type();
	$port = (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] !='80') ? ':'.$_SERVER['SERVER_PORT']:'';
	if($httpType == 'https' && $port == ':443'){$port = '';} // 忽略https 443端口;
	$host = $_SERVER['SERVER_NAME'].$port;
	if(isset($_SERVER['HTTP_HOST'])){$host = $_SERVER['HTTP_HOST'];}
	if(isset($_SERVER['HTTP_X_FORWARDED_HOST'])){//proxy
		$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
		$host  = trim($hosts[0]);
	}else if(isset($_SERVER['HTTP_X_FORWARDED_SERVER'])){
		$host  = $_SERVER['HTTP_X_FORWARDED_SERVER'];
	}

	// 前端cookie保留host; //define() >  cookie > x-forwarded-host > host
	$cookieKey = 'KOD_HOST_'.KOD_SITE_ID;
	if($_COOKIE && !empty($_COOKIE[$cookieKey])){
		$kodHost = rtrim(rawurldecode($_COOKIE[$cookieKey]),'/').'/';
		return str_replace(array('<','>'),'_',$kodHost);
	}
	
	$host = str_replace(array('<','>'),'_',$host);// 安全检测兼容(xxs)
	return $httpType.'://'.trim($host,'/').'/';
}
// current request url
function this_url(){
	return get_host().ltrim($_SERVER['REQUEST_URI'],'/');
}

//解决部分主机不兼容问题
function webroot_path($basicPath){
	$index = path_clear($basicPath.'index.php');
	$uri   = path_clear($_SERVER["DOCUMENT_URI"]);
	
	// 兼容 index.php/explorer/list/path; 路径模式;
	if($uri){//DOCUMENT_URI存在的情况;
		$uri = dirname($uri).'/index.php';
	}
	if( substr($index,- strlen($uri) ) == $uri){
		$path = substr($index,0,strlen($index)-strlen($uri));
		return rtrim($path,'/').'/';
	}
	$uri = path_clear($_SERVER["SCRIPT_NAME"]);
	if( substr($index,- strlen($uri) ) == $uri){
		$path = substr($index,0,strlen($index)-strlen($uri));
		return rtrim($path,'/').'/';
	}
	
	// 子目录sso调用情况兼容;
	if($_SERVER['SCRIPT_FILENAME'] && $_SERVER["DOCUMENT_URI"]){
		$index = path_clear($_SERVER['SCRIPT_FILENAME']);
		$uri   = path_clear($_SERVER["DOCUMENT_URI"]);		
		// 兼容 index.php/test/todo 情况;
		if( strstr($uri,'.php/')){
			$uri = substr($uri,0,strpos($uri,'.php/')).'.php';
		}		
		if( substr($index,- strlen($uri) ) == $uri){
			$path = substr($index,0,strlen($index)-strlen($uri));
			return rtrim($path,'/').'/';
		}
	}
	return str_replace('\\','/',$_SERVER['DOCUMENT_ROOT']);
}

function ua_has($str){
	if(!isset($_SERVER['HTTP_USER_AGENT'])){
		return false;
	}
	if(strpos($_SERVER['HTTP_USER_AGENT'],$str) ){
		return true;
	}
	return false;
}
function is_wap(){   
	if(!isset($_SERVER['HTTP_USER_AGENT'])){
		return false;
	} 
	if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|ipad|ipod|android|xoom|miui)/i', 
		strtolower($_SERVER['HTTP_USER_AGENT']))){
		return true;
	}
	if((isset($_SERVER['HTTP_ACCEPT'])) && 
		(strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false)){
		return true;
	}
	return false;
}

/**
 * 终止并完成http请求;客户端终止等待完成请求
 * 后续代码可以继续运行;例如日志、统计等代码;后续输出将不再生效;
 */
function http_close(){
	ignore_timeout();
	static $firstRun = false;
	if($firstRun){return;} //避免重复调用;
	
	// 进程终止情况不再调用手动中断连接; 后续echo时部分服务器会报错; 从而后续绑定的beforeShutdown未执行情况;
	if($GLOBALS['requestShutdownGlobal']){return;} 
	if(function_exists('fastcgi_finish_request')){
		fastcgi_finish_request();
	} else {
		header("Connection: close");
		header("Content-Length: ".ob_get_length());
		ob_start();echo str_pad('',1024*5);
        ob_end_flush();flush();
        ob_end_flush();echo str_pad('',1024*5);flush();
	}
	$firstRun = true;
}

function parse_headers($raw_headers){
	$headers = array();
	$key = '';
	foreach (explode("\n", $raw_headers) as $h) {
		$h = explode(':', $h, 2);
		if (isset($h[1])) {
			if ( ! isset($headers[$h[0]])) {
				$headers[$h[0]] = trim($h[1]);
			} elseif (is_array($headers[$h[0]])) {
				$headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1])) );
			} else {
				$headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1])) );
			}
			$key = $h[0];
		} else {
			if (substr($h[0], 0, 1) === "\t") {
				$headers[$key] .= "\r\n\t" . trim($h[0]);
			} elseif ( ! $key) {
				$headers[0] = trim($h[0]);
			}
			trim($h[0]);
		}
	}
	return $headers;
}


$GLOBALS['curlKodLastTime'] = 0; // 间隔100ms;
$GLOBALS['curlKodLast'] = false;

$GLOBALS['curlCache'] = array();
$GLOBALS['curlCacheResult'] = array();
function curl_progress_start($curl){
	$GLOBALS['curlKodLastTime'] = 0;
	$GLOBALS['curlKodLast'] = $curl;
	Hook::trigger('curl.progressStart',$curl);
	think_status('curlTimeStart');

	// 内存缓存;
	// $curlInfo = curl_getinfo($curl);
	// if(isset($GLOBALS['curlCache'][$curlInfo['url']])){
	// 	write_log($curlInfo);
	// 	$curl = curl_copy_handle($GLOBALS['curlCache'][$curlInfo['url']]);
	// 	return $GLOBALS['curlCacheResult'][$curlInfo['url']];
	// }
}
function curl_progress_end($curl,&$curlResult=false){
	$GLOBALS['curlKodLastTime'] = 0;
	$GLOBALS['curlKodLast'] = false;
	Hook::trigger('curl.progressEnd',$curl);
	
	// 网络请求记录;
	$curlInfo = curl_getinfo($curl);
	think_status('curlTimeEnd');
	$runTime = '[ RunTime:'.think_status('curlTimeStart','curlTimeEnd',6).'s ]';
	$runInfo = "sizeUp={$curlInfo['size_upload']};sizeDown={$curlInfo['download_content_length']};";//json_encode($curlInfo)
	think_trace(" ".$curlInfo['url'].";".$runInfo.$runTime,'','CURL');
	
	$httpCode = $curlInfo['http_code'];
	$errorMessage = '';
	if($curlResult && $httpCode < 200 || $httpCode >= 300){
		$errorMessage = "curl error code=".$httpCode.'; '.curl_error($curl);		
		$GLOBALS['curl_request_error'] = array('message'=>$errorMessage,'url'=> $curlInfo['url'],'code'=>$httpCode);
		write_log("[CURL] code=".$httpCode.';'.$curlInfo['url'],'curl');
	}
	// write_log("[CURL] ".$curlInfo['url']."; code=$httpCode;".curl_error($curl).";".get_caller_msg(),'test');
	if(GLOBAL_DEBUG){
		$response = strlen($curlResult) > 1000 ? substr($curlResult,0,1000).'...':$curlResult;
		write_log("[CURL] code=".$httpCode.';'.$curlInfo['url'].";$errorMessage",'curl');
	}
}
function curl_progress(){
	$args = func_get_args();
	if (is_resource($args[0]) || (is_object($args[0]) && get_class($args[0])=== 'CurlHandle')  ) { 
		// php5.5+ 第一个为$curl; <5.5则只有4个参数; php8兼容
		array_shift($args);
	}
	$downloadSize 	= $args[0];
	$download 		= $args[1];
	$uploadSize 	= $args[2];
	$upload 		= $args[3];
	if(!$download && !$upload ) return;
	if(timeFloat() - $GLOBALS['curlKodLastTime'] < 0.1) return;
	
	$GLOBALS['curlKodLastTime'] = timeFloat();
	Hook::trigger('curl.progress',$GLOBALS['curlKodLast'],$downloadSize,$download,$uploadSize,$upload);
}


// https://segmentfault.com/a/1190000000725185
// http://blog.csdn.net/havedream_one/article/details/52585331 
// php7.1 curl上传中文路径文件失败问题?【暂时通过重命名方式解决】
function url_request($url,$method='GET',$data=false,$headers=false,$options=false,$json=false,$timeout=3600){
	if($url && substr($url,0,2) == '//'){$url = 'http:'.$url;}
	$header = url_header($url);// 跳转同时检测;
	if(!$url || !$header['url'] ){
		$theUrl = isset($header['urlBefore']) ? $header['urlBefore']:$url;
		return array('data'=> 'URL not allow! '.htmlentities($theUrl),'code'=> 0);
	}
	ignore_timeout();
	$ch = curl_init();
	$upload = false;
	if(is_array($data)){//上传检测并兼容
		foreach($data as $key => $value){
			if(!is_string($value) || substr($value,0,1) !== "@"){
				continue;
			}
			$upload = true;
			$path = ltrim($value,'@');
			$filename = iconv_app(get_path_this($path));
			$mime = get_file_mime(get_path_ext($filename));
			if(isset($data['curlUploadName'])){//自定义上传文件名;临时参数
				$filename = $data['curlUploadName'];
				unset($data['curlUploadName']);
			}
			if (class_exists('\CURLFile')){
				$data[$key] = new CURLFile(realpath($path),$mime,$filename);
			}else{
				$data[$key] = "@".realpath($path).";type=".$mime.";filename=".$filename;
			}
			//有update且method为PUT
			if($method == 'PUT'){
				$fp = @fopen($path,'r');
				$error = array('data'=>"path fopen error!",'status'=>false,'code'=>100,'header'=>array());
				if(!$fp){return $error;}
				curl_setopt($ch, CURLOPT_PUT,1);
				curl_setopt($ch, CURLOPT_INFILE,$fp);
				curl_setopt($ch, CURLOPT_INFILESIZE,@filesize($path));
				unset($data[$key]); // put通常通过body上传文件;不需要post参数,参数放在url中
			}
		}
	}
	if($upload){
		if(class_exists('\CURLFile')){
			curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
		}else if (defined('CURLOPT_SAFE_UPLOAD')) {
			curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
		}
	}

	// post数组或拼接的参数;不同方式服务器兼容性有所差异
	// http://blog.csdn.net/havedream_one/article/details/52585331 
	// post默认用array发送;content-type为x-www-form-urlencoded时用key=1&key=2的形式
	if (is_array($data) && is_array($headers) && $method != 'DOWNLOAD'){
		foreach ($headers as $key) {
			if(strstr($key,'x-www-form-urlencoded')){
				$data = http_build_query($data);
				break;
			}
		}
	}
	if($method == 'GET' && $data){
		$data = is_array($data) ? http_build_query($data) : '';
		if($data &&  strstr($url,'?')){$url = $url.'&'.$data;}
		if($data && !strstr($url,'?')){$url = $url.'?'.$data;}
	}
	curl_setopt($ch, CURLOPT_URL,$url);
	curl_setopt($ch, CURLOPT_HEADER,1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
	curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	// curl_setopt($ch, CURLOPT_SSLVERSION,1);//1|5|6; http://t.cn/RZy5nXF
	// curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
	curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
	curl_setopt($ch, CURLOPT_REFERER,get_url_root($url));
	curl_setopt($ch, CURLOPT_NOPROGRESS, false);
	curl_setopt($ch, CURLOPT_PROGRESSFUNCTION,'curl_progress');curl_progress_start($ch);
	curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36');
	
	if($options && isset($options['cookie'])){
		curl_setopt($ch, CURLOPT_COOKIE, $options['cookie']);
		unset($options['cookie']);
	}
	if($headers){
		if(is_string($headers)){
			$headers = array($headers);
		}
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
	}

	switch ($method) {
		case 'GET':
			curl_setopt($ch,CURLOPT_HTTPGET,1);
			break;
		case 'DOWNLOAD':
			//远程下载到指定文件;进度条
			$fp = fopen ($data,'w+');
			curl_setopt($ch, CURLOPT_HTTPGET,1);
			curl_setopt($ch, CURLOPT_HEADER,0);//不输出头
			curl_setopt($ch, CURLOPT_FILE, $fp);
			//CURLOPT_RETURNTRANSFER 必须放在CURLOPT_FILE前面;否则出问题
			break;
		case 'HEAD':
			curl_setopt($ch, CURLOPT_NOBODY, true);
			break;
		case 'POST':
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
			break;
		case 'OPTIONS':
		case 'PATCH':
		case 'DELETE':
		case 'PUT':
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST,$method);
			if($data){curl_setopt($ch, CURLOPT_POSTFIELDS,$data);}
			break;
		default:break;
	}

	if(is_array($options)){
		curl_setopt_array($ch, $options);
	}
	$response = curl_exec($ch);curl_progress_end($ch,$response);
	$header_size = curl_getinfo($ch,CURLINFO_HEADER_SIZE);
	$response_info = curl_getinfo($ch);
	$http_body   = substr($response, $header_size);
	$http_header = substr($response, 0, $header_size);
	$http_header = parse_headers($http_header);
	if(is_array($http_header)){
		$http_header['kod_add_request_url'] = $url;
	}
	//error
	if($response_info['http_code'] == 0){
		$error_message = curl_error($ch);
		$error_message = $error_message ? $error_message : 'Network error!';
		return array(
			'data'		=> "Request error:".get_url_root($url).";\n".$error_message,
			'status'	=> false,
			'code'		=> 0,
			'header'	=> $response_info,
		);
	}

	curl_close($ch);
	if(isset($GLOBALS['curlCurrentFile']) && is_array($GLOBALS['curlCurrentFile'])){
		Cache::remove($GLOBALS['curlCurrentFile']['cacheKey']);
	}
	$success = $response_info['http_code'] >= 200 && $response_info['http_code'] <= 299;
	if( $json && $success){
		$data = @json_decode($http_body,true);
		if (json_last_error() == 0) { // string
			$http_body = $data;
		}
	}
	$return = array(
		'data'		=> $http_body,
		'status'	=> $success,
		'code'		=> $response_info['http_code'],
		'header'	=> $http_header,
	);
	return $return;
}
function curl_get_contents($url,$timeout=60){
	$data = url_request($url,'GET',0,0,0,0,$timeout);
	if($data['code'] == 0) return false;
	return $data['data'];
}
function file_get_contents_nossl($url){
	$options = array('ssl'	=> array(
		'verify_peer'		=> false, 
		'verify_peer_name'	=> false
	));
	return file_get_contents($url, false, stream_context_create($options));
}

function url_request_proxy($url,$method='GET',$data=false,$headers=false,$options=false,$json=false,$timeout=3600){
	if(!is_array($headers)){$headers = array();}
	$config = $GLOBALS['config'];
	if($config['CURLOPT_PROXY']){
		if(!is_array($options)){$options = array();}
		foreach($config['CURLOPT_PROXY'] as $k=>$v){$options[$k] = $v;}
	}else if($config['HTTP_PROXY']){
		$add = strstr($config['HTTP_PROXY'],'?') ? '&':'?';
		$url = $config['HTTP_PROXY'] .$add.'_url='.base64_encode($url);
	};
	return url_request($url,$method,$data,$headers,$options,$json,$timeout);
}


// 多个url批量请求; ['url1','url2',...],  or [{url,method,data,header,options},...],  
function url_request_mutil($requests,$timeout=20){
	$mh = curl_multi_init();
	$handles = array();

	// 初始化每个请求
	foreach($requests as $index => $request){
		if(is_string($request)){$request = array('url' => $request,'method'=>'GET');}
		$ch 	= curl_init();
		$url 	= $request['url'];
		$data 	= is_array($request['data']) ? http_build_query($request['data']) : $request['data'].'';
		if(isset($request['method']) && strtoupper($request['method']) === 'POST') {
			curl_setopt($ch, CURLOPT_POST,1);
			if($data){curl_setopt($ch, CURLOPT_POSTFIELDS,$data);}
		}else{
			curl_setopt($ch,CURLOPT_HTTPGET,1);
			if($data &&  strstr($url,'?')){$url = $url.'&'.$data;}
			if($data && !strstr($url,'?')){$url = $url.'?'.$data;}
		}
		if(isset($request['headers'])){
			$headers = is_string($request['headers']) ? array($request['headers']) : $request['headers'];
			curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
		}
		if(is_array($request['options'])){
			if(isset($request['options']['cookie'])){
				curl_setopt($ch, CURLOPT_COOKIE, $request['options']['cookie']);
				unset($request['options']['cookie']);
			}
			curl_setopt_array($ch, $request['options']);
		}
		
		curl_setopt($ch, CURLOPT_URL,$url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
		curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
		curl_setopt($ch, CURLOPT_REFERER,get_url_link($url));
		curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36');
		curl_setopt($ch, CURLOPT_NOPROGRESS, false);
		curl_setopt($ch, CURLOPT_PROGRESSFUNCTION,'curl_progress');curl_progress_start($ch);
		curl_multi_add_handle($mh, $ch);
		$handles[$index] = $ch;
	}

	// 执行所有请求;循环调用-每次调用返回当前状态码;	
	$active = null;
	do{
		$mrc = curl_multi_exec($mh, $active);
	}while($mrc == CURLM_CALL_MULTI_PERFORM);
	while($active && $mrc == CURLM_OK){
		if(curl_multi_select($mh) == -1){continue;}
		do{
			$mrc = curl_multi_exec($mh, $active);
		}while($mrc == CURLM_CALL_MULTI_PERFORM);
	}

	// 获取结果
	$results = array();
	foreach($handles as $index => $ch){
		$info = curl_getinfo($ch);
		$body = curl_multi_getcontent($ch);
		$results[$index] = array(
			'data' 	=> $body,
			'info' 	=> $info,
			'status'=> $info['http_code'] >= 200 && $info['http_code'] <= 299,
			'code'	=> $info['http_code'],
		);
		curl_progress_end($ch,$body);
		curl_multi_remove_handle($mh, $ch);
		curl_close($ch);
	}	
	curl_multi_close($mh);
	return $results;
}

function get_headers_curl($url,$timeout=10,$depth=0,&$headers=array()){
	if($url && substr($url,0,2) == '//'){$url = 'http:'.$url;}
	if(!function_exists('curl_init')) return false;
	if(!$url || !request_url_safe($url)) return false;
	if($depth >= 10) return false;
	$ch = curl_init(); 
	curl_setopt($ch, CURLOPT_URL,$url);
	curl_setopt($ch, CURLOPT_HEADER,true); 
	curl_setopt($ch, CURLOPT_NOBODY,true); 
    curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
	curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
	curl_setopt($ch, CURLOPT_REFERER,get_url_link($url));
	curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36');
	
	// 通过GET获取header, 兼容oss等服务器不允许method=HEAD的情况;
	if($GLOBALS['curl_header_use_get']){
		curl_setopt($ch, CURLOPT_NOBODY,false);
		curl_setopt($ch, CURLOPT_HTTPGET,1);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Range: bytes=0-0"));
	}

	$res = curl_exec($ch);
	$res = explode("\r\n", $res);
	$response_info = curl_getinfo($ch);
	$headers['http_code'] = $response_info['http_code'];

	$location = false;
	foreach ($res as $line) {
		list($key, $val) = explode(": ", $line, 2);
		$the_key = trim($key);
		if($the_key == 'Location' || $the_key == 'location'){
			$the_key = 'Location';
			$location = trim($val);
		}
		if( strlen($the_key) == 0 &&
			strlen(trim($val)) == 0  ){
			continue;
		}
		if( substr($the_key,0,4) == 'HTTP' &&
			strlen(trim($val)) == 0  ){
			$headers[] = $the_key;
			continue;
		}

		if(!isset($headers[$the_key])){
			$headers[$the_key] = trim($val);
		}else{
			if(is_string($headers[$the_key])){
				$temp = $headers[$the_key];
				$headers[$the_key] = array($temp);
			}
			$headers[$the_key][] = trim($val);
		}
	}
	if($location !== false){
		$depth++;
		get_headers_curl($location,$timeout,$depth,$headers);
	}
	return count($headers)==0?false:$headers;
} 

/**
 * url安全监测; 防止SSRF 攻击;
 * 监测处: curl_exec,file_get_contents,fsockopen
 * 
 * https://websec.readthedocs.io/zh/latest/vuln/ssrf.html 
 * 仅保留http,https协议; 禁用内网及本机访问; 端口白名单; 
 * 301跳转注意处理; 
 */
function request_url_safe($url){
	$url   = str_replace('\\','/',$url);
	$allow = array('http','https','ftp');
	$info  = parse_url($url);$hasAllow = false;
	foreach($allow as $scheme){
		$schemeNow = substr($url,0,strlen($scheme) + 3);
		if($schemeNow === $scheme."://"){$hasAllow = true;}
	}
	if(strstr($url,'../')) return false;
	if(!$hasAllow) return false;
	if(!$info['scheme'] || !$info['host'] || !in_array($info['scheme'],$allow)) return false;
	if(@file_exists($url) ) return false;
	//if($info['host'] == 'localhost' || $info['host'] == '127.0.0.1' || strstr($info['host'],'192.168.')) return false;
	
	return true;
}

// url header data
function url_header($url){
	if(!request_url_safe($url)) return false;
	$header = get_headers_curl($url);//curl优先
	if(is_array($header) && $header['http_code'] == 302){$header = false;}
	if(is_array($header)){
		$header['ACTION_BY'] = 'get_headers_curl';
	}else{
		stream_context_set_default(array(
            'ssl' => array(
                'verify_host'       => false,
                'verify_peer'       => false,
                'verify_peer_name'  => false,
            ),
        ));
		$header = @get_headers($url,true);
		if($header){
			$header['http_code'] = intval(match_text($header[0],'HTTP\/1\.1\s+(\d+)\s+'));
		}
	}
	if (!$header) return false; 
	foreach ($header as $key => $value) {
		$header[strtolower($key)] = $value;
	}

	//加入小写header值;兼容各种不统一的情况
	$header['———'] = '————————————';//分隔
	foreach ($header as $key => $value) {
		$header[strtolower($key)] = $value;
	}
	$checkArr = array(
		'content-length'		=> 0, 
		'location'				=> $url,//301调整
		'content-disposition'	=> '',
		'content-range'			=> '',
	);
	//处理多次跳转的情况
	foreach ($checkArr as $key=>$val) {
		if(isset($header[$key])){
			$checkArr[$key] = $header[$key];
			if(is_array($header[$key])  && count($header[$key])>0){
				$checkArr[$key] = $header[$key][count($header[$key])-1];
			}
		}
	}
	
	$name 	= $checkArr['content-disposition'];
	$length = $checkArr['content-length'];
	$fileUrl= $checkArr['location'];
	if($fileUrl && substr($fileUrl,0,2) == '//'){$fileUrl = 'http:'.$fileUrl;}
	
	// 如果是断点请求, 内容长度从content-range取总长度;
	if($checkArr['content-range']){
		$rangeArr = explode('/',$checkArr['content-range']);
		if(count($rangeArr) == 2 && intval($rangeArr[1]) > intval($length)){
			$length = intval($rangeArr[1]);
		}
	}
	
	if($name){
		$disposition = $name;
		$name = '';
		$checkReg = array( //前后优先级依次降低;
			'/filename\s*\*\s*=.*\'\'(.*)/i',
			'/filename\s*=\s*"(.*)"/i',
			'/filename\s*=\s*(.*);/i'
		);
		foreach ($checkReg as $reg){
			preg_match($reg,$disposition,$match);
			if(!$name && is_array($match) && count($match) == 2 && $match[1]){
				$name = $match[1];
			}
		}
	}
	if(isset($header['x-outfilename']) && $header['x-outfilename']){
		$name = rawurldecode($header['x-outfilename']);
	}
	if(!$name){
		$name = get_path_this($fileUrl);
		if (strstr($name,'?')){
			$name = substr($name,0,strrpos($name,'?'));
		}
		if(!$name) $name = date("mdHi");
		if(!strstr($name,'.')){ //没有扩展名,自动追加;
			$contentType = $header['content-type']; // location ;跳转情况;
			if(is_array($contentType)){
				$contentType = $contentType[count($contentType)-1];
			}
			$ext  = get_file_ext_by_mime($contentType);
			$name .= '.'.$ext;
		}
	}

	$name = str_replace(array('/','\\'),'-',rawurldecode($name));//safe;
	$supportRange = isset($header["accept-ranges"])?true:false;
	$result = array(
		'url' 		=> request_url_safe($fileUrl) ? $fileUrl: '',
		'urlBefore' => $fileUrl,
		'length' 	=> $length,
		'name' 		=> trim($name,'"'),
		'supportRange' => $supportRange && ($length!=0),
		'code'		=> $header['http_code'],
		'status'	=> $header['http_code'] >= 200 && $header['http_code'] < 400,
		'all'		=> $header,
	);
	if(!function_exists('curl_init')){
		$result['supportRange'] = false;
	}
	//pr($url,$result);
	return $result;
}


// check url if can use
function check_url($url){
	stream_context_set_default(array(
		'ssl' => array(
			'verify_host'       => false,
			'verify_peer'       => false,
			'verify_peer_name'  => false,
		),
	));
	$array = @get_headers($url,true);
	if(!$array) return false;

	$error = array('/404/','/403/','/500/');
	foreach ($error as $value) {
		if (preg_match($value, $array[0])) {
			return false;
		}
	}
	return true;
} 

// refer URL
function refer_url(){
	return isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : '';
} 

function select_var($array){
	if (!is_array($array)) return -1;
	ksort($array);
	$chosen = -1;
	foreach ($array as $k => $v) {
		if (isset($v)) {
			$chosen = $v;
			break;
		} 
	} 
	return $chosen;
}

/**
 * 解析url获得url参数
 * @param $query
 * @return array array
 */
function parse_url_query($url){
	$arr = mb_parse_url($url);
	$queryParts = explode('&',$arr['query']);
	$params = array();
	foreach ($queryParts as $param) {
		$item = explode('=', $param);
		// $params[$item[0]] = $item[1];
		$key = $item[0]; unset($item[0]);
        $params[$key] = implode('=', $item);
	}
	return $params;
}

function mb_parse_url($url, $component = -1) {
	$encodedUrl = preg_replace_callback(
		'%[^:/?#&=\.]+%usD',
		function ($matches) {
			return urlencode($matches[0]);
		},
		$url
	);
	$components = parse_url($encodedUrl, $component);
	if (is_array($components)) {
		foreach ($components as &$part) {
			if (is_string($part)) {
				$part = urldecode($part);
			}
		};unset($part);
	} else if (is_string($components)) {
		$components = urldecode($components);
	}
	return $components;
}

function stripslashes_deep($value,$decode=true){
	return is_array($value) ?array_map('stripslashes_deep',$value) :stripslashes($value);
}

function parse_url_route(){
	$param = str_replace($_SERVER['SCRIPT_NAME'],"",$_SERVER['SCRIPT_NAME']);
	if($param && substr($param,0,1) == '/'){
		$arr = explode('&',$param);
		$arr[0] = ltrim($arr[0],'/');
		foreach ($arr as  $cell) {
			$cell = explode('=',$cell);
			if(is_array($cell)){
				if(!isset($cell[1])){
					$cell[1] = '';
				}
				$_GET[$cell[0]] = $cell[1];
				$_REQUEST[$cell[0]] = $cell[1];
			}
		}
	}
}


/**
 * GET/POST数据统一入口
 * 将GET和POST的数据进行过滤,去掉非法字符以及hacker code,返回一个数组
 * 注意如果GET和POST有相同的Key,POST优先
 * 
 * @return array $_GET和$_POST数据过滤处理后的值
 */
function parse_incoming(){
	parse_url_route();
	global $_GET, $_POST,$_COOKIE;
	if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) {
		$_COOKIE = stripslashes_deep($_COOKIE);
		$_GET	 = stripslashes_deep($_GET);
		$_POST	 = stripslashes_deep($_POST);
	}	
	$return = array();
	$return = array_merge($_GET,$_POST);
	foreach ($return as $itemKey => $itemValue) {
		if(is_array($itemValue)){
			unset($return[$itemKey]);
		}
	}
	$remote = array_get_index($return,0);
	
	//路由支持以参数形式传入;兼容没有value的GET参数key被忽略掉的情况;UC手机浏览器;
	if(isset($return['API_ROUTE'])){
		$remote = array($return['API_ROUTE'],'');
		unset($return['API_ROUTE']);
	}
	
	$router = isset($remote[0]) ? trim($remote[0],'/') : '';
	preg_match_all('/[0-9a-zA-Z\/_-]*/',$router,$arr);
    $router = join('',$arr[0]);
    $router = str_replace('/','.',$router);
	$remote = explode('.',$router);

	// 微信等追加到根地址后面参数情况处理;  domain.com/?a=1&b=2; 
	if( count($remote) == 1 && 
		$remote[0] == $router &&
		isset($return[$router]) &&
		$return[$router] !='' ){
		$router = '';
		$remote = array('');
	}
	
	$return['URLrouter'] = $router;
	$return['URLremote'] = $remote;
	// pr($_GET,$_POST,$_COOKIE,$return);exit;
	return $return;
} 

function db_escape($str) {
	$str = addslashes($str);
	$str = str_replace(array('_', '%'),array('\\_', '\\%'), $str);
	return $str;
}

/**
 * 获取输入参数 支持过滤和默认值
 * 使用方法:
 * <code>
 * in('id',0); 获取id参数 自动判断get或者post
 * in('post.name','','htmlspecialchars'); 获取$_POST['name']
 * in('get.'); 获取$_GET
 * </code> 
 * @param string $name 变量的名称 支持指定类型
 * @param mixed $default 不存在的时候默认值
 * @param mixed $filter 参数过滤方法
 * @return mixed
 */
function in($name,$default='',$filter=null) {
	$default_filter = 'htmlspecialchars,db_escape';
	if(strpos($name,'.')) { // 指定参数来源
		list($method,$name) = explode('.',$name,2);
	}else{ // 默认为自动判断
		$method = 'request';
	}
	switch(strtolower($method)) {
		case 'get'     :   $input =& $_GET;break;
		case 'post'    :   $input =& $_POST;break;
		case 'request' :   $input =& $_REQUEST;   break;

		case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;
		case 'session' :   $input =Session::get();   break;
		case 'cookie'  :   $input =& $_COOKIE;    break;
		case 'server'  :   $input =& $_SERVER;    break;
		case 'globals' :   $input =  $GLOBALS; break;
		default:return NULL;
	}
	$filters = isset($filter)?$filter:$default_filter;
	if($filters) {
		$filters = explode(',',$filters);
	}
	if(empty($name)) { // 获取全部变量
		$data = $input; 
		foreach($filters as $filter){
			$data = array_map($filter,$data); // 参数过滤
		}
	}elseif(isset($input[$name])) { // 取值操作
		$data =	$input[$name];
		foreach($filters as $filter){
			if(function_exists($filter)) {
				$data = is_array($data)?array_map($filter,$data):$filter($data); // 参数过滤
			}else{
				$data = filter_var($data,is_int($filter)?$filter:filter_id($filter));
				if(false === $data) {
					return isset($default)?$default:NULL;
				}
			}
		}
	}else{ // 变量默认值
		$data = isset($default)?$default:NULL;
	}
	return $data;
}


function url2absolute($index_url, $preg_url){
	if (preg_match('/[a-zA-Z]*\:\/\//', $preg_url)) return $preg_url;
	preg_match('/([a-zA-Z]*\:\/\/.*)\//', $index_url, $match);
	$index_url_temp = $match[1];

	foreach(explode('/', $preg_url) as $key => $var) {
		if ($key == 0 && $var == '') {
			preg_match('/([a-zA-Z]*\:\/\/[^\/]*)\//', $index_url, $match);
			$index_url_temp = $match[1] . $preg_url;
			break;
		} 
		if ($var == '..') {
			preg_match('/([a-zA-Z]*\:\/\/.*)\//', $index_url_temp, $match);
			$index_url_temp = $match[1];
		} elseif ($var != '.') $index_url_temp .= '/' . $var;
	} 
	return $index_url_temp;
}

// 输出js
function exec_js($js){
	echo "<script language='JavaScript'>\n" . $js . "</script>\n";
} 
// 禁止缓存
function no_cache(){
	header("Pragma:no-cache\r\n");
	header("Cache-Control:no-cache\r\n");
	header("Expires:0\r\n");
} 
// 生成javascript转向
function go_url($url, $msg = ''){
	header("Content-type: text/html; charset=utf-8\r\n");
	echo "<script type='text/javascript'>\n";
	echo "window.location.href='$url';";
	echo "</script>\n";
	exit;
} 

function send_http_status($i_status, $s_message = ''){
	$a_status = array(
		// Informational 1xx
		100 => 'Continue',
		101 => 'Switching Protocols', 
		// Success 2xx
		200 => 'OK',
		201 => 'Created',
		202 => 'Accepted',
		203 => 'Non-Authoritative Information',
		204 => 'No Content',
		205 => 'Reset Content',
		206 => 'Partial Content', 
		// Redirection 3xx
		300 => 'Multiple Choices',
		301 => 'Moved Permanently',
		302 => 'Found', // 1.1
		303 => 'See Other',
		304 => 'Not Modified',
		305 => 'Use Proxy', // 306 is deprecated but reserved
		307 => 'Temporary Redirect', 
		// Client Error 4xx
		400 => 'Bad Request',
		401 => 'Unauthorized',
		402 => 'Payment Required',
		403 => 'Forbidden',
		404 => 'Not Found',
		405 => 'Method Not Allowed',
		406 => 'Not Acceptable',
		407 => 'Proxy Authentication Required',
		408 => 'Request Timeout',
		409 => 'Conflict',
		410 => 'Gone',
		411 => 'Length Required',
		412 => 'Precondition Failed',
		413 => 'Request Entity Too Large',
		414 => 'Request-URI Too Long',
		415 => 'Unsupported Media Type',
		416 => 'Requested Range Not Satisfiable',
		417 => 'Expectation Failed', 
		// Server Error 5xx
		500 => 'Internal Server Error',
		501 => 'Not Implemented',
		502 => 'Bad Gateway',
		503 => 'Service Unavailable',
		504 => 'Gateway Timeout',
		505 => 'HTTP Version Not Supported',
		509 => 'Bandwidth Limit Exceeded'
		);

	if (array_key_exists($i_status, $a_status)) {
		header('HTTP/1.1 ' . $i_status . ' ' . $a_status[$i_status]);
	} 
	if ($s_message) {
		echo $s_message;
		exit();
	} 
} 

//是否是windows
function client_is_windows(){
	static $is_windows;
	if(!is_array($is_windows)){
		$is_windows = array(0);
		$os = get_os();
		if(strstr($os,'Windows')){
			$is_windows = array(1);
		}	
	}	
	return $is_windows[0];
}

function is_ajax(){
	if(isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"])=="xmlhttprequest"){
		return true;
	}
	return false;
}

// 获取操作系统信息 TODO
function get_os (){
	$agent = $_SERVER['HTTP_USER_AGENT'];
	$preg_find = array(
		"Windows 95"	=>array('win','95'),
		"Windows ME"	=>array('win 9x','4.90'),
		"Windows 98"	=>array('win','98'),
		"Windows 2000"	=>array('win','nt 5.0',),
		"Windows XP"	=>array('win','nt 5.1'),
		"Windows Vista"	=>array('win','nt 6.0'),
		"Windows 7"		=>array('win','nt 6.1'),
		"Windows 32"	=>array('win','32'),
		"Windows NT"	=>array('win','nt'),
		"Mac OS"		=>array('Mac OS'),
		"Linux"			=>array('linux'),
		"Unix"			=>array('unix'),
		"SunOS"			=>array('sun','os'),
		"IBM OS/2"		=>array('ibm','os'),
		"Macintosh"		=>array('Mac','PC'),
		"PowerPC"		=>array('PowerPC'),
		"AIX"			=>array('AIX'),
		"HPUX"			=>array('HPUX'),
		"NetBSD"		=>array('NetBSD'),
		"BSD"			=>array('BSD'),
		"OSF1"			=>array('OSF1'),
		"IRIX"			=>array('IRIX'),
		"FreeBSD"		=>array('FreeBSD'),
	);

	$os='';
	foreach ($preg_find as $key => $value) {
		if(count($value)==1 && stripos($agent,$value[0])){
			$os=$key;break;
		}else if(count($value)==2 
				 && stripos($agent,$value[0])
				 && stripos($agent,$value[1])
				 ){
			$os=$key;break;
		}
	}
	if ($os=='') {$os = "Unknown"; }
	return $os;
}

function get_broswer(){
    $agent = $_SERVER['HTTP_USER_AGENT']; //获取用户代理字符串
    $pregFind = array(
        "Firefox" => array("/Firefox\/([^;)]+)+/i"),
        "Maxthon" => array("/Maxthon\/([\d\.]+)/", "傲游"),
        "MSIE" => array("/MSIE\s+([^;)]+)+/i", "IE"),
        "OPR" => array("/OPR\/([\d\.]+)/", "Opera"),
        "Edge" => array("/Edge\/([\d\.]+)/"),
        "Chrome" => array("/Chrome\/([\d\.]+)/"),
        "rv:" => array("/rv:([\d\.]+)/", "IE", 'Gecko'),
    );
    $broswer = '';
    foreach ($pregFind as $key => $value) {
        if (stripos($agent, $key)) {
            if (count($value) == 3) {
                if (!stripos($agent, $value[2])) {
                    break;
                }
            }
            $name = count($value) == 1 ? $key : $value[1];
            preg_match($value[0], $agent, $match);
			$broswer = $name . '(' . $match[1] . ')';
			return $broswer;
        }
    }
    if ($broswer == '') {$broswer = "Unknown";}
    return $broswer;
}

// 浏览器是否直接打开
function mime_support($mime){
	$arr_start = array(
		"text/",
		"image/",
		"audio/",
		"video/",
		"message/",
	);
	$arr_mime = array(
		"application/hta",
		"application/javascript",
		"application/json",
		"application/x-latex",
		"application/pdf",
		"application/x-shockwave-flash",
		"application/x-tex",
		"application/x-texinfo"
	);
	if(in_array($mime,$arr_mime)){
		return true;
	}
	foreach ($arr_start as $val) {
		if(substr($mime,0,strlen($val)) == $val){
			return true;
		}
	}
	return false;
}
function get_file_ext_by_mime($contentType){
	$mimetypes = mime_array();
	$contentType = trim(strtolower($contentType));
	foreach ($mimetypes as $ext => $out){
		if($contentType == $out){
			return $ext;
		}
	}
	return 'txt';
}

//根据扩展名获取mime
function get_file_mime($ext){
	$mimetypes = mime_array();
	if (array_key_exists($ext,$mimetypes)){
		$result = $mimetypes[$ext];
		if($result == 'text/html'){
			// $result = "text/plain"; //禁用html网页输出;
		}
		return $result;
	}else{
		if(is_text_file($ext)){
			return "text/plain";
		}
		return 'application/octet-stream';
	}
}

function mime_array(){
	return array(
		"323" => "text/h323",
		"3gp" => "video/3gpp",
		"acx" => "application/internet-property-stream",
		"ai"  => "application/postscript",
		"aif" => "audio/x-aiff",
		"aifc" => "audio/x-aiff",
		"aiff" => "audio/x-aiff",
		"asf" => "video/x-ms-asf",
		"asr" => "video/x-ms-asf",
		"asx" => "video/x-ms-asf",
		"au" => "audio/basic",
		"avi" => "video/x-msvideo",
		"axs" => "application/olescript",
		"bas" => "text/plain",
		"bcpio" => "application/x-bcpio",
		"bin" => "application/octet-stream",
		"bmp" => "image/bmp",
		"c" => "text/plain",
		"cat" => "application/vnd.ms-pkiseccat",
		"cdf" => "application/x-cdf",
		"cer" => "application/x-x509-ca-cert",
		"class" => "application/octet-stream",
		"clp" => "application/x-msclip",
		"cmx" => "image/x-cmx",
		"cod" => "image/cis-cod",
		"cpio" => "application/x-cpio",
		"crd" => "application/x-mscardfile",
		"crl" => "application/pkix-crl",
		"crt" => "application/x-x509-ca-cert",
		"csh" => "application/x-csh",
		"css" => "text/css",
		"dcr" => "application/x-director",
		"der" => "application/x-x509-ca-cert",
		"dir" => "application/x-director",
		"dll" => "application/x-msdownload",
		"dms" => "application/octet-stream",
		"doc" => "application/msword",
		"docx" => "application/msword",
		"dot" => "application/msword",
		"dvi" => "application/x-dvi",
		"dxr" => "application/x-director",
		"eps" => "application/postscript",
		"etx" => "text/x-setext",
		"evy" => "application/envoy",
		"exe" => "application/octet-stream",
		"fif" => "application/fractals",
		"flr" => "x-world/x-vrml",
		"flv" => "video/x-flv",
		"f4v" => "video/x-flv",
		// "f4v" => "application/octet-stream",
		"gif" => "image/gif",
		"gtar" => "application/x-gtar",
		"gz" => "application/x-gzip",
		"h" => "text/plain",
		"hdf" => "application/x-hdf",
		"hlp" => "application/winhlp",
		"hqx" => "application/mac-binhex40",
		"hta" => "application/hta",
		"htc" => "text/x-component",
		"htm" => "text/html",
		"html" => "text/html",
		"htt" => "text/webviewhtml",
		"ico" => "image/x-icon",
		"ief" => "image/ief",
		"iii" => "application/x-iphone",
		"ins" => "application/x-internet-signup",
		"isp" => "application/x-internet-signup",
		"jfif" => "image/pipeg",
		"jpg" => "image/jpeg",
		"jpeg" => "image/jpeg",
		"jpe"  => "image/jpeg",
		"heic" => "image/heic",
		"webp" => "image/webp",
		"cur"  => "image/x-icon",
		"apng" => "image/apng",
		"avif" => "image/avif",
		"js" => "application/javascript",
		"json" => "application/json",
		"latex" => "application/x-latex",
		"lha" => "application/octet-stream",
		"lsf" => "video/x-la-asf",
		"lsx" => "video/x-la-asf",
		"lzh" => "application/octet-stream",
		"m13" => "application/x-msmediaview",
		"m14" => "application/x-msmediaview",
		"m3u" => "audio/x-mpegurl",
		'm4a' => "audio/mp4",
		'm4v' => "audio/mp4",
		"man" => "application/x-troff-man",
		"mdb" => "application/x-msaccess",
		"me" => "application/x-troff-me",
		"mht" => "message/rfc822",
		"mhtml" => "message/rfc822",
		"mid" => "audio/mid",
		"mka" => "audio/x-matroska",
		"mkv" => "video/x-matroska",
		"mny" => "application/x-msmoney",
		"mov" => "video/quicktime",
		"movie" => "video/x-sgi-movie",
		"mp2" => "video/mpeg",
		"mp3" => "audio/mpeg",
		"mp4" => "video/mp4",
		"mp4v" => "video/x-m4v",
		"mpa" => "video/mpeg",
		"mpe" => "video/mpeg",
		"mpeg" => "video/mpeg",
		"mpg" => "video/mpeg",
		"mpp" => "application/vnd.ms-project",
		"mpv2" => "video/mpeg",
		"ms" => "application/x-troff-ms",
		"mvb" => "application/x-msmediaview",
		"nws" => "message/rfc822",
		"oda" => "application/oda",
		"ogg" => "audio/ogg",
		"oga" => "audio/ogg",
		"ogv" => "audio/ogg",
		"p10" => "application/pkcs10",
		"p12" => "application/x-pkcs12",
		"p7b" => "application/x-pkcs7-certificates",
		"p7c" => "application/x-pkcs7-mime",
		"p7m" => "application/x-pkcs7-mime",
		"p7r" => "application/x-pkcs7-certreqresp",
		"p7s" => "application/x-pkcs7-signature",
		"pbm" => "image/x-portable-bitmap",
		"pdf" => "application/pdf",
		"pfx" => "application/x-pkcs12",
		"pgm" => "image/x-portable-graymap",
		"pko" => "application/ynd.ms-pkipko",
		"pma" => "application/x-perfmon",
		"pmc" => "application/x-perfmon",
		"pml" => "application/x-perfmon",
		"pmr" => "application/x-perfmon",
		"pmw" => "application/x-perfmon",
		"png" => "image/png",
		"pnm" => "image/x-portable-anymap",
		"pot," => "application/vnd.ms-powerpoint",
		"ppm" => "image/x-portable-pixmap",
		"pps" => "application/vnd.ms-powerpoint",
		"ppt" => "application/vnd.ms-powerpoint",
		"pptx" => "application/vnd.ms-powerpoint",
		"plist"=> "text/xml",
		"ipa" =>"application/octet-stream",
		"prf" => "application/pics-rules",
		"ps" => "application/postscript",
		"pub" => "application/x-mspublisher",
		"qt" => "video/quicktime",
		"ra" => "audio/x-pn-realaudio",
		"ram" => "audio/x-pn-realaudio",
		"ras" => "image/x-cmu-raster",
		"rgb" => "image/x-rgb",
		"rmi" => "audio/mid",
		"roff" => "application/x-troff",
		"rtf" => "application/rtf",
		"rtx" => "text/richtext",
		"scd" => "application/x-msschedule",
		"sct" => "text/scriptlet",
		"setpay" => "application/set-payment-initiation",
		"setreg" => "application/set-registration-initiation",
		"sh" => "application/x-sh",
		"shar" => "application/x-shar",
		"sit" => "application/x-stuffit",
		"snd" => "audio/basic",
		"spc" => "application/x-pkcs7-certificates",
		"spl" => "application/futuresplash",
		"src" => "application/x-wais-source",
		"sst" => "application/vnd.ms-pkicertstore",
		"stl" => "application/vnd.ms-pkistl",
		"stm" => "text/html",
		"svg" => "image/svg+xml",
		"sv4cpio" => "application/x-sv4cpio",
		"sv4crc" => "application/x-sv4crc",
		"swf" => "application/x-shockwave-flash",
		"t" => "application/x-troff",
		"tar" => "application/x-tar",
		"tcl" => "application/x-tcl",
		"tex" => "application/x-tex",
		"texi" => "application/x-texinfo",
		"texinfo" => "application/x-texinfo",
		"tgz" => "application/x-compressed",
		"tif" => "image/tiff",
		"tiff" => "image/tiff",
		"tr" => "application/x-troff",
		"trm" => "application/x-msterminal",
		"tsv" => "text/tab-separated-values",
		"txt" => "text/plain",
		"uls" => "text/iuls",
		"ustar" => "application/x-ustar",
		"vcf" => "text/x-vcard",
		"vrml" => "x-world/x-vrml",
		"wav" => "audio/wav",
		"wcm" => "application/vnd.ms-works",
		"wdb" => "application/vnd.ms-works",
		"webm" => "video/webm",
		"webmv" => "video/webm",
		"wks" => "application/vnd.ms-works",
		"wmf" => "application/x-msmetafile",
		"wps" => "application/vnd.ms-works",
		"wri" => "application/x-mswrite",
		"wrl" => "x-world/x-vrml",
		"wrz" => "x-world/x-vrml",
		"xaf" => "x-world/x-vrml",
		"xbm" => "image/x-xbitmap",
		"xla" => "application/vnd.ms-excel",
		"xlc" => "application/vnd.ms-excel",
		"xlm" => "application/vnd.ms-excel",
		"xls" => "application/vnd.ms-excel",
		"xlsx" => "application/vnd.ms-excel",
		"xlt" => "application/vnd.ms-excel",
		"xlw" => "application/vnd.ms-excel",
		"xof" => "x-world/x-vrml",
		"xpm" => "image/x-xpixmap",
		"xwd" => "image/x-xwindowdump",
		"z" => "application/x-compress",
		"zip" => "application/zip"
	);
}