<?php
 /**
 * Magic CMS 函数库
 * ============================================================================
 * Copyright 2014 大秦科技，并保留所有权利。
 * 网站地址: http://www.qintech.net；
 * ----------------------------------------------------------------------------
 * 未获商业授权之前，不得将Magic CMS用于商业用途（包括但不限于企业网站、经营性网站
 * 以营利为目的或实现盈利的网站）未经官方许可，禁止在Magic CMS的整体或任何部分基础
 * 上以发展任何派生版本、修改版本或第三方版本用于重新分发。如果您未能遵守本协议的
 * 条款，您的授权将被终止，所被许可的权利将被收回，并承担相应法律责任。
 * ============================================================================
 * Date:2014/12/31
**/

if (!defined('KERNEL_PATH'))exit('No direct script access allowed');

/**
 * 加载核心模型
 * @param String $table 表名
 * @param Boolean $full 是否为全表名
 * @return Object 返回模型对象
 */
function M($table = null, $full = null, $param = array(), $driver = null){
	return new Model($table, $full, $param, $driver);
}

/**
 * 获得扩展模型
 * @param $name  模型名不加Model后缀
 * @param bool $full 是否为全表名
 * @param array $param 参数
 * @return mixed
 */
function K($name, $full = null, $param = array(), $driver = null){
    $class = ucfirst($name) . "Model";
    return new $class(strtolower($name), $full, $param);
}

/**
 * @param String $tableName 表名
 * @param Boolean $full 是否为全表
 * @return relationModel
 */
function R($tableName = null, $full = null){
    return new RelationModel($tableName, $full);
}

/**
 * 获得视图模型
 * @param null $table 表名
 * @param null $full 带前缀
 * @return ViewModel
 */
function V($table = null, $full = null){
    return new ViewModel($table, $full);
}


//加载语言处理
function L($name = null, $value = null){
    static $languge = array();
    if (is_null($name)) {
        return $languge;
    }
    if (is_string($name)) {
        $name = strtolower($name);
        if (!strstr($name, '.')) {
            if (is_null($value))
                return isset($languge[$name]) ? $languge[$name] : null;
            $languge[$name] = $value;
            return $languge[$name];
        }
        //二维数组
        $name = array_change_key_case_d(explode(".", $name), 0);
        if (is_null($value)) {
            return isset($languge[$name[0]][$name[1]]) ? $languge[$name[0]][$name[1]] : null;
        }
        $languge[$name[0]][$name[1]] = $value;
    }
    if (is_array($name)) {
        $languge = array_merge($languge, array_change_key_case_d($name));
        return true;
    }
}

/**
 * 载入或设置配置顶
 * @param string $name 配置名
 * @param string $value 配置值
 * @return bool|null
 */
function C($name = null, $value = null){

    static $config = array();
    if (is_null($name)) {
        return $config;
    } else if (is_string($name)) {
        $name = strtoupper($name);

        $data = array_change_key_case($config, CASE_UPPER);

        if (!strstr($name, '.')) {

            //获得配置
            if (is_null($value)) {
                return isset($data[$name]) ? $data[$name] : null;
            } else {
                return $config[$name] = isset($data[$name]) && is_array($data[$name]) && is_array($value) ? array_merge($config[$name], $value) : $value;
            }
        } else {

            //二维数组
            $name = array_change_key_case(explode('.', $name));
			//p($name);
            if (is_null($value)) {
                return isset($data[$name[0]][$name[1]]) ? $data[$name[0]][$name[1]] : null;
            } else {
                return $config[$name[0]][$name[1]] = $value;
            }
        }
    } else if (is_array($name)) {
        return $config = array_merge($config, array_change_key_case($name, CASE_UPPER));
    }
}


/**
 * 解析配置参数
 * @param string $files    配置文件路径
 * @param array  $config 配置数组
 * @param bool  $put      配置数组是否直接写入配置文件
 * @return bool|null
 */
 function CA($files,$config,$put = true){
	if (empty($config)) return true ;
	$config_array = array();
	foreach ($config as $key => $value) {
		if (is_array($value)) {
			foreach ($value as $k => $v) {
				$config_array[$key][$k] = $v;
			}
		}else {
			$config_array[$key] = $value;
		}
	}

	$config_files = (array)$files;
	if (!empty($config_files)) {
        foreach ($config_files as $config_file) {
			//读取配置
			if (file_exists($config_file)) {
				$config = @file_get_contents($config_file);
				foreach ($config_array as $name => $value) {
					//转义特殊字符
					$name = str_replace(array(
							"'",
							'"',
							'[',
							'*'
						), array(
							"\\'",
							'\"',
							'\[',
							'\*'
						), $name);
						if (is_string($value) && !in_array($value, array(
							'true',
							'false',
							'3306'
						))) {
							 //如果是字符串，加上单引号
							if (!is_numeric($value) && !stristr($value,'array('))
								$value = "'" . $value . "'";
						}
						$config = preg_replace("/(\\'".$name."')(\s*)=>(\s*)(.*?),/iU","$1 $2=>$3 {$value},",$config);
					}

					if ($put) $config = @file_put_contents($config_file, $config);
				}

				return $config;
			}
		}
}

/**
 * 获取与设置请求参数
 * @param      $var     参数如 Q("cid) Q("get.cid") Q("get.")
 * @param null $default 默认值 当变量不存在时的值
 * @param null $filter 过滤函数
 * @return array|null
 */
