PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/ThinkPHP/Common/functions.php

https://github.com/ycj/thinkphp
PHP | 773 lines | 559 code | 26 blank | 188 comment | 147 complexity | ff99139fd09ef316686d59afe26857bf MD5 | raw file
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. /**
  12. * Think 标准模式公共函数库
  13. * @category Think
  14. * @package Common
  15. * @author liu21st <liu21st@gmail.com>
  16. */
  17. /**
  18. * 错误输出
  19. * @param mixed $error 错误
  20. * @return void
  21. */
  22. function halt($error) {
  23. $e = array();
  24. if (APP_DEBUG) {
  25. //调试模式下输出错误信息
  26. if (!is_array($error)) {
  27. $trace = debug_backtrace();
  28. $e['message'] = $error;
  29. $e['file'] = $trace[0]['file'];
  30. $e['class'] = isset($trace[0]['class'])?$trace[0]['class']:'';
  31. $e['function'] = isset($trace[0]['function'])?$trace[0]['function']:'';
  32. $e['line'] = $trace[0]['line'];
  33. $traceInfo = '';
  34. $time = date('y-m-d H:i:m');
  35. foreach ($trace as $t) {
  36. $traceInfo .= '[' . $time . '] ' . $t['file'] . ' (' . $t['line'] . ') ';
  37. $traceInfo .= $t['class'] . $t['type'] . $t['function'] . '(';
  38. $traceInfo .= implode(', ', $t['args']);
  39. $traceInfo .=')<br/>';
  40. }
  41. $e['trace'] = $traceInfo;
  42. } else {
  43. $e = $error;
  44. }
  45. } else {
  46. //否则定向到错误页面
  47. $error_page = C('ERROR_PAGE');
  48. if (!empty($error_page)) {
  49. redirect($error_page);
  50. } else {
  51. if (C('SHOW_ERROR_MSG'))
  52. $e['message'] = is_array($error) ? $error['message'] : $error;
  53. else
  54. $e['message'] = C('ERROR_MESSAGE');
  55. }
  56. }
  57. // 包含异常页面模板
  58. include C('TMPL_EXCEPTION_FILE');
  59. exit;
  60. }
  61. /**
  62. * 自定义异常处理
  63. * @param string $msg 异常消息
  64. * @param string $type 异常类型 默认为ThinkException
  65. * @param integer $code 异常代码 默认为0
  66. * @return void
  67. */
  68. function throw_exception($msg, $type='ThinkException', $code=0) {
  69. if (class_exists($type, false))
  70. throw new $type($msg, $code, true);
  71. else
  72. halt($msg); // 异常类型不存在则输出错误信息字串
  73. }
  74. /**
  75. * 浏览器友好的变量输出
  76. * @param mixed $var 变量
  77. * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
  78. * @param string $label 标签 默认为空
  79. * @param boolean $strict 是否严谨 默认为true
  80. * @return void|string
  81. */
  82. function dump($var, $echo=true, $label=null, $strict=true) {
  83. $label = ($label === null) ? '' : rtrim($label) . ' ';
  84. if (!$strict) {
  85. if (ini_get('html_errors')) {
  86. $output = print_r($var, true);
  87. $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  88. } else {
  89. $output = $label . print_r($var, true);
  90. }
  91. } else {
  92. ob_start();
  93. var_dump($var);
  94. $output = ob_get_clean();
  95. if (!extension_loaded('xdebug')) {
  96. $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
  97. $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  98. }
  99. }
  100. if ($echo) {
  101. echo($output);
  102. return null;
  103. }else
  104. return $output;
  105. }
  106. /**
  107. * 404处理
  108. * 调试模式会抛异常
  109. * 部署模式下面传入url参数可以指定跳转页面,否则发送404信息
  110. * @param string $msg 提示信息
  111. * @param string $url 跳转URL地址
  112. * @return void
  113. */
  114. function _404($msg='',$url='') {
  115. APP_DEBUG && throw_exception($msg);
  116. if($msg && C('LOG_EXCEPTION_RECORD')) Log::write($msg);
  117. if(empty($url) && C('URL_404_REDIRECT')) {
  118. $url = C('URL_404_REDIRECT');
  119. }
  120. if($url) {
  121. redirect($url);
  122. }else{
  123. send_http_status(404);
  124. exit;
  125. }
  126. }
  127. /**
  128. * 设置当前页面的布局
  129. * @param string|false $layout 布局名称 为false的时候表示关闭布局
  130. * @return void
  131. */
  132. function layout($layout) {
  133. if(false !== $layout) {
  134. // 开启布局
  135. C('LAYOUT_ON',true);
  136. if(is_string($layout)) { // 设置新的布局模板
  137. C('LAYOUT_NAME',$layout);
  138. }
  139. }else{// 临时关闭布局
  140. C('LAYOUT_ON',false);
  141. }
  142. }
  143. /**
  144. * URL组装 支持不同URL模式
  145. * @param string $url URL表达式,格式:'[分组/模块/操作#锚点@域名]?参数1=值1&参数2=值2...'
  146. * @param string|array $vars 传入的参数,支持数组和字符串
  147. * @param string $suffix 伪静态后缀,默认为true表示获取配置值
  148. * @param boolean $redirect 是否跳转,如果设置为true则表示跳转到该URL地址
  149. * @param boolean $domain 是否显示域名
  150. * @return string
  151. */
  152. function U($url='',$vars='',$suffix=true,$redirect=false,$domain=false) {
  153. // 解析URL
  154. $info = parse_url($url);
  155. $url = !empty($info['path'])?$info['path']:ACTION_NAME;
  156. if(isset($info['fragment'])) { // 解析锚点
  157. $anchor = $info['fragment'];
  158. if(false !== strpos($anchor,'?')) { // 解析参数
  159. list($anchor,$info['query']) = explode('?',$anchor,2);
  160. }
  161. if(false !== strpos($anchor,'@')) { // 解析域名
  162. list($anchor,$host) = explode('@',$anchor, 2);
  163. }
  164. }elseif(false !== strpos($url,'@')) { // 解析域名
  165. list($url,$host) = explode('@',$info['path'], 2);
  166. }
  167. // 解析子域名
  168. if(isset($host)) {
  169. $domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.'));
  170. }elseif($domain===true){
  171. $domain = $_SERVER['HTTP_HOST'];
  172. if(C('APP_SUB_DOMAIN_DEPLOY') ) { // 开启子域名部署
  173. $domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.');
  174. // '子域名'=>array('项目[/分组]');
  175. foreach (C('APP_SUB_DOMAIN_RULES') as $key => $rule) {
  176. if(false === strpos($key,'*') && 0=== strpos($url,$rule[0])) {
  177. $domain = $key.strstr($domain,'.'); // 生成对应子域名
  178. $url = substr_replace($url,'',0,strlen($rule[0]));
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. // 解析参数
  185. if(is_string($vars)) { // aaa=1&bbb=2 转换成数组
  186. parse_str($vars,$vars);
  187. }elseif(!is_array($vars)){
  188. $vars = array();
  189. }
  190. if(isset($info['query'])) { // 解析地址里面参数 合并到vars
  191. parse_str($info['query'],$params);
  192. $vars = array_merge($params,$vars);
  193. }
  194. // URL组装
  195. $depr = C('URL_PATHINFO_DEPR');
  196. if($url) {
  197. if(0=== strpos($url,'/')) {// 定义路由
  198. $route = true;
  199. $url = substr($url,1);
  200. if('/' != $depr) {
  201. $url = str_replace('/',$depr,$url);
  202. }
  203. }else{
  204. if('/' != $depr) { // 安全替换
  205. $url = str_replace('/',$depr,$url);
  206. }
  207. // 解析分组、模块和操作
  208. $url = trim($url,$depr);
  209. $path = explode($depr,$url);
  210. $var = array();
  211. $var[C('VAR_ACTION')] = !empty($path)?array_pop($path):ACTION_NAME;
  212. $var[C('VAR_MODULE')] = !empty($path)?array_pop($path):MODULE_NAME;
  213. if($maps = C('URL_ACTION_MAP')) {
  214. if(isset($maps[strtolower($var[C('VAR_MODULE')])])) {
  215. $maps = $maps[strtolower($var[C('VAR_MODULE')])];
  216. if($action = array_search(strtolower($var[C('VAR_ACTION')]),$maps)){
  217. $var[C('VAR_ACTION')] = $action;
  218. }
  219. }
  220. }
  221. if($maps = C('URL_MODULE_MAP')) {
  222. if($module = array_search(strtolower($var[C('VAR_MODULE')]),$maps)){
  223. $var[C('VAR_MODULE')] = $module;
  224. }
  225. }
  226. if(C('URL_CASE_INSENSITIVE')) {
  227. $var[C('VAR_MODULE')] = parse_name($var[C('VAR_MODULE')]);
  228. }
  229. if(!C('APP_SUB_DOMAIN_DEPLOY') && C('APP_GROUP_LIST')) {
  230. if(!empty($path)) {
  231. $group = array_pop($path);
  232. $var[C('VAR_GROUP')] = $group;
  233. }else{
  234. if(GROUP_NAME != C('DEFAULT_GROUP')) {
  235. $var[C('VAR_GROUP')]= GROUP_NAME;
  236. }
  237. }
  238. if(C('URL_CASE_INSENSITIVE') && isset($var[C('VAR_GROUP')])) {
  239. $var[C('VAR_GROUP')] = strtolower($var[C('VAR_GROUP')]);
  240. }
  241. }
  242. }
  243. }
  244. if(C('URL_MODEL') == 0) { // 普通模式URL转换
  245. $url = __APP__.'?'.http_build_query(array_reverse($var));
  246. if(!empty($vars)) {
  247. $vars = urldecode(http_build_query($vars));
  248. $url .= '&'.$vars;
  249. }
  250. }else{ // PATHINFO模式或者兼容URL模式
  251. if(isset($route)) {
  252. $url = __APP__.'/'.rtrim($url,$depr);
  253. }else{
  254. $url = __APP__.'/'.implode($depr,array_reverse($var));
  255. }
  256. if(!empty($vars)) { // 添加参数
  257. foreach ($vars as $var => $val){
  258. if('' !== trim($val)) $url .= $depr . $var . $depr . urlencode($val);
  259. }
  260. }
  261. if($suffix) {
  262. $suffix = $suffix===true?C('URL_HTML_SUFFIX'):$suffix;
  263. if($pos = strpos($suffix, '|')){
  264. $suffix = substr($suffix, 0, $pos);
  265. }
  266. if($suffix && '/' != substr($url,-1)){
  267. $url .= '.'.ltrim($suffix,'.');
  268. }
  269. }
  270. }
  271. if(isset($anchor)){
  272. $url .= '#'.$anchor;
  273. }
  274. if($domain) {
  275. $url = (is_ssl()?'https://':'http://').$domain.$url;
  276. }
  277. if($redirect) // 直接跳转URL
  278. redirect($url);
  279. else
  280. return $url;
  281. }
  282. /**
  283. * 渲染输出Widget
  284. * @param string $name Widget名称
  285. * @param array $data 传人的参数
  286. * @param boolean $return 是否返回内容
  287. * @param string $path Widget所在路径
  288. * @return void
  289. */
  290. function W($name, $data=array(), $return=false,$path='') {
  291. $class = $name . 'Widget';
  292. $path = empty($path) ? BASE_LIB_PATH : $path;
  293. require_cache($path . 'Widget/' . $class . '.class.php');
  294. if (!class_exists($class))
  295. throw_exception(L('_CLASS_NOT_EXIST_') . ':' . $class);
  296. $widget = Think::instance($class);
  297. $content = $widget->render($data);
  298. if ($return)
  299. return $content;
  300. else
  301. echo $content;
  302. }
  303. /**
  304. * 过滤器方法 引用传值
  305. * @param string $name 过滤器名称
  306. * @param string $content 要过滤的内容
  307. * @return void
  308. */
  309. function filter($name, &$content) {
  310. $class = $name . 'Filter';
  311. require_cache(BASE_LIB_PATH . 'Filter/' . $class . '.class.php');
  312. $filter = new $class();
  313. $content = $filter->run($content);
  314. }
  315. /**
  316. * 判断是否SSL协议
  317. * @return boolean
  318. */
  319. function is_ssl() {
  320. if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){
  321. return true;
  322. }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
  323. return true;
  324. }
  325. return false;
  326. }
  327. /**
  328. * URL重定向
  329. * @param string $url 重定向的URL地址
  330. * @param integer $time 重定向的等待时间(秒)
  331. * @param string $msg 重定向前的提示信息
  332. * @return void
  333. */
  334. function redirect($url, $time=0, $msg='') {
  335. //多行URL地址支持
  336. $url = str_replace(array("\n", "\r"), '', $url);
  337. if (empty($msg))
  338. $msg = "系统将在{$time}秒之后自动跳转到{$url}!";
  339. if (!headers_sent()) {
  340. // redirect
  341. if (0 === $time) {
  342. header('Location: ' . $url);
  343. } else {
  344. header("refresh:{$time};url={$url}");
  345. echo($msg);
  346. }
  347. exit();
  348. } else {
  349. $str = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
  350. if ($time != 0)
  351. $str .= $msg;
  352. exit($str);
  353. }
  354. }
  355. /**
  356. * 缓存管理
  357. * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
  358. * @param mixed $value 缓存值
  359. * @param mixed $options 缓存参数
  360. * @return mixed
  361. */
  362. function S($name,$value='',$options=null) {
  363. static $cache = '';
  364. if(is_array($options)){
  365. // 缓存操作的同时初始化
  366. $type = isset($options['type'])?$options['type']:'';
  367. $cache = Cache::getInstance($type,$options);
  368. $expire = is_numeric($options['expire'])?$options['expire']:NULL; //修复查询缓存无法设置过期时间
  369. }elseif(is_array($name)) { // 缓存初始化
  370. $type = isset($name['type'])?$name['type']:'';
  371. $cache = Cache::getInstance($type,$name);
  372. return $cache;
  373. }elseif(empty($cache)) { // 自动初始化
  374. $cache = Cache::getInstance();
  375. $expire = is_numeric($options)?$options:NULL; //默认快捷缓存设置过期时间
  376. }
  377. if(''=== $value){ // 获取缓存
  378. return $cache->get($name);
  379. }elseif(is_null($value)) { // 删除缓存
  380. return $cache->rm($name);
  381. }else { // 缓存数据
  382. //$expire = is_numeric($options)?$options:NULL; //原始语句
  383. return $cache->set($name, $value, $expire);
  384. }
  385. }
  386. // S方法的别名 已经废除 不再建议使用
  387. function cache($name,$value='',$options=null){
  388. return S($name,$value,$options);
  389. }
  390. /**
  391. * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
  392. * @param string $name 缓存名称
  393. * @param mixed $value 缓存值
  394. * @param string $path 缓存路径
  395. * @return mixed
  396. */
  397. function F($name, $value='', $path=DATA_PATH) {
  398. static $_cache = array();
  399. $filename = $path . $name . '.php';
  400. if ('' !== $value) {
  401. if (is_null($value)) {
  402. // 删除缓存
  403. return false !== strpos($name,'*')?array_map("unlink", glob($filename)):unlink($filename);
  404. } else {
  405. // 缓存数据
  406. $dir = dirname($filename);
  407. // 目录不存在则创建
  408. if (!is_dir($dir))
  409. mkdir($dir,0755,true);
  410. $_cache[$name] = $value;
  411. return file_put_contents($filename, strip_whitespace("<?php\treturn " . var_export($value, true) . ";?>"));
  412. }
  413. }
  414. if (isset($_cache[$name]))
  415. return $_cache[$name];
  416. // 获取缓存数据
  417. if (is_file($filename)) {
  418. $value = include $filename;
  419. $_cache[$name] = $value;
  420. } else {
  421. $value = false;
  422. }
  423. return $value;
  424. }
  425. /**
  426. * 取得对象实例 支持调用类的静态方法
  427. * @param string $name 类名
  428. * @param string $method 方法名,如果为空则返回实例化对象
  429. * @param array $args 调用参数
  430. * @return object
  431. */
  432. function get_instance_of($name, $method='', $args=array()) {
  433. static $_instance = array();
  434. $identify = empty($args) ? $name . $method : $name . $method . to_guid_string($args);
  435. if (!isset($_instance[$identify])) {
  436. if (class_exists($name)) {
  437. $o = new $name();
  438. if (method_exists($o, $method)) {
  439. if (!empty($args)) {
  440. $_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
  441. } else {
  442. $_instance[$identify] = $o->$method();
  443. }
  444. }
  445. else
  446. $_instance[$identify] = $o;
  447. }
  448. else
  449. halt(L('_CLASS_NOT_EXIST_') . ':' . $name);
  450. }
  451. return $_instance[$identify];
  452. }
  453. /**
  454. * 根据PHP各种类型变量生成唯一标识号
  455. * @param mixed $mix 变量
  456. * @return string
  457. */
  458. function to_guid_string($mix) {
  459. if (is_object($mix) && function_exists('spl_object_hash')) {
  460. return spl_object_hash($mix);
  461. } elseif (is_resource($mix)) {
  462. $mix = get_resource_type($mix) . strval($mix);
  463. } else {
  464. $mix = serialize($mix);
  465. }
  466. return md5($mix);
  467. }
  468. /**
  469. * XML编码
  470. * @param mixed $data 数据
  471. * @param string $root 根节点名
  472. * @param string $item 数字索引的子节点名
  473. * @param string $attr 根节点属性
  474. * @param string $id 数字索引子节点key转换的属性名
  475. * @param string $encoding 数据编码
  476. * @return string
  477. */
  478. function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
  479. if(is_array($attr)){
  480. $_attr = array();
  481. foreach ($attr as $key => $value) {
  482. $_attr[] = "{$key}=\"{$value}\"";
  483. }
  484. $attr = implode(' ', $_attr);
  485. }
  486. $attr = trim($attr);
  487. $attr = empty($attr) ? '' : " {$attr}";
  488. $xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
  489. $xml .= "<{$root}{$attr}>";
  490. $xml .= data_to_xml($data, $item, $id);
  491. $xml .= "</{$root}>";
  492. return $xml;
  493. }
  494. /**
  495. * 数据XML编码
  496. * @param mixed $data 数据
  497. * @param string $item 数字索引时的节点名称
  498. * @param string $id 数字索引key转换为的属性名
  499. * @return string
  500. */
  501. function data_to_xml($data, $item='item', $id='id') {
  502. $xml = $attr = '';
  503. foreach ($data as $key => $val) {
  504. if(is_numeric($key)){
  505. $id && $attr = " {$id}=\"{$key}\"";
  506. $key = $item;
  507. }
  508. $xml .= "<{$key}{$attr}>";
  509. $xml .= (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
  510. $xml .= "</{$key}>";
  511. }
  512. return $xml;
  513. }
  514. /**
  515. * session管理函数
  516. * @param string|array $name session名称 如果为数组则表示进行session设置
  517. * @param mixed $value session值
  518. * @return mixed
  519. */
  520. function session($name,$value='') {
  521. $prefix = C('SESSION_PREFIX');
  522. if(is_array($name)) { // session初始化 在session_start 之前调用
  523. if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
  524. if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
  525. session_id($_REQUEST[C('VAR_SESSION_ID')]);
  526. }elseif(isset($name['id'])) {
  527. session_id($name['id']);
  528. }
  529. ini_set('session.auto_start', 0);
  530. if(isset($name['name'])) session_name($name['name']);
  531. if(isset($name['path'])) session_save_path($name['path']);
  532. if(isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']);
  533. if(isset($name['expire'])) ini_set('session.gc_maxlifetime', $name['expire']);
  534. if(isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
  535. if(isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies']?1:0);
  536. if(isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']);
  537. if(isset($name['cache_expire'])) session_cache_expire($name['cache_expire']);
  538. if(isset($name['type'])) C('SESSION_TYPE',$name['type']);
  539. if(C('SESSION_TYPE')) { // 读取session驱动
  540. $class = 'Session'. ucwords(strtolower(C('SESSION_TYPE')));
  541. // 检查驱动类
  542. if(require_cache(EXTEND_PATH.'Driver/Session/'.$class.'.class.php')) {
  543. $hander = new $class();
  544. $hander->execute();
  545. }else {
  546. // 类没有定义
  547. throw_exception(L('_CLASS_NOT_EXIST_').': ' . $class);
  548. }
  549. }
  550. // 启动session
  551. if(C('SESSION_AUTO_START')) session_start();
  552. }elseif('' === $value){
  553. if(0===strpos($name,'[')) { // session 操作
  554. if('[pause]'==$name){ // 暂停session
  555. session_write_close();
  556. }elseif('[start]'==$name){ // 启动session
  557. session_start();
  558. }elseif('[destroy]'==$name){ // 销毁session
  559. $_SESSION = array();
  560. session_unset();
  561. session_destroy();
  562. }elseif('[regenerate]'==$name){ // 重新生成id
  563. session_regenerate_id();
  564. }
  565. }elseif(0===strpos($name,'?')){ // 检查session
  566. $name = substr($name,1);
  567. if($prefix) {
  568. return isset($_SESSION[$prefix][$name]);
  569. }else{
  570. return isset($_SESSION[$name]);
  571. }
  572. }elseif(is_null($name)){ // 清空session
  573. if($prefix) {
  574. unset($_SESSION[$prefix]);
  575. }else{
  576. $_SESSION = array();
  577. }
  578. }elseif($prefix){ // 获取session
  579. return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;
  580. }else{
  581. return isset($_SESSION[$name])?$_SESSION[$name]:null;
  582. }
  583. }elseif(is_null($value)){ // 删除session
  584. if($prefix){
  585. unset($_SESSION[$prefix][$name]);
  586. }else{
  587. unset($_SESSION[$name]);
  588. }
  589. }else{ // 设置session
  590. if($prefix){
  591. if (!is_array($_SESSION[$prefix])) {
  592. $_SESSION[$prefix] = array();
  593. }
  594. $_SESSION[$prefix][$name] = $value;
  595. }else{
  596. $_SESSION[$name] = $value;
  597. }
  598. }
  599. }
  600. /**
  601. * Cookie 设置、获取、删除
  602. * @param string $name cookie名称
  603. * @param mixed $value cookie值
  604. * @param mixed $options cookie参数
  605. * @return mixed
  606. */
  607. function cookie($name, $value='', $option=null) {
  608. // 默认设置
  609. $config = array(
  610. 'prefix' => C('COOKIE_PREFIX'), // cookie 名称前缀
  611. 'expire' => C('COOKIE_EXPIRE'), // cookie 保存时间
  612. 'path' => C('COOKIE_PATH'), // cookie 保存路径
  613. 'domain' => C('COOKIE_DOMAIN'), // cookie 有效域名
  614. );
  615. // 参数设置(会覆盖黙认设置)
  616. if (!is_null($option)) {
  617. if (is_numeric($option))
  618. $option = array('expire' => $option);
  619. elseif (is_string($option))
  620. parse_str($option, $option);
  621. $config = array_merge($config, array_change_key_case($option));
  622. }
  623. // 清除指定前缀的所有cookie
  624. if (is_null($name)) {
  625. if (empty($_COOKIE))
  626. return;
  627. // 要删除的cookie前缀,不指定则删除config设置的指定前缀
  628. $prefix = empty($value) ? $config['prefix'] : $value;
  629. if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
  630. foreach ($_COOKIE as $key => $val) {
  631. if (0 === stripos($key, $prefix)) {
  632. setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
  633. unset($_COOKIE[$key]);
  634. }
  635. }
  636. }
  637. return;
  638. }
  639. $name = $config['prefix'] . $name;
  640. if ('' === $value) {
  641. if(isset($_COOKIE[$name])){
  642. $value = $_COOKIE[$name];
  643. if(0===strpos($value,'think:')){
  644. $value = substr($value,6);
  645. return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
  646. }else{
  647. return $value;
  648. }
  649. }else{
  650. return null;
  651. }
  652. } else {
  653. if (is_null($value)) {
  654. setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
  655. unset($_COOKIE[$name]); // 删除指定cookie
  656. } else {
  657. // 设置cookie
  658. if(is_array($value)){
  659. $value = 'think:'.json_encode(array_map('urlencode',$value));
  660. }
  661. $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
  662. setcookie($name, $value, $expire, $config['path'], $config['domain']);
  663. $_COOKIE[$name] = $value;
  664. }
  665. }
  666. }
  667. /**
  668. * 加载动态扩展文件
  669. * @return void
  670. */
  671. function load_ext_file() {
  672. // 加载自定义外部文件
  673. if(C('LOAD_EXT_FILE')) {
  674. $files = explode(',',C('LOAD_EXT_FILE'));
  675. foreach ($files as $file){
  676. $file = COMMON_PATH.$file.'.php';
  677. if(is_file($file)) include $file;
  678. }
  679. }
  680. // 加载自定义的动态配置文件
  681. if(C('LOAD_EXT_CONFIG')) {
  682. $configs = C('LOAD_EXT_CONFIG');
  683. if(is_string($configs)) $configs = explode(',',$configs);
  684. foreach ($configs as $key=>$config){
  685. $file = CONF_PATH.$config.'.php';
  686. if(is_file($file)) {
  687. is_numeric($key)?C(include $file):C($key,include $file);
  688. }
  689. }
  690. }
  691. }
  692. /**
  693. * 获取客户端IP地址
  694. * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
  695. * @return mixed
  696. */
  697. function get_client_ip($type = 0) {
  698. $type = $type ? 1 : 0;
  699. static $ip = NULL;
  700. if ($ip !== NULL) return $ip[$type];
  701. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  702. $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  703. $pos = array_search('unknown',$arr);
  704. if(false !== $pos) unset($arr[$pos]);
  705. $ip = trim($arr[0]);
  706. }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
  707. $ip = $_SERVER['HTTP_CLIENT_IP'];
  708. }elseif (isset($_SERVER['REMOTE_ADDR'])) {
  709. $ip = $_SERVER['REMOTE_ADDR'];
  710. }
  711. // IP地址合法验证
  712. $long = sprintf("%u",ip2long($ip));
  713. $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
  714. return $ip[$type];
  715. }
  716. /**
  717. * 发送HTTP状态
  718. * @param integer $code 状态码
  719. * @return void
  720. */
  721. function send_http_status($code) {
  722. static $_status = array(
  723. // Success 2xx
  724. 200 => 'OK',
  725. // Redirection 3xx
  726. 301 => 'Moved Permanently',
  727. 302 => 'Moved Temporarily ', // 1.1
  728. // Client Error 4xx
  729. 400 => 'Bad Request',
  730. 403 => 'Forbidden',
  731. 404 => 'Not Found',
  732. // Server Error 5xx
  733. 500 => 'Internal Server Error',
  734. 503 => 'Service Unavailable',
  735. );
  736. if(isset($_status[$code])) {
  737. header('HTTP/1.1 '.$code.' '.$_status[$code]);
  738. // 确保FastCGI模式下正常
  739. header('Status:'.$code.' '.$_status[$code]);
  740. }
  741. }
  742. // 过滤表单中的表达式
  743. function filter_exp(&$value){
  744. if (in_array(strtolower($value),array('exp','or'))){
  745. $value .= ' ';
  746. }
  747. }