<?php
// 统计程序运行时间
function runtime() {
	return number_format(microtime(1) - $_ENV['_start_time'], 4);
}
// 统计程序内存开销
function runmem() {
	return MEMORY_LIMIT_ON ? get_byte(memory_get_usage() - $_ENV['_start_memory']) : 'unknown';
}
function ip() {
	if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
		preg_match('#[\d\.]{7,15}#', $_SERVER['HTTP_X_FORWARDED_FOR'], $mat);
		$ip = $mat[0];
	}elseif(isset($_SERVER['HTTP_CLIENT_IP'])) {
		$ip = $_SERVER['HTTP_CLIENT_IP'];
	}elseif(isset($_SERVER['REMOTE_ADDR'])) {
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	return long2ip(ip2long($ip));
}
function E($err, $msg, $name = '') {
	exit('{"err":'.$err.', "msg":"'.$msg.'", "name":"'.$name.'"}');
}
function ME($err, $msg) {
	exit(json_encode(array('err'=>$err,'msg'=>$msg)));
}
function R($k, $var = 'G') {
	switch($var) {
		case 'G': $var = &$_GET; break;
		case 'P': $var = &$_POST; break;
		case 'C': $var = &$_COOKIE; break;
		case 'R': $var = isset($_GET[$k]) ? $_GET : (isset($_POST[$k]) ? $_POST : $_COOKIE); break;
		case 'S': $var = &$_SERVER; break;
	}
	return isset($var[$k]) ? $var[$k] : null;
}
function C($key, $val = null) {
	if(is_null($val)) return isset($_ENV['_config'][$key]) ? $_ENV['_config'][$key] : $val;
	return $_ENV['_config'][$key] = $val;
}
function FW($filename, $data) {
	$dir = dirname($filename);
	is_dir($dir) || mkdir($dir, 0755, true);
	return file_put_contents($filename, $data);	// 不使用 LOCK_EX，多线程访问时会有同步问题
}
function _setcookie($name, $value='', $expire=0, $path='', $domain='', $secure=false, $httponly=false) {
	$name = $_ENV['_config']['cookie_pre'].$name;
	if(!$path) $path = $_ENV['_config']['cookie_path'];
	if(!$domain) $domain = $_ENV['_config']['cookie_domain'];
	$_COOKIE[$name] = $value;
	return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
}
function _addslashes(&$var) {
	if(is_array($var)) {
		foreach($var as $k=>&$v) _addslashes($v);
	}else{
		$var = addslashes($var);
	}
}
function _stripslashes(&$var) {
	if(is_array($var)) {
		foreach($var as $k=>&$v) _stripslashes($v);
	}else{
		$var = stripslashes($var);
	}
}
function _htmls(&$var) {
	if(is_array($var)) {
		foreach($var as $k=>&$v) _htmls($v);
	}else{
		$var = htmlspecialchars($var);
	}
}
function _trim(&$var) {
	if(is_array($var)) {
		foreach($var as $k=>&$v) _trim($v);
	}else{
		$var = trim($var);
	}
}
function _urlencode($s) {
	return str_replace('-', '%2D', urlencode($s));
}
function _json_decode($s) {
	return $s === FALSE ? FALSE : json_decode($s, true);
}
function _json_encode($arr) {
	if(!is_array($arr) && empty($arr)) return '';
	$s = '{';
	foreach($arr as $k=>$v) {
		$s .= '"'.$k.'":"'.strtr($v, array('\\'=>'\\\\', '"'=>'\"')).'",';
	}
	return rtrim($s, ',').'}';
}
function _array_multisort(&$data, $c_1, $c_2 = true, $a_1 = 1, $a_2 = 1) {
	if(!is_array($data)) return $data;

	$col_1 = $col_2 = array();
	foreach($data as $key => $row) {
		$col_1[$key] = $row[$c_1];
		$col_2[$key] = $c_2===true ? $key : $row[$c_2];
	}

	$asc_1 = $a_1 ? SORT_DESC : SORT_ASC;
	$asc_2 = $a_2 ? SORT_DESC : SORT_ASC;
	array_multisort($col_1, $asc_1, $col_2, $asc_2, $data);

	return $data;
}
function _int(&$c, $k, $v = 0) {
	if(isset($c[$k])) {
		$i = intval($c[$k]);
		return $i ? $i : $v;
	}else{
		return $v;
	}
}
function _scandir($dir) {
	if(function_exists('scandir')) return scandir($dir);	// 有些服务器禁用了scandir
	$dh = opendir($dir);
	$arr = array();
	while($file = readdir($dh)) {
		if($file == '.' || $file == '..') continue;
		$arr[] = $file;
	}
	closedir($dh);
	return $arr;
}
function _rmdir($dir, $keepdir = 0) {
	if(!is_dir($dir) || $dir == '/' || $dir == '../') return FALSE;
	$files = _scandir($dir);
	foreach($files as $file) {
		if($file == '.' || $file == '..') continue;
		$filepath = $dir.'/'.$file;
		if(!is_dir($filepath)) {
			try{unlink($filepath);}catch(Exception $e){}
		}else{
			_rmdir($filepath);
		}
	}
	if(!$keepdir) try{rmdir($dir);}catch(Exception $e){}
	return TRUE;
}
function _is_writable($file) {
	try{
		if(is_dir($file)) {
			$tmpfile = $file.'/_test.tmp';
			$n = @file_put_contents($tmpfile, 'test');
			if($n > 0) {
				unlink($tmpfile);
				return TRUE;
			}else{
				return FALSE;
			}
		}elseif(is_file($file)) {
			if(strpos(strtoupper(PHP_OS), 'WIN') !== FALSE) {
				$fp = @fopen($file, 'a'); 
				@fclose($fp);
				return (bool)$fp;
			}else{
				return is_writable($file);
			}
		}
	}catch(Exception $e) {}
	return FALSE;
}
function _strip_whitespace($content) {
	$tokens = token_get_all($content);
	$last = FALSE;
	$s = '';
	for($i = 0, $j = count($tokens); $i < $j; $i++) {
		if(is_string($tokens[$i])) {
			$last = FALSE;
			$s .= $tokens[$i];
		}else{
			switch($tokens[$i][0]) {
				case T_COMMENT:
				case T_DOC_COMMENT:
					break;
				case T_WHITESPACE:
					if(!$last) {
						$s .= ' ';
						$last = TRUE;
					}
					break;
				case T_START_HEREDOC:
					$s .= "<<<FINE\n";
					break;
				case T_END_HEREDOC:
					$s .= "FINE;\n";
					for($k = $i+1; $k < $j; $k++) {
						if(is_string($tokens[$k]) && $tokens[$k] == ';') {
							$i = $k;
							break;
						}elseif($tokens[$k][0] == T_CLOSE_TAG) {
							break;
						}
					}
					break;
				default:
					$last = FALSE;
					$s .= $tokens[$i][1];
			}
		}
	}
	return $s;
}
function random($length, $type = 1, $chars = '0123456789abcdefghijklmnopqrstuvwxyz') {
	if($type == 1) {
		$hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1));
	} else {
		$hash = '';
		if($type == 3) $chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$max = strlen($chars) - 1;
		for($i = 0; $i < $length; $i++) $hash .= $chars[mt_rand(0, $max)];
	}
	return $hash;
}
function get_byte($byte) {
	if($byte < 1024) {
		return $byte.' Byte';
	}elseif($byte < 1048576) {
		return round($byte/1024, 2).' KB';
	}elseif($byte < 1073741824) {
		return round($byte/1048576, 2).' MB';
	}elseif($byte < 1099511627776) {
		return round($byte/1073741824, 2).' GB';
	}else{
		return round($byte/1099511627776, 2).' TB';
	}
}
function human_date($dateline, $dateformat = 'Y-m-d H:i:s') {
	$second = $_ENV['_time'] - $dateline;
	if($second > 31536000) {
		return date($dateformat, $dateline);
	}elseif($second > 2592000) {
		return floor($second / 2592000).'月前';
	}elseif($second > 86400) {
		return floor($second / 86400).'天前';
	}elseif($second > 3600) {
		return floor($second / 3600).'小时前';
	}elseif($second > 60) {
		return floor($second / 60).'分钟前';
	}else{
		return $second.'秒前';
	}
}
function safe_str($s, $ext = '') {
	$ext = preg_quote($ext);
	$s = preg_replace('#[^\040\w\x{4E00}-\x{9FA5}\x{30A0}-\x{30FF}\x{3040}-\x{309F}\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}'.$ext.']+#u', '', $s);
	$s = trim($s);
	return $s;
}
function get_dirs($path, $fullpath = false) {
	$arr = array();
	$dh = opendir($path);
	while($dir = readdir($dh)) {
		if(preg_match('#\W#', $dir) || !is_dir($path.$dir)) continue;
		$arr[] = $fullpath ? $path.$dir.'/' : $dir;
	}
	sort($arr);
	return $arr;
}
function str_replace_once($search, $replace, $content) {
	$pos = strpos($content, $search);
	if($pos === false) return $content;
	return substr_replace($content, $replace, $pos, strlen($search));
}
function str_auth($string, $operation = 'DECODE', $key = '', $expiry = 0) {
	$ckey_length = 4;
	$key = md5($key != '' ? $key : C('auth_key'));
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);

	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);

	$result = '';
	$box = range(0, 255);

	$rndkey = array();
	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}

	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}

	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}

	if($operation == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		}else{
			return '';
		}
	}else{
		return $keyc.str_replace('=', '', base64_encode($result));
	}
}
function form_hash() {
	return substr(md5(substr($_ENV['_time'], 0, -5).$_ENV['_config']['auth_key']), 16);
}
function form_submit() {
	return R('FORM_HASH', 'P') == form_hash();
}
function fetch_url($url, $timeout = 30) {
	$opts = array ('http'=>array('method'=>'GET', 'timeout'=>$timeout));
	$context = stream_context_create($opts);
	$html = file_get_contents($url, false, $context);
	return $html;
}
function pp_pages($page, $maxpage, $url, $offset = 5, $lang = array('&#171;', '&#187;')) {
	if($maxpage < 2) return '';
	$pnum = $offset*2;
	$ismore = $maxpage > $pnum;
	$s = '';
	$ua = explode('{page}', $url);
	if($page > 1) $s .= '<li><a href="'.$ua[0].($page-1).$ua[1].'">'.$lang[0].'</a></li>';
	if($ismore) {
		$i_end = min($maxpage, max($pnum, $page+$offset)) - 1;
		$i = max(2, $i_end-$pnum+2);
	}else{
		$i_end = min($maxpage, $pnum)-1;
		$i = 2;
	}
	$s .= $page == 1 ? '<li class="active"><a href="javascript:;">1</a></li>' : '<li><a href="'.$ua[0].'1'.$ua[1].'">1'.($ismore && $i > 2 ? ' ...' : '').'</a></li>';
	for($i; $i<=$i_end; $i++){
		$s .= $page == $i ? '<li class="active"><a href="javascript:;">'.$i.'</a></li>' : '<li><a href="'.$ua[0].$i.$ua[1].'">'.$i.'</a></li>';
	}
	$s .= $page == $maxpage ? '<li class="active"><a href="javascript:;">'.$maxpage.'</a></li>' : '<li><a href="'.$ua[0].$maxpage.$ua[1].'">'.($ismore && $i_end < $maxpage-1 ? '... ' : '').$maxpage.'</a></li>';
	if($page < $maxpage) $s .= '<li><a href="'.$ua[0].($page+1).$ua[1].'">'.$lang[1].'</a></li>';
	return $s;
}
function user_pages($page, $maxpage, $url, $offset = 5, $lang = array('&#171;', '&#187;')) {
	if($maxpage < 2) return '';
	$pnum = $offset*2;
	$ismore = $maxpage > $pnum;
	$s = '';
	$ua = explode('{page}', $url);
	if($page > 1) $s .= '<li><a href="'.$ua[0].($page-1).$ua[1].'">'.$lang[0].'</a></li>';
	if($ismore) {
		$i_end = min($maxpage, max($pnum, $page+$offset)) - 1;
		$i = max(2, $i_end-$pnum+2);
	}else{
		$i_end = min($maxpage, $pnum)-1;
		$i = 2;
	}
	$s .= $page == 1 ? '<li class="active"><a href="javascript:;">1</a></li>' : '<li><a href="'.$ua[0].'1'.$ua[1].'">1'.($ismore && $i > 2 ? ' ...' : '').'</a></li>';
	for($i; $i<=$i_end; $i++){
		$s .= $page == $i ? '<li class="active"><a href="javascript:;">'.$i.'</a></li>' : '<li><a href="'.$ua[0].$i.$ua[1].'">'.$i.'</a></li>';
	}
	$s .= $page == $maxpage ? '<li class="active"><a href="javascript:;">'.$maxpage.'</a></li>' : '<li><a href="'.$ua[0].$maxpage.$ua[1].'">'.($ismore && $i_end < $maxpage-1 ? '... ' : '').$maxpage.'</a></li>';
	if($page < $maxpage) $s .= '<li><a href="'.$ua[0].($page+1).$ua[1].'">'.$lang[1].'</a></li>';
	return $s;
}
function pages($page, $maxpage, $url, $offset = 5, $lang = array('&#171;', '&#187;')) {
	if($maxpage < 2) return '';
	$pnum = $offset*2;
	$ismore = $maxpage > $pnum;
	$s = '';
	$ua = explode('{page}', $url);
	if($page > 1) $s .= '<a href="'.$ua[0].($page-1).$ua[1].'">'.$lang[0].'</a>';
	if($ismore) {
		$i_end = min($maxpage, max($pnum, $page+$offset)) - 1;
		$i = max(2, $i_end-$pnum+2);
	}else{
		$i_end = min($maxpage, $pnum)-1;
		$i = 2;
	}
	$s .= $page == 1 ? '<b>1</b>' : '<a href="'.$ua[0].'1'.$ua[1].'">1'.($ismore && $i > 2 ? ' ...' : '').'</a>';
	for($i; $i<=$i_end; $i++){
		$s .= $page == $i ? '<b>'.$i.'</b>' : '<a href="'.$ua[0].$i.$ua[1].'">'.$i.'</a>';
	}
	$s .= $page == $maxpage ? '<b>'.$maxpage.'</b>' : '<a href="'.$ua[0].$maxpage.$ua[1].'">'.($ismore && $i_end < $maxpage-1 ? '... ' : '').$maxpage.'</a>';
	if($page < $maxpage) $s .= '<a href="'.$ua[0].($page+1).$ua[1].'">'.$lang[1].'</a>';
	return $s;
}
// 密码生成规则
function get_password($password='',$salt=''){
	return md5(md5($password).$salt);
}
// 判断是否为手机访问
function is_mobile() {
	$is_mobile = R($_ENV['_config']['cookie_pre'].'is_mobile', 'R');
	if(isset($is_mobile)) return $is_mobile ? 1 : 0;

	$mobile_agents = array(
		'iphone','ipod','android','samsung','sony','meizu','ericsson','mot','htc','sgh','lg','sharp','sie-',
		'philips','panasonic','alcatel','lenovo','blackberry','netfront','symbian','ucweb','windowsce',
		'palm','operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile'
	);

	$is_mobile = 0;
	$browser = $_SERVER['HTTP_USER_AGENT'];
	foreach($mobile_agents as $agent) {
		if(stripos($browser, $agent) !== 0) {
			$is_mobile = 1;
			break;
		}
	}
	_setcookie('is_mobile', $is_mobile);
	return $is_mobile;
}
//生成订单号
function order_number(){
    static $ORDERSN=array();                                        //静态变量
    $ors=date('ymd').substr(time(),-5).substr(microtime(),2,5);     //生成16位数字基本号
    if (isset($ORDERSN[$ors])) {                                    //判断是否有基本订单号
        $ORDERSN[$ors]++;                                           //如果存在,将值自增1
    }else{
        $ORDERSN[$ors]=1;
    }
    return $ors.str_pad($ORDERSN[$ors],2,'0',STR_PAD_LEFT);     //链接字符串
}
//人性化时间
function humandate($timestamp,$dateformat) {
	$time = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
	$seconds = $time - $timestamp;
	if($seconds > 7776000) {
		return date($dateformat, $timestamp);
	} elseif($seconds > 2592000) {
		return floor($seconds / 2592000).'月前';
	} elseif($seconds > 86400) {
		return floor($seconds / 86400).'天前';
	} elseif($seconds > 3600) {
		return floor($seconds / 3600).'小时前';
	} elseif($seconds > 60) {
		return floor($seconds / 60).'分钟前';
	} else {
		return $seconds.'秒前';
	}
}
function t2js($str){
    $tmp = str_replace(array("\r", "\n"), array('', '\n'), addslashes($str));
    return "document.write(\"$tmp\");";
}