function Q($var, $default = null, $filter = null){

    //拆分，支持get.id  或 id
    $var = explode(".", $var);
    if (count($var) == 1) {
        array_unshift($var, 'request');
    }
    $var[0] = strtolower($var[0]);
    //获得数据并执行相应的安全处理
    switch (strtolower($var[0])) {
        case 'get' :
            $data = &$_GET;
            break;
        case 'post' :
            $data = &$_POST;
            break;
        case 'request' :
            $data = &$_REQUEST;
            break;
        case 'files' :
            $data = &$_FILES;
            break;
        case 'session' :
            $data = &$_SESSION;
            break;
        case 'cookie' :
            $data = &$_COOKIE;
            break;
        case 'server' :
            $data = &$_SERVER;
            break;
        case 'globals' :
            $data = &$GLOBALS;
            break;
        default :
            throw_exception($var[0] . 'Q方法参数错误');
    }
    //没有执行参数如q("post.")时返回所有数据
    if (empty($var[1])) {
        return in($data);
        //如果存在数据如$this->_get("page")，$_GET中存在page数据
    } else if (!empty($data[$var[1]])) {
        //要获得参数如$this->_get("page")中的page
        $value = $data[$var[1]];
        //对参数进行过滤的函数
        $funcArr = is_null($filter) ? C("FILTER_FUNCTION") : $filter;
        //参数过滤函数
        if (is_string($funcArr) && !empty($funcArr)) {
            $funcArr = explode(",", $funcArr);
        }
        //是否存在过滤函数
        if (!empty($funcArr) && is_array($funcArr)) {
            //对数据进行过滤处理
            foreach ($funcArr as $func) {
                if (!function_exists($func))
                    continue;
                $value = is_array($value) ? array_map($func, $value) : $func($value);
            }
            $data[$var[1]] = $value;
            return in($value);
        }
        return in($value);

    } else {
        $data[$var[1]] = $default;
        return in($default);
    }
}

/**
 * 快速缓存 以文件形式缓存
 * @param String $name 缓存KEY
 * @param bool $value 删除缓存
 * @param string $path 缓存目录
 * @param string $type 数据储存方式，1为序列号后存储，其他数值直接存储
 * @return bool
 */
function F($name, $value = false, $path = 'Cache/',$type='1'){
    static $_cache = array();
    $cacheFile = rtrim($path, '/') . '/' . $name . '.php';
    if (is_null($value)) {
        if (is_file($cacheFile)) {
            unlink($cacheFile);
            unset($_cache[$name]);
        }
        return true;
    }
    if ($value === false) {
        if (isset($_cache[$name])){
            return $_cache[$name];
		}
        if(is_file($cacheFile)){
			if($type=='1'){
				$content = @file_get_contents($cacheFile);
				$data = substr($content, 39, -3);
				return unserialize($data);
			}else{
				 return include $cacheFile;
			}
		}else{
			return null;
		}
    }

	if($type==1){
		$cdata = '//' . serialize($value);
	}else{
		$cdata = 'return '.compress(var_export($value, true));
	}

    $data = "<?php if(!defined('APP_PATH'))exit;\n " . $cdata . ";\n?>";
    is_dir($path) || dir_create($path);
    if (!file_put_contents($cacheFile, $data)) {
        return false;
    }
    $_cache[$name] = $value;
    return true;
}


/**
 * 缓存处理
 * @param string $name 缓存名称
 * @param bool $value 缓存内容
 * @param null $expire 缓存时间
 * @param array $options 选项
 *                        <code>
 *                        array("Driver"=>"file","dir"=>"Cache","Driver"=>"memcache")
 *                        </code>
 * @return bool
 */
function S($name, $value = false, $expire = null, $options = array()){
    // 缓存数据
    static $_data = array();
    //实例缓存对象
    $cacheObj = Cache::init($options);
    if (is_null($value)) {
        return $cacheObj->del($name);
    }
    $driver = isset($options['Driver']) ? $options['Driver'] : '';
    $key = $name . $driver;
    if ($value === false) {
        if (isset($_data[$key])) {
            Debug::$cache['read_s']++;
            return $_data[$key];
        } else {
            return $cacheObj->get($name, $expire);
        }
    }
    $cacheObj->set($name, $value, $expire);
    $_data[$key] = $value;
    return true;
}


/**
 * 根据配置文件的URL参数重新生成URL地址
 * @param String $path 访问url
 * @param array $args GET参数
 *                     <code>
 *                     $args = "nid=2&cid=1"
 *                     $args=array("nid"=>2,"cid"=>1)
 *                     </code>
 * @return string
 */
function U($path,$repath, $args = array()){
    return Route::getUrl($path,$repath, $args);
}


/**
 * 浏览器友好的变量输出
 */
function p($var){
    if (is_bool($var)) {
        var_dump($var);
    } else if (is_null($var)) {
        var_dump(NULL);
    } else {
		$content = htmlspecialchars(print_r($var, true));
		require KERNEL_PATH . 'Tpl/dump.html';
    }
}

/**
 * 404错误
 * @param string $msg 提示信息
 * @param string $url 跳转url
 */
function _404($msg = "", $url = ""){
    DEBUG && error($msg);

    //写入日志
    Log::write($msg);

    if (empty($url) || C("404_URL")) {
        $url = C("404_URL");
    }
    if ($url){
		$url = stristr($url,'http://') > 0 ? $url : __HOST__.$url;
        go($url);
    }else{
        set_http_state(404);
	}
    exit;
}

/**
 * 抛出异常
 * @param string $msg 错误信息
 * @param string $type 异常类
 * @param int $code 编码
 * @throws
 */
function throw_exception($msg, $type = "HdException", $code = 0)
{
    if (class_exists($type, false)) {
        throw new $type($msg, $code, true);
    } else {
        error($msg);
    }
}

/**
 * 将错误记录到日志
 * @param $error 错误信息
 */
function log_write($error)
{
    $trace = debug_backtrace();
    $e['message'] = $error;
    $e['file'] = $trace[0]['file'];
    $e['line'] = $trace[0]['line'];
    $e['class'] = isset($trace[0]['class']) ? $trace[0]['class'] : "";
    $e['function'] = isset($trace[0]['function']) ? $trace[0]['function'] : "";
    $msg = ("[Error]" . $e['message'] . " [Time]" . date("y-m-d h:i") . " [File]" . $e['file'] . " [Line]" . $e['line']);
    //写入日志
    Log::write($msg);
}

/**
 * 错误中断
 * @param string | array $error 错误内容
 */
function error($error){
    $e = array();
    if (DEBUG) {
		$trace = array();
        if (!is_array($error)) {
			if(C('TRACE')) {$trace = debug_backtrace();}
            $e['message'] = $error;
            $e['file'] = $trace[0]['file'];
            $e['line'] = $trace[0]['line'];
            $e['class'] = isset($trace[0]['class']) ? $trace[0]['class'] : "";
            $e['function'] = isset($trace[0]['function']) ? $trace[0]['function'] : "";
            ob_start();
            debug_print_backtrace();
            $e['trace'] = htmlspecialchars(ob_get_clean());
        } else {
            $e = $error;
        }
    } else {
        //错误显示url
        if ($_url = C('ERROR_URL')) {
            go($_url);
        } else {
            $e['message'] = C('ERROR_MESSAGE');
        }
    }

    //显示DEBUG模板，开启DEBUG显示trace
    require KERNEL_PATH . 'Tpl/error.html';
    exit;
}

/**
 * trace记录
 * @param string $value 错误信息
 * @param string $level
 * @param bool $record
 * @return mixed
 */
function trace($value = '[HDPHP]', $level = 'DEBUG', $record = false){
    static $_trace = array();
    if ('[HDPHP]' === $value) { // 获取trace信息
        return $_trace;
    } else {
        $info = ' : ' . print_r($value, true);
        //调试模式时处理ERROR类型
        if ( C('DEBUG') && 'ERROR' == $level) {
            throw_exception($info);
        }
        if (!isset($_trace[$level])) {
            $_trace[$level] = array();
        }
        $_trace[$level][] = $info;
        if (IS_AJAX || $record) {
            Log::record($info, $level, $record);
        }
    }
}


/**
 * firebug调试模式
 * 需要firefox下安装firebug和firephp插件
 * @param $data 打印的数据
 */
function firephp($data)
{
    ob_start();
    $firephp = FirePHP::getInstance(true);
    $firephp->log($data, 'Iterators');
    ob_flush();
    ob_clean();
}

/**
 * 返回错误类型
 * @param int $type
 * @return strings
 */
function FriendlyErrorType($type)
{
    switch ($type) {
        case E_ERROR: // 1 //
            return 'E_ERROR';
        case E_WARNING: // 2 //
            return 'E_WARNING';
        case E_PARSE: // 4 //
            return 'E_PARSE';
        case E_NOTICE: // 8 //
            return 'E_NOTICE';
        case E_CORE_ERROR: // 16 //
            return 'E_CORE_ERROR';
        case E_CORE_WARNING: // 32 //
            return 'E_CORE_WARNING';
        case E_CORE_ERROR: // 64 //
            return 'E_COMPILE_ERROR';
        case E_CORE_WARNING: // 128 //
            return 'E_COMPILE_WARNING';
        case E_USER_ERROR: // 256 //
            return 'E_USER_ERROR';
        case E_USER_WARNING: // 512 //
            return 'E_USER_WARNING';
        case E_USER_NOTICE: // 1024 //
            return 'E_USER_NOTICE';
        case E_STRICT: // 2048 //
            return 'E_STRICT';
        case E_RECOVERABLE_ERROR: // 4096 //
            return 'E_RECOVERABLE_ERROR';
        case E_DEPRECATED: // 8192 //
            return 'E_DEPRECATED';
        case E_USER_DEPRECATED: // 16384 //
            return 'E_USER_DEPRECATED';
    }
    return $type;
}

/**
 * 跳转网址
 * @param string $url 跳转url
 * @param int $time 跳转时间
 * @param string $msg
 */
function go($url, $time = 0, $msg = ''){
    $url = Route::getUrl($url);
    if (!headers_sent()) {
        $time == 0 ? header("Location:" . $url) : header("refresh:{$time};url={$url}");
        exit($msg);
    } else {
        echo "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
        if ($time)
			exit($msg);
    }
}

 /**
 * 直接跳转
 * @param string $url 跳转url
 * @param int $code HTML状态码
 */
function redirect( $url, $code=302) {
	header('location:' . $url, true, $code);
	exit;
}


/**
 * 判断请求方式
 * @return boolean
 */
function request_type($type){
	switch ($type){
	case 'ajax': //是否为AJAX提交
	  return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false;
	  break;
	case 'get':
	  return $_SERVER['REQUEST_METHOD'] == 'GET' ? true : false;
	  break;
	default:
	    return ($_SERVER['REQUEST_METHOD'] == 'POST' && (empty($_SERVER['HTTP_REFERER']) || preg_replace("~https?:\/\/([^\:\/]+).*~i", "\\1", $_SERVER['HTTP_REFERER']) == preg_replace("~([^\:]+).*~", "\\1", $_SERVER['HTTP_HOST']))) ? true : false;
	}
}


/**
 * 递归创建目录
 * @param string $dirName 目录
 * @param int $auth 权限
 * @return bool
 */
function dir_create($dirName, $auth = 0755){
    $dirName = str_replace("\\", "/", $dirName);
    $dirPath = rtrim($dirName, '/');
    if (is_dir($dirPath))
        return true;
    $dirs = explode('/', $dirPath);
    $dir = '';
    foreach ($dirs as $v) {
        $dir .= $v . '/';
        is_dir($dir) or @mkdir($dir, $auth, true);
    }
    return is_dir($dirPath);
}


/**
 * 将数组中的值全部转为大写或小写
 * @param array $arr
 * @param int $type 类型 1值大写 0值小写
 * @return array
 */
function array_change_value_case($arr, $type = 0){
    $function = $type ? 'strtoupper' : 'strtolower';
    $newArr = array(); //格式化后的数组
    foreach ($arr as $k => $v) {
        if (is_array($v)) {
            $newArr[$k] = array_change_value_case($v, $type);
        } else {
            $newArr[$k] = $function($v);
        }
    }

    return $newArr;
}

/**
 * 将数组键名变成大写或小写
 * @param array $arr 数组
 * @param int $type 转换方式 1大写   0小写
 * @return array
 */
function array_change_key_case_d($arr, $type = 0){
    $function = $type ? 'strtoupper' : 'strtolower';
    $newArr = array(); //格式化后的数组
    if (!is_array($arr) || empty($arr))
        return $newArr;
    foreach ($arr as $k => $v) {
        $k = $function($k);
        if (is_array($v)) {
            $newArr[$k] = array_change_key_case_d($v, $type);
        } else {
            $newArr[$k] = $v;
        }
    }
    return $newArr;
}

/**
 * 不区分大小写检测数据键名是否存在
 * @access public
 * @param string $key  数组的键或值
 * @param array $data  数组
 * @return boolean
 */
function array_key_exists_d($key, $arr){
    return array_key_exists(strtolower($key), array_change_key_case_d($arr));
}



/**
 * HTTP状态信息设置
 * @param Number $code 状态码
 */
function set_http_state($code){
    $state = array(200 => 'OK', // Success 2xx
        // Redirection 3xx
        301 => 'Moved Permanently', 302 => 'Moved Temporarily ',
        // Client Error 4xx
        400 => 'Bad Request', 403 => 'Forbidden', 404 => 'Not Found',
        // Server Error 5xx
        500 => 'Internal Server Error', 503 => 'Service Unavailable',
    );
    if (isset($state[$code])) {
        header('HTTP/1.1 ' . $code . ' ' . $state[$code]);
        header('Status:' . $code . ' ' . $state[$code]);
        //FastCGI模式
    }
}

/**
 * 是否为SSL协议
 * @return boolean
 */
function is_ssl(){
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
        return true;
    }
    return false;
}



/**
 * 加载文件并缓存
 * @param null $path 导入的文件
 * @return bool
 */
function require_cache($path = null){

	//文件缓存
    static $_files = array();

	//加载过的文件列表
    if (is_null($path)) {
        return $_files;
    }

	//已经加载过
    if (isset($_files[$path])) {
        return true;
    }

	//区分大小写的文件判断
	 if (!file_exists_case($path)) {
        return false;
    }

	//加载文件并记录缓存
    require($path);
    $_files[$path] = true;
    return true;
}


/**
 * 区分大小写的判断文件判断
 * @param string $file 需要判断的文件
 * @return boolean
 */
function file_exists_case($file){
    if (is_file($file)) {
        //windows环境下检测文件大小写
        if (IS_WIN && C("CHECK_FILE_CASE")) {
            if (basename(realpath($file)) != basename($file)) {
                return false;
            }
        }
        return true;
    }
    return false;
}



/**
 * 移除URL中的指定GET变量
 * @param string $var 要移除的GET变量名称
 * @param string $url 操作的url
 * @return string 移除GET变量后的URL地址
 */
function remove_url_param($var, $url = null){
    return Route::removeUrlParam($var, $url);
}

/**
 * session处理
 * @param string|array $name 数组为初始session
 * @param string $value 值
 * @return mixed
 */
function session($name = '', $value = ''){
	ini_set('session.use_only_cookies', 1);
    if (is_array($name)) {

        ini_set('session.auto_start', 0);
        if (isset($name['name'])){
            session_name($name['name']);
		}
        if (isset($_REQUEST[session_name()])){
            session_id($_REQUEST[session_name()]);
		}
        if (isset($name['path'])){
            session_save_path($name['path']);
		}
        if (isset($name['domain'])){
            ini_set('session.cookie_domain', $name['domain']);
		}
        if (isset($name['expire'])) {
            ini_set('session.gc_maxlifetime', $name['expire']);
            session_set_cookie_params($name['expire']);
        }
        if (isset($name['use_trans_sid'])){
            ini_set('session.use_trans_sid', $name['use_trans_sid'] ? 1 : 0);
		}
        if (isset($name['use_cookies'])){
            ini_set('session.use_cookies', $name['use_cookies'] ? 1 : 0);
		}
        if (isset($name['cache_limiter'])){
            session_cache_limiter($name['cache_limiter']);
		}
        if (isset($name['cache_expire'])){
            session_cache_expire($name['cache_expire']);
		}
        if (isset($name['type'])) {
            $class = 'Session' . ucwords($name['type']);
            require_cache(DRIVER_PATH . '/Session/' . $class . '.class.php');
            $hander = new $class();
            $hander->run();
        }
        //自动开启SESSION
        if (C('SESSION_AUTO_START')) {
			$session_name = session_name();
			if(!isset($_COOKIE[$session_name])){
				 foreach($_COOKIE as $key=>$val){
					 $key = strtoupper($key); //转换为大写
					//如果包含 session_name 关键字则把该字串当做 sessionid 启用
					if(strpos($key,$session_name)){
					  session_id($_COOKIE[$key]);
					}
				 }
			}
            session_start();
        }
    } elseif ($name === '') {
        return $_SESSION;
    } elseif (is_null($name)) {
        $_SESSION = array();
        session_unset();
        session_destroy();
    } elseif ($value === '') {
        if ('[pause]' == $name) { // 暂停
            session_write_close();
        } elseif ('[start]' == $name) { //开启
			$session_name = session_name();
			if(!isset($_COOKIE[$session_name])){
				 foreach($_COOKIE as $key=>$val){
					 $key = strtoupper($key); //转换为大写
					//如果包含 session_name 关键字则把该字串当做 sessionid 启用
					if(strpos($key,$session_name)){
					  session_id($_COOKIE[$key]);
					}
				 }
			}
            session_start();
        } elseif ('[destroy]' == $name) { //销毁
            $_SESSION = array();
            session_unset();
            session_destroy();
        } elseif ('[regenerate]' == $name) { //生成id
            session_regenerate_id();
        } elseif (0 === strpos($name, '?')) { // 检查session
            $name = substr($name, 1);
            return isset($_SESSION[C('SESSION_KEY').'_'.$name]);
        } elseif (is_null($name)) { // 清空session
            $_SESSION = array();
        } else {
            return isset($_SESSION[C('SESSION_KEY').'_'.$name]) ? $_SESSION[C('SESSION_KEY').'_'.$name] : null;
        }
    } elseif (is_null($value)) { // 删除session
        if (isset($_SESSION[C('SESSION_KEY').'_'.$name]))
            unset($_SESSION[C('SESSION_KEY').'_'.$name]);
    } else { //设置session
        $_SESSION[C('SESSION_KEY').'_'.$name] = $value;
    }
}

/**
 * cookie处理
 * @param        $name   名称
 * @param string $value 值
 * @param mixed $option 选项
 * @return mixed
 */
function cookie($name, $value = '', $option = array()){
    // 默认设置
    $config = array(
		'prefix' => C('COOKIE_PREFIX'), // cookie 名称前缀
        'expire' => C('COOKIE_EXPIRE'), // cookie 保存时间
        'path'   => C('COOKIE_PATH'), // cookie 保存路径
        'domain' => C('COOKIE_DOMAIN'), // cookie 有效域名
    );
    // 参数设置(会覆盖黙认设置)
    if (!empty($option)) {
        if (is_numeric($option))
            $option = array('expire' => $option);
        elseif (is_string($option))
            parse_str($option, $option);
        $config = array_merge($config, array_change_key_case($option));
    }
    // 清除指定前缀的所有cookie
    if (is_null($name)) {
        if (empty($_COOKIE)) return;
        // 要删除的cookie前缀，不指定则删除config设置的指定前缀
        $prefix = empty($value) ? $config['prefix'] : $value;
        if (!empty($prefix)) { // 如果前缀为空字符串将不作处理直接返回
            foreach ($_COOKIE as $key => $val) {
                if (0 === stripos($key, $prefix)) {
                    setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
                    unset($_COOKIE[$key]);
                }
            }
        }
        return $_COOKIE;
    }
    $name = $config['prefix'] . $name;
    if ('' === $value) {
        // 获取指定Cookie
        return isset($_COOKIE[$name]) ? json_decode(MAGIC_QUOTES_GPC ? stripslashes($_COOKIE[$name]) : $_COOKIE[$name]) : null;
    } else {
        if (is_null($value)) {
            setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
            unset($_COOKIE[$name]);
            // 删除指定cookie
        } else {
            // 设置cookie
            $value = json_encode($value);
            $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
            setcookie($name, $value, $expire, $config['path'], $config['domain']);
            $_COOKIE[$name] = $value;
        }
    }
}


/**
 * 获得随机字符串
 * @param int $len 长度
 * @return string
 */
function rand_str($len = 6,$data = 'abcdefghijklmnopqrstuvwxyz0123456789'){
    $str = '';
    while (strlen($str) < $len)
        $str .= substr($data, mt_rand(0, strlen($data) - 1), 1);
    return $str;
}

/**
 * 检测是否序列化
 * @param $var
 * @return blooue
 */
function is_serialized($data) {
     $data = trim( $data );
     if ( 'N;' == $data )
         return true;
     if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
         return false;
     switch ( $badions[1] ) {
         case 'a' :
         case 'O' :
         case 's' :
             if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
                 return true;
             break;
         case 'b' :
         case 'i' :
         case 'd' :
             if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
                 return true;
             break;
     }
     return false;
 }


/**
 *过滤字符串和字符串数组，防止被挂马和sql注入
 * @param string $string 必需，规定被过滤的字符串或字符串数组
 * @param bool $force 可选，规定是否忽略get_magic_quotes_gpc函数
 * @return string|array
 */
function in($string,$force=true){
	if(is_string($string)){
		$string=trim(htmlspecialchars($string));//防止被挂马，跨站攻击
		if(($force==true)||(!get_magic_quotes_gpc())) {
		   $string = addslashes($string);//防止sql注入
		}
		return  addslashes($string);
	} else if(is_array($string)) {
		foreach($string as $key=>$value){
			 $string[$key]=in($value,$force);
		}
		return $string;
	} else {
		return $string;
	}
}

/**
 *用来还原字符串和字符串数组，把已经转义的字符还原回来
 * @param string $string 必需，规定还原字符串和字符串数组
 * @return string|array
 */
function out($string){
	if(is_string($string)){
		return $string = stripslashes($string);
	} else if(is_array($string)){
		foreach($string as $key=>$value){
			 $string[$key]=out($value);
		}
		return $string;
	} else {
		return $string;
	}
}


/**
 * 检查是否是正确的邮箱地址，
 * @param string $string 必需，规定被检查的字符串
 * @return bool  返回true 或 false
 */
function is_email($string){
    $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
    if (strpos($string, '@') !== false && strpos($string, '.') !== false){
        if (preg_match($chars, $string)){
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

/**
 * 获取图片缩略图
 * @param string $string 必需，原图片路径
 * @return string  返回包含路径的缩略图
 */
function thumb($string){
	$strinfo = pathinfo($string);
	return $strinfo['dirname'].'/'.C('THUMB_PREFIX').$strinfo['filename'].C('THUMB_ENDFIX').'.'.$strinfo['extension'];
}


/**
 * 导入文件数组
 */
function require_array($fileArr,$module=null){
    foreach ($fileArr as $key=>$file) {
		if(isset($module)){
			$file = APP_PATH.$file.'/'.$module.'/'.CONTROLLER.$key.EXT;
			if (is_file($file) && require_cache($file)) return $key;
		}else{
			if (is_file($file) && require_cache($file)) return true;
		}
    }
    return false;
}

/**
 * 检测通过分隔符检测某字符串是否存在
 * @param string $ide 必需，规定所搜索的字符串
 * @param string $string 必需，被检测的字符串标识
 * @param string $sign  可选，字符串分割标示
 * @return bool  ture或false
 */
function stride($ide,$string,$sign = '|'){
	if (in_array($ide,explode($sign,$string))){
		return true;
	}else{
		return false;
	}
	return false;
}


/**
 * 写入最新消息
 * @param string $type 必需，消息类型，order：订单，gbook：留言，comment：评论
 * @param string $status 必需，状态标识，比如当消息为order是，0表示未读订单，1表示未发货订单...可自行定义
 * @param string $id  可选，数据库ID，
 * @param string $path  可选，消息文件存储路径，
 * @return bool  ture或false
 */
function message($type='order', $status=0, $id=0, $action='add', $path=''){
	$path = empty($path) ? C('MESSAGE_PATH') : $path;
	if ($action=='add') {
		$file = base64_encode($type.'-'.$id.'-'.time().'-'.rand_str(20).'.msg');
		@file_put_contents($path.$file,$status);
	}else{
		$list = scandir($path);
		unset($list[0],$list[1]);
		if (!empty($list)){
			foreach ($list  as $file) {
				$file_info = base64_decode($file);
				if (stripos($file_info,'.msg')) {
					$temp_content = explode('-',$file_info);
					if ($temp_content[0]==$type && $id==$temp_content[1]) {
						unlink($path.$file);
					}
				}
			}
		}
	}
}

/**
* 生成一定数量的随机数，并且不重复
* @param integer $number 可选，生成的数量
* @param integer $length 可选，生成的字符串长度
* @param integer $mode 可选，字符串类型：0 字母 1 数字 其它 混合
* @return string
*/
function buildCountRand ($number='100',$length=4,$mode=1) {
	if($mode==1 && $length<strlen($number) ) {return false;}
	$rand   =  array();
	for($i=0; $i<$number; $i++) {
            $rand[] =   self::randString($length,$mode);
    }
        $unqiue = array_unique($rand);
        if(count($unqiue)==count($rand)) {
            return $rand;
        }
        $count   = count($rand)-count($unqiue);
        for($i=0; $i<$count*3; $i++) {
            $rand[] =   self::randString($length,$mode);
        }
    $rand = array_slice(array_unique ($rand),0,$number);
    return $rand;
}

/**
 * POST表单过滤
 * @param array $post_array  必需，表单数据
 * @param bool $null_value   可选，是否删除空表单
 * @param array $delete_value  可选，删除指定表单
 * @return string 压缩后的字符串
 */
function postinput($post_array,$null_value = null,$delete_value = array()){
    //清除值为空或者为0的元素
    if($null_value){
        foreach($post_array as $key=>$value){
            $value = in($value);
            if($value == ''){
                unset($post_array[$key]);
            }
        }
    }
    //清除不需要的元素
    $default_value = array('action','button','fid','submit');
    $clear_array = array_merge($default_value,$delete_value);
    foreach($post_array as $key=>$value){
        if(in_array($key,$clear_array)){
            unset($post_array[$key]);
        }
    }
    return $post_array;
}

/**
 * 会员密码加密
 * @param string $string  必需，规定被加密的字符串
 * @return string 返回加密后的字符串
 */
function encrypt($string){
    return md5(substr(md5($string),7,-7));
}


/**
 * 加密方法
 * @param      $data 加密字符串
 * @param null $key 密钥
 * @return mixed|string
 */
function encode($data, $key = null){
    return encry::encrypt($data, $key);
}

/**
 * 解密方法
 * @param string $data 解密字符串
 * @param null $key 密钥
 * @return mixed
 */
function decode($data, $key = null){
    return encry::decrypt($data, $key);
}

/**
 * 多维数组转一维
 * @param Array $array 数组
 * @return Array 返回一维数组
 */
function array_columns($array){
  static $tmp=array();
  foreach($array as $key=>$value){
	 if(is_array($value)){
		 array_columns($value);
	 }else{
		$tmp[]=$value;
	 }
  }
  return $tmp;
}

/**
 * 多维数组根据值排序
 * @param Array $multi_array 数组
 * @param Array $sort_key 排序键值
 * @param Array $sort 排序方式
 * @return Array 返回一维数组
 */
function multi_array_sort($multi_array, $sort_key, $sort = SORT_ASC) {
	if (is_array($multi_array)) {
		foreach ($multi_array as $row_array) {
			if (is_array($row_array)) {
				$key_array[] = $row_array[$sort_key];
			}else{
			return false;
			}
		}
	}else{
		return false;
	}
	array_multisort($key_array, $sort, $multi_array);
	return $multi_array;
}

/**
 * 去空格，去除注释包括单行及多行注释
 * @param string $content 数据
 * @return string
 */
function compress($content)
{
    $str = ""; //合并后的字符串
    $data = token_get_all($content);
    $end = false; //没结束如$v = "hdphp"中的等号;
    for ($i = 0, $count = count($data); $i < $count; $i++) {
        if (is_string($data[$i])) {
            $end = false;
            $str .= $data[$i];
        } else {
            switch ($data[$i][0]) { //检测类型
                //忽略单行多行注释
                case T_COMMENT:
                case T_DOC_COMMENT:
                    break;
                //去除格
                case T_WHITESPACE:
                    if (!$end) {
                        $end = true;
                        $str .= " ";
                    }
                    break;
                //定界符开始
                case T_START_HEREDOC:
                    $str .= "<<<SUKE\n";
                    break;
                //定界符结束
                case T_END_HEREDOC:
                    $str .= "SUKE;\n";
                    //类似str;分号前换行情况
                    for ($m = $i + 1; $m < $count; $m++) {
                        if (is_string($data[$m]) && $data[$m] == ';') {
                            $i = $m;
                            break;
                        }
                        if ($data[$m] == T_CLOSE_TAG) {
                            break;
                        }
                    }
                    break;

                default:
                    $end = false;
                    $str .= $data[$i][1];
            }
        }
    }
    return $str;
}

/**
 * Hash函数
 */
function hash_hd($data, $len){
    $hash = crc32($data) & 0xfffffff;
    return $hash % $len;
}


/**
 * 压缩html，清除换行符,清除制表符,去掉注释标记
 * @param string $string  必需，规定被压缩的字符串
 * @return string 压缩后的字符串
 */
function compress_html($string) {
	$string = str_replace("\r\n", '', $string); //清除换行符
	$string = str_replace("\n", '', $string); //清除换行符
	$string = str_replace("\t", '', $string); //清除制表符
	return $string;
}

/**
 * 获取微秒时间，常用于计算程序的运行时间
 */
function utime(){
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

/**
 * 生成唯一编号
 */
function uniq_orderid($str='10',$isdate=true){
   $orderid = substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, $str);
	if($isdate){
		return date('Ymd').$orderid;
	}else{
		return $orderid;
	}
}


/**
 * 生成序列字符串
 * @param $var
 * @return string
 */
function seria($var){
    return md5(serialize($var));
}

/**
 * 友好的时间输出
 */
function mdate($time=NULL) {
    $text = '';
    $time = $time === NULL || $time > time() ? time() : intval($time);
    $t = time() - $time; //时间差 （秒）
    $y = date('Y', $time)-date('Y', time());//是否跨年
    switch($t){
     case $t == 0:
       $text = '刚刚';
       break;
     case $t < 60:
      $text = $t . '秒前'; // 一分钟内
      break;
     case $t < 60 * 60:
      $text = floor($t / 60) . '分钟前'; //一小时内
      break;
     case $t < 60 * 60 * 24:
      $text = floor($t / (60 * 60)) . '小时前'; // 一天内
      break;
     case $t < 60 * 60 * 24 * 3:
      $text = floor($time/(60*60*24)) ==1 ?'昨天 ' . date('H:i', $time) : '前天 ' . date('H:i', $time) ; //昨天和前天
      break;
     case $t < 60 * 60 * 24 * 30:
      $text = date('m月d日 H:i', $time); //一个月内
      break;
     case $t < 60 * 60 * 24 * 365&&$y==0:
      $text = date('m月d日', $time); //一年内
      break;
     default:
      $text = date('Y年m月d日', $time); //一年以前
      break;
    }
    return $text;
}

/**
 * 获取客户端IP地址
 */
function get_client_ip(){
	$ip=false;
	if(!empty($_SERVER["HTTP_CLIENT_IP"])){
		$ip = $_SERVER["HTTP_CLIENT_IP"];
	}
	if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
		$ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
		if($ip) array_unshift($ips, $ip); $ip = FALSE;
			foreach ($ips as $value){
				if (!eregi("^(10|172\.16|192\.168)\.", $value)){
				$ip = $value;
				break;
				}
			}
		}
    return($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}

/**
 * 获取服务器端IP地址
 */
function get_server_ip() {
    if (isset($_SERVER)) {
        if($_SERVER['SERVER_ADDR']) {
            $ip = $_SERVER['SERVER_ADDR'];
        } else {
            $ip = $_SERVER['LOCAL_ADDR'];
        }
    } else {
        $ip = getenv('SERVER_ADDR');
    }
    return $ip;
}

/**
 * 判断是不是时间
 * @param datetime $date  必需，待检测的时间
 * @param array formats  必需，时间格式
 * @return blue
 */
function is_date($date,$formats=array('Y-m-d','Y/m/d','Y-m-d H:i:s','Y/m/d H:i:s','Y-m','m-d','H:i:s','Y年m月d日 H时i分s秒','Y年m月d日','m月d日','H时i分s秒')){
	$unixtime = strtotime($date);
	if(!$unixtime){
		return false;
	}
	foreach($formats as $format){
		if (date($format,$unixtime)==$date) {
			return true;
		}
	}

}


/**
 * 格式化金额
 *
 * @param int $money 必须，需要格式化的金额
 * @param int $len  可选,小数点长度，默认保留两位小数
 * @param string $sign 可选，货币单位符号，默认为人民币单位
 * @param string $unit 可选，货币单位符号，默认无
 * @param string $split 可选，千位是否分隔，默认true
 * @return string
 */
function format_money($money, $unit='', $sign='￥', $len=2,$split= true,$format=true){
    $negative = $money > 0 ? '' : '-';
    $int_money = intval(abs($money));
    $len = intval(abs($len));
    $decimal = '';//小数
    if ($len > 0) {
        $decimal = '.'.substr(sprintf('%01.'.$len.'f', $money),-$len);
    }
    $tmp_money = strrev($int_money);
	if ($split) {
		$strlen = strlen($tmp_money);
		for ($i = 3; $i < $strlen; $i += 3) {
			$format_money .= substr($tmp_money,0,3).',';
			$tmp_money = substr($tmp_money,3);
		}
	}
    $format_money .= $tmp_money;
    $format_money = strrev($format_money);
	if ($format) {
		return '<label class="cursign">'.$sign.'</label>'.$negative.$format_money.$decimal.'<label class="curunit">'.$unit.'</label>';
	}else{
		return $sign.$negative.$format_money.$decimal.$unit;
	}
}

/**
 * 中文金额转大写
 *
 * @param m $string  必需，数字货币金额
 * @return string 返回大写中文金额
 */
function changemoney($m) {
		$i = 0;
        $c = '';
		$c1 = '零壹贰叁肆伍陆柒捌玖';
		$c2 = '分角元拾佰仟万拾佰仟亿';
		if (empty($m)) {
			return '';
		}
        //精确到分,只留两个小数位
        $m = round($m, 2) * 100;

        if (strlen($m) > 10) {
            return '金额过大，无法转换';
        }

        while (1) {
            if ($i == 0) {
                $n = substr($m, strlen($m)-1, 1);
            } else {
                $n = $m % 10;
            }
            $p1 = substr($c1, 3 * $n, 3);
            $p2 = substr($c2, 3 * $i, 3);
            if ($n != '0' || ($n == '0' && ($p2 == '亿' || $p2 == '万' || $p2 == '元'))) {
                    $c = $p1 . $p2 . $c;
            } else {
                    $c = $p1 . $c;
            }
            $i = $i + 1;
            $m = (int)($m / 10);
			if ($m == 0) {
				break;
			}
        }
        $j = 0;
        $slen = strlen($c);
        while ($j < $slen) {
            $m = substr($c, $j, 6);
            //处理数字中很多0的情况,每次循环去掉一个汉字“零”
            if ($m == '零元' || $m == '零万' || $m == '零亿' || $m == '零零') {
                $left = substr($c, 0, $j);
                $right = substr($c, $j + 3);
                $c = $left . $right;
                $j = $j-3;
                  $slen = $slen-3;
            }
            $j = $j + 3;
        }
        if (substr($c, strlen($c)-3, 3) == '零') {
                $c = substr($c, 0, strlen($c)-3);
        }
        //将处理的汉字加上“整”

		return empty($c) ?  '零元整' :  $c . '整';
 }

/**
 * 分割URL参数到数组
 * @param m $string  必需，url
 * @return string 数组
 */
function conUrlQuery($query){
    $queryparts = explode('&',$query);
    $params = array();
    foreach ($queryparts as $param) {
        $item = explode('=', $param);
        $params[$item[0]] = $item[1];
    }
    return $params;
}

/**
 * 解析Json格式数据
 */
 function analyJson($data, $mode=false){
	$data = str_replace('\\', '', $data);
	//key无双引号时自动不全；
	if(preg_match('/\w:/', $data)){
		$data = preg_replace('/(\w+):/is', '"$1":', $data);
	}
	//值无双引号时自动不全；
	if(preg_match('/:\w/', $data)){
	    $data = preg_replace('/:(\w+)/is', ':"$1"', $data);
	}

	if (!empty($data)) {
		$data = json_decode($data, $mode);
	}else{
		return false;
	}
	return $data;
}

//如果json_encode没有定义，则定义json_encode函数，常用于返回ajax数据
if (!function_exists('json_encode')) {
     function format_json_value(&$value){
        if(is_bool($value)) {
            $value = $value?'true':'false';
        }else if(is_int($value)){
            $value = intval($value);
        }else if(is_float($value)){
            $value = floatval($value);
        }else if(defined($value) && $value === null){
            $value = strval(constant($value));
        }else if(is_string($value)){
            $value = '"'.addslashes($value).'"';
        }
        return $value;
    }

    function json_encode($data){
        if(is_object($data)){
            //对象转换成数组
            $data = get_object_vars($data);
        }else if(!is_array($data)) {
            // 普通格式直接输出
            return format_json_value($data);
        }
        // 判断是否关联数组
        if(empty($data) || is_numeric(implode('',array_keys($data)))) {
            $assoc  =  false;
        }else {
            $assoc  =  true;
        }
        // 组装 Json字符串
        $json = $assoc ? '{' : '[' ;
        foreach($data as $key=>$val) {
            if(!is_null($val)) {
                if($assoc){
                    $json .= "\"$key\":".json_encode($val).",";
                }else{
                    $json .= json_encode($val).",";
                }
            }
        }
        if(strlen($json)>1) {// 加上判断 防止空数组
            $json  = substr($json,0,-1);
        }
        $json .= $assoc ? '}' : ']' ;
        return $json;
    }
}