<?php

/*
	XiunoPHP 4.0 只是定义了一些函数和全局变量，方便使用，并没有要求如何组织代码。
	采用静态语言编程风格，有利于 Zend 引擎的编译和 OPCache 缓存，支持 PHP7
	1. 禁止使用 eval(), 正则表达式 e 修饰符
	2. 尽量避免 autoload
	3. 尽量避免 $$var 多重变量
	4. 尽量避免 PHP 高级特性 __call __set __get 等魔术方法，不利于错误排查
	5. 尽量采用函数封装功能，通过前缀区分模块
*/

!defined('DEBUG') AND define('DEBUG', 1); // 1: 开发模式， 2: 线上调试：日志记录，0: 关闭
!defined('APP_PATH') AND define('APP_PATH', './');
!defined('XIUNOPHP_PATH') AND define('XIUNOPHP_PATH', dirname(__FILE__).'/');

function_exists('ini_set') AND ini_set('display_errors', DEBUG ? '1' : '0');
error_reporting(DEBUG ? E_ALL : 0);
version_compare(PHP_VERSION, '5.3.0', '<') AND set_magic_quotes_runtime(0);
$get_magic_quotes_gpc = get_magic_quotes_gpc();
$starttime = microtime(1);
$time = time();

// 头部，判断是否运行在命令行下
define('IN_CMD', !empty($_SERVER['SHELL']) || empty($_SERVER['REMOTE_ADDR']));
if(IN_CMD) {
	!isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] = '';
	!isset($_SERVER['REQUEST_URI']) AND $_SERVER['REQUEST_URI'] = '';
	!isset($_SERVER['REQUEST_METHOD']) AND $_SERVER['REQUEST_METHOD'] = 'GET';
} else {
	header("Content-type: text/html; charset=utf-8");
	//header("Cache-Control: max-age=0;"); // 手机返回的时候回导致刷新
	//header("Cache-Control: no-store;");
	//header("X-Powered-By: XiunoPHP 4.0");
}

// hook xiunophp_include_before.php

class db_mysql { public $conf = array(); public $rconf = array(); public $wlink = NULL; public $rlink = NULL; public $link = NULL; public $errno = 0; public $errstr = ''; public $sqls = array(); public $tablepre = ''; public $innodb_first = TRUE; public function __construct($conf) { $this->conf = $conf; $this->tablepre = $conf['master']['tablepre']; } public function connect() { $this->wlink = $this->connect_master(); $this->rlink = $this->connect_slave(); return $this->wlink && $this->rlink; } public function connect_master() { if($this->wlink) return $this->wlink; $conf = $this->conf['master']; if(!$this->wlink) $this->wlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); return $this->wlink; } public function connect_slave() { if($this->rlink) return $this->rlink; if(empty($this->conf['slaves'])) { if($this->wlink === NULL) $this->wlink = $this->connect_master(); $this->rlink = $this->wlink; $this->rconf = $this->conf['master']; } else { $n = array_rand($this->conf['slaves']); $conf = $this->conf['slaves'][$n]; $this->rconf = $conf; $this->rlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); } return $this->rlink; } public function real_connect($host, $user, $password, $name, $charset = '', $engine = '') { $link = @mysql_connect($host, $user, $password); if(!$link) { $this->error(mysql_errno(), '连接数据库服务器失败:'.mysql_error()); return FALSE; } if(!mysql_select_db($name, $link)) { $this->error(mysql_errno(), '选择数据库失败:'.mysql_error()); return FALSE; } $charset AND $this->query("SET names $charset, sql_mode=''", $link); return $link; } public function sql_find_one($sql) { $query = $this->query($sql); if(!$query) return $query; $r = mysql_fetch_assoc($query); if($r === FALSE) { return NULL; } return $r; } public function sql_find($sql, $key = NULL) { $query = $this->query($sql); if(!$query) return $query; $arrlist = array(); while($arr = mysql_fetch_assoc($query)) { $key ? $arrlist[$arr[$key]] = $arr : $arrlist[] = $arr; } return $arrlist; } public function find($table, $cond = array(), $orderby = array(), $page = 1, $pagesize = 10, $key = '', $col = array()) { $page = max(1, $page); $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $offset = ($page - 1) * $pagesize; $cols = $col ? implode(',', $col) : '*'; return $this->sql_find("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT $offset,$pagesize", $key); } public function find_one($table, $cond = array(), $orderby = array(), $col = array()) { $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $cols = $col ? implode(',', $col) : '*'; return $this->sql_find_one("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT 1"); } public function query($sql, $link = NULL) { if(!$link) { if(!$this->rlink && !$this->connect_slave()) return FALSE;; $link = $this->link = $this->rlink; } $t1 = microtime(1); $query = mysql_query($sql, $link); $t2 = microtime(1); if($query === FALSE) $this->error(); if(count($this->sqls) < 1000) $this->sqls[] = substr($t2-$t1, 0, 6).' '.$sql; return $query; } public function exec($sql, $link = NULL) { if(!$link) { if(!$this->wlink && !$this->connect_master()) return FALSE; $link = $this->link = $this->wlink; } if(strtoupper(substr($sql, 0, 12) == 'CREATE TABLE')) { $fulltext = strpos($sql, 'FULLTEXT(') !== FALSE; $highversion = version_compare($this->version(), '5.6') >= 0; if(!$fulltext || ($fulltext && $highversion)) { $conf = $this->conf['master']; if(strtolower($conf['engine']) != 'myisam') { $this->innodb_first AND $this->is_support_innodb() AND $sql = str_ireplace('MyISAM', 'InnoDB', $sql); } } } $t1 = microtime(1); $query = mysql_query($sql, $this->wlink); $t2 = microtime(1); if(count($this->sqls) < 1000) $this->sqls[] = substr($t2-$t1, 0, 6).' '.$sql; if($query !== FALSE) { $pre = strtoupper(substr(trim($sql), 0, 7)); if($pre == 'INSERT ' || $pre == 'REPLACE') { return mysql_insert_id($this->wlink); } elseif($pre == 'UPDATE ' || $pre == 'DELETE ') { return mysql_affected_rows($this->wlink); } } else { $this->error(); } return $query; } public function count($table, $cond = array()) { $this->connect_slave(); if(empty($cond) && $this->rconf['engine'] == 'innodb') { $dbname = $this->rconf['name']; $sql = "SELECT TABLE_ROWS as num FROM information_schema.tables WHERE TABLE_SCHEMA='$dbname' AND TABLE_NAME='$table'"; } else { $cond = db_cond_to_sqladd($cond); $sql = "SELECT COUNT(*) AS num FROM `$table` $cond"; } $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['num']) : $arr; } public function maxid($table, $field, $cond = array()) { $sqladd = db_cond_to_sqladd($cond); $sql = "SELECT MAX($field) AS maxid FROM `$table` $sqladd"; $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['maxid']) : $arr; } public function truncate($table) { return $this->exec("TRUNCATE $table"); } public function close() { $r = mysql_close($this->wlink); if($this->wlink != $this->rlink) { $r = mysql_close($this->rlink); } return $r; } public function version() { $r = $this->sql_find_one("SELECT VERSION() AS v"); return $r['v']; } public function error($errno = 0, $errstr = '') { $this->errno = $errno ? $errno : ($this->link ? mysql_errno($this->link) : mysql_errno()); $this->errstr = $errstr ? $errstr : ($this->link ? mysql_error($this->link) : mysql_error()); DEBUG AND trigger_error('Database Error:'.$this->errstr); } public function is_support_innodb() { $arrlist = $this->sql_find('SHOW ENGINES'); $arrlist2 = arrlist_key_values($arrlist, 'Engine', 'Support'); return isset($arrlist2['InnoDB']) AND $arrlist2['InnoDB'] == 'YES'; } public function __destruct() { if($this->wlink) $this->wlink = NULL; if($this->rlink) $this->rlink = NULL; } } ?><?php
 class db_pdo_mysql { public $conf = array(); public $rconf = array(); public $wlink = NULL; public $rlink = NULL; public $link = NULL; public $errno = 0; public $errstr = ''; public $sqls = array(); public $tablepre = ''; public $innodb_first = TRUE; public function __construct($conf) { $this->conf = $conf; $this->tablepre = $conf['master']['tablepre']; } public function connect() { $this->wlink = $this->connect_master(); $this->rlink = $this->connect_slave(); return $this->wlink && $this->rlink; } public function connect_master() { if($this->wlink) return $this->wlink; $conf = $this->conf['master']; $this->wlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); return $this->wlink; } public function connect_slave() { if($this->rlink) return $this->rlink; if(empty($this->conf['slaves'])) { if($this->wlink === NULL) $this->wlink = $this->connect_master(); $this->rlink = $this->wlink; $this->rconf = $this->conf['master']; } else { $n = array_rand($this->conf['slaves']); $conf = $this->conf['slaves'][$n]; $this->rconf = $conf; $this->rlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); } return $this->rlink; } public function real_connect($host, $user, $password, $name, $charset = '', $engine = '') { if(strpos($host, ':') !== FALSE) { list($host, $port) = explode(':', $host); } else { $port = 3306; } try { $attr = array( PDO::ATTR_TIMEOUT => 5, ); $link = new PDO("mysql:host=$host;port=$port;dbname=$name", $user, $password, $attr); } catch (Exception $e) { $this->error($e->getCode(), '连接数据库服务器失败:'.$e->getMessage()); return FALSE; } $charset AND $link->query("SET names $charset, sql_mode=''"); return $link; } public function sql_find_one($sql) { $query = $this->query($sql); if(!$query) return $query; $query->setFetchMode(PDO::FETCH_ASSOC); $r = $query->fetch(); if($r === FALSE) { return NULL; } return $r; } public function sql_find($sql, $key = NULL) { $query = $this->query($sql); if(!$query) return $query; $query->setFetchMode(PDO::FETCH_ASSOC); $arrlist = $query->fetchAll(); $key AND $arrlist = arrlist_change_key($arrlist, $key); return $arrlist; } public function find($table, $cond = array(), $orderby = array(), $page = 1, $pagesize = 10, $key = '', $col = array()) { $page = max(1, $page); $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $offset = ($page - 1) * $pagesize; $cols = $col ? implode(',', $col) : '*'; return $this->sql_find("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT $offset,$pagesize", $key); } public function find_one($table, $cond = array(), $orderby = array(), $col = array()) { $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $cols = $col ? implode(',', $col) : '*'; return $this->sql_find_one("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT 1"); } public function query($sql) { if(!$this->rlink && !$this->connect_slave()) return FALSE; $link = $this->link = $this->rlink; try { $t1 = microtime(1); $query = $link->query($sql); $t2 = microtime(1); } catch (Exception $e) { $this->error($e->getCode(), $e->getMessage()); return FALSE; } if($query === FALSE) $this->error(); if(count($this->sqls) < 1000) $this->sqls[] = substr($t2-$t1, 0, 6).' '.$sql; return $query; } public function exec($sql) { if(!$this->wlink && !$this->connect_master()) return FALSE; $link = $this->link = $this->wlink; $n = 0; try { if(strtoupper(substr($sql, 0, 12) == 'CREATE TABLE')) { $fulltext = strpos($sql, 'FULLTEXT(') !== FALSE; $highversion = version_compare($this->version(), '5.6') >= 0; if(!$fulltext || ($fulltext && $highversion)) { $conf = $this->conf['master']; if(strtolower($conf['engine']) != 'myisam') { $this->innodb_first AND $this->is_support_innodb() AND $sql = str_ireplace('MyISAM', 'InnoDB', $sql); } } } $t1 = microtime(1); $n = $link->exec($sql); $t2 = microtime(1); } catch (Exception $e) { $this->error($e->getCode(), $e->getMessage()); return FALSE; } if(count($this->sqls) < 1000) $this->sqls[] = substr($t2-$t1, 0, 6).' '.$sql; if($n !== FALSE) { $pre = strtoupper(substr(trim($sql), 0, 7)); if($pre == 'INSERT ' || $pre == 'REPLACE') { return $this->last_insert_id(); } } else { $this->error(); } return $n; } public function count($table, $cond = array()) { $this->connect_slave(); if(empty($cond) && $this->rconf['engine'] == 'innodb') { $dbname = $this->rconf['name']; $sql = "SELECT TABLE_ROWS as num FROM information_schema.tables WHERE TABLE_SCHEMA='$dbname' AND TABLE_NAME='$table'"; } else { $cond = db_cond_to_sqladd($cond); $sql = "SELECT COUNT(*) AS num FROM `$table` $cond"; } $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['num']) : $arr; } public function maxid($table, $field, $cond = array()) { $sqladd = db_cond_to_sqladd($cond); $sql = "SELECT MAX($field) AS maxid FROM `$table` $sqladd"; $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['maxid']) : $arr; } public function truncate($table) { return $this->exec("TRUNCATE $table"); } public function last_insert_id() { return $this->wlink->lastinsertid(); } public function version() { $r = $this->sql_find_one("SELECT VERSION() AS v"); return $r['v']; } public function error($errno = 0, $errstr = '') { $error = $this->link ? $this->link->errorInfo() : array(0, $errno, $errstr); $this->errno = $errno ? $errno : (isset($error[1]) ? $error[1] : 0); $this->errstr = $errstr ? $errstr : (isset($error[2]) ? $error[2] : ''); } public function is_support_innodb() { $arrlist = $this->sql_find('SHOW ENGINES'); $arrlist2 = arrlist_key_values($arrlist, 'Engine', 'Support'); return isset($arrlist2['InnoDB']) AND $arrlist2['InnoDB'] == 'YES'; } public function close() { $this->wlink = NULL; $this->rlink = NULL; return TRUE; } public function __destruct() { if($this->wlink) $this->wlink = NULL; if($this->rlink) $this->rlink = NULL; } } ?><?php
 class db_pdo_sqlite { public $conf = array(); public $wlink = NULL; public $rlink = NULL; public $link = NULL; public $errno = 0; public $errstr = ''; public $tablepre = ''; public function __construct($conf) { $this->conf = $conf; $this->tablepre = $conf['master']['tablepre']; } public function connect() { $this->wlink = $this->connect_master(); $this->rlink = $this->connect_slave(); return $this->wlink && $this->rlink; } public function connect_master() { if($this->wlink) return $this->wlink; $conf = $this->conf['master']; $this->wlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); return $this->wlink; } public function connect_slave() { if($this->rlink) return $this->rlink; if(empty($this->conf['slaves'])) { if(!$this->wlink) $this->wlink = $this->connect_master(); $this->rlink = $this->wlink; } else { $n = array_rand($this->conf['slaves']); $conf = $this->conf['slaves'][$n]; $this->rlink = $this->real_connect($conf['host'], $conf['user'], $conf['password'], $conf['name'], $conf['charset'], $conf['engine']); } return $this->rlink; } public function real_connect($host, $user, $password, $name, $charset = '', $engine = '') { $sqlitedb = "sqlite:$host"; try { $attr = array( PDO::ATTR_TIMEOUT => 5, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); $link = new PDO($sqlitedb, $attr); } catch (Exception $e) { $this->error($e->getCode(), '连接数据库服务器失败:'.$e->getMessage()); return FALSE; } return $link; } public function sql_find_one($sql) { $query = $this->query($sql); if(!$query) return $query; $query->setFetchMode(PDO::FETCH_ASSOC); return $query->fetch(); } public function sql_find($sql, $key = NULL) { $query = $this->query($sql); if(!$query) return $query; $query->setFetchMode(PDO::FETCH_ASSOC); $arrlist = $query->fetchAll(); $key AND $arrlist = arrlist_change_key($arrlist, $key); return $arrlist; } public function find($table, $cond = array(), $orderby = array(), $page = 1, $pagesize = 10, $key = '', $col = array()) { $page = max(1, $page); $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $offset = ($page - 1) * $pagesize; $cols = $col ? implode(',', $col) : '*'; return $this->sql_find("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT $offset,$pagesize", $key); } public function find_one($table, $cond = array(), $orderby = array(), $col = array()) { $cond = db_cond_to_sqladd($cond); $orderby = db_orderby_to_sqladd($orderby); $cols = $col ? implode(',', $col) : '*'; return $this->sql_find_one("SELECT $cols FROM {$this->tablepre}$table $cond$orderby LIMIT 1"); } public function query($sql) { if(!$this->rlink && !$this->connect_slave()) return FALSE; $link = $this->link = $this->rlink; $query = $link->query($sql); if($query === FALSE) $this->error(); if(count($this->sqls) < 1000) $this->sqls[] = $sql; return $query; } public function exec($sql) { if(!$this->wlink && !$this->connect_master()) return FALSE; $link = $this->link = $this->wlink; $n = $link->exec($sql); if(count($this->sqls) < 1000) $this->sqls[] = $sql; if($n !== FALSE) { $pre = strtoupper(substr(trim($sql), 0, 7)); if($pre == 'INSERT ' || $pre == 'REPLACE') { return $this->last_insert_id(); } } else { $this->error(); } return $n; } public function count($table, $cond = array()) { $cond = db_cond_to_sqladd($cond); $sql = "SELECT COUNT(*) AS num FROM `$table` $cond"; $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['num']) : $arr; } public function maxid($table, $field, $cond = array()) { $sqladd = db_cond_to_sqladd($cond); $sql = "SELECT MAX($field) AS maxid FROM `$table` $sqladd"; $arr = $this->sql_find_one($sql); return !empty($arr) ? intval($arr['maxid']) : $arr; } public function truncate($table) { return $this->exec("TRUNCATE $table"); } public function last_insert_id() { return $this->wlink->lastinsertid(); } public function version() { $r = $this->sql_find_one("SELECT VERSION() AS v"); return $r['v']; } public function error($errno = 0, $errstr = '') { $error = $this->link ? $this->link->errorInfo() : array(0, 0, ''); $this->errno = $errno ? $errno : (isset($error[1]) ? $error[1] : 0); $this->errstr = $errstr ? $errstr : (isset($error[2]) ? $error[2] : ''); DEBUG AND trigger_error('Database Error:'.$this->errstr); } public function __destruct() { if($this->wlink) $this->wlink = NULL; if($this->rlink) $this->rlink = NULL; } } ?><?php
 class cache_apc { public $conf = array(); public $link = NULL; public $cachepre = ''; public $errno = 0; public $errstr = ''; public function __construct($conf = array()) { if(!function_exists('apc_fetch')) { return $this->error(-1, 'APC 扩展没有加载，请检查您的 PHP 版本'); } $this->conf = $conf; $this->cachepre = isset($conf['cachepre']) ? $conf['cachepre'] : 'pre_'; } public function connect() { } public function set($k, $v, $life) { return apc_store($k, $v, $life); } public function get($k) { $r = apc_fetch($k); if($r === FALSE) $r = NULL; return $r; } public function delete($k) { return apc_delete($k); } public function truncate() { return apc_clear_cache('user'); } public function error($errno = 0, $errstr = '') { $this->errno = $errno; $this->errstr = $errstr; DEBUG AND trigger_error('Cache Error:'.$this->errstr); } public function __destruct() { } } ?><?php
 class cache_memcached { public $conf = array(); public $link = NULL; public $cachepre = ''; public $errno = 0; public $errstr = ''; public $ismemcache = FALSE; public function __construct($conf = array()) { if(!extension_loaded('Memcache') && !extension_loaded('Memcached') ) { return $this->error(1, ' Memcached 扩展没有加载，请检查您的 PHP 版本'); } $this->conf = $conf; $this->cachepre = isset($conf['cachepre']) ? $conf['cachepre'] : 'pre_'; } public function connect() { $conf = $this->conf; if($this->link) return $this->link; if(extension_loaded('Memcache')) { $this->ismemcache = TRUE; $memcache = new Memcache; $r = $memcache->connect($conf['host'], $conf['port']); } elseif(extension_loaded('Memcached')) { $this->ismemcache = FALSE; $memcache = new Memcached; $r = $memcache->addserver($conf['host'], $conf['port']); } else { return $this->error(-1, 'Memcache 扩展不存在。'); } if(!$r) { return $this->error(-1, '连接 Memcached 服务器失败。'); } $this->link = $memcache; return $this->link; } public function set($k, $v, $life = 0) { if(!$this->link && !$this->connect()) return FALSE; if($this->ismemcache) { $r = $this->link->set($k, $v, 0, $life); } else { $r = $this->link->set($k, $v, $life); } return $r; } public function get($k) { if(!$this->link && !$this->connect()) return FALSE; $r = $this->link->get($k); return $r === FALSE ? NULL : $r; } public function delete($k) { if(!$this->link && !$this->connect()) return FALSE; return $this->link->delete($k); } public function truncate() { if(!$this->link && !$this->connect()) return FALSE; return $this->link->flush(); } public function error($errno = 0, $errstr = '') { $this->errno = $errno; $this->errstr = $errstr; DEBUG AND trigger_error('Cache Error:'.$this->errstr); } public function __destruct() { } } ?><?php
 class cache_mysql { public $conf = array(); public $db = NULL; public $link = NULL; public $table = 'cache'; public $cachepre = ''; public $errno = 0; public $errstr = ''; public function __construct($dbconf = array()) { if(is_object($dbconf['db'])) { $this->db = $dbconf['db']; } else { $this->conf = $dbconf; $this->db = db_new($dbconf); } $this->cachepre = isset($dbconf['cachepre']) ? $dbconf['cachepre'] : 'pre_'; } public function connect() { return db_connect($this->db); } public function set($k, $v, $life = 0) { $time = time(); $expiry = $life ? $time + $life : 0; $arr= array( 'k'=>$k, 'v'=>xn_json_encode($v), 'expiry'=>$expiry, ); $r = db_replace($this->table, $arr, $this->db); if($r === FALSE) { $this->errno = $this->db->errno; $this->errstr = $this->db->errstr; return FALSE; } return $r !== FALSE; } public function get($k) { $time = time(); $arr = db_find_one($this->table, array('k'=>$k), array(), array(), $this->db); if($arr === FALSE) { $this->errno = $this->db->errno; $this->errstr = $this->db->errstr; return FALSE; } if(!$arr) return NULL; if($arr['expiry'] && $time > $arr['expiry']) { db_delete($this->table, array('k'=>$k), $this->db); return NULL; } return xn_json_decode($arr['v'], 1); } public function delete($k) { $r = db_delete($this->table, array('k'=>$k), $this->db); if($r === FALSE) { $this->errno = $this->db->errno; $this->errstr = $this->db->errstr; return FALSE; } return empty($r) ? FALSE : TRUE; } public function truncate() { $r = db_truncate($this->table, $this->db); if($r === FALSE) { $this->errno = $this->db->errno; $this->errstr = $this->db->errstr; return FALSE; } return TRUE; } public function error($errno, $errstr) { $this->errno = $errno; $this->errstr = $errstr; } public function __destruct() { } } ?><?php
 class cache_redis { public $conf = array(); public $link = NULL; public $cachepre = ''; public $errno = 0; public $errstr = ''; public function __construct($conf = array()) { if(!extension_loaded('Redis')) { return $this->error(-1, ' Redis 扩展没有加载'); } $this->conf = $conf; $this->cachepre = isset($conf['cachepre']) ? $conf['cachepre'] : 'pre_'; } public function connect() { if($this->link) return $this->link; $redis = new Redis; $r = $redis->connect($this->conf['host'], $this->conf['port']); if(!$r) { return $this->error(-1, '连接 Redis 服务器失败。'); } $this->link = $redis; return $this->link; } public function set($k, $v, $life = 0) { if(!$this->link && !$this->connect()) return FALSE; $v = xn_json_encode($v); $r = $this->link->set($k, $v); $life AND $r AND $this->link->expire($k, $life); return $r; } public function get($k) { if(!$this->link && !$this->connect()) return FALSE; $r = $this->link->get($k); return $r === FALSE ? NULL : xn_json_decode($r); } public function delete($k) { if(!$this->link && !$this->connect()) return FALSE; return $this->link->del($k) ? TRUE : FALSE; } public function truncate() { if(!$this->link && !$this->connect()) return FALSE; return $this->link->flushdb(); } public function error($errno = 0, $errstr = '') { $this->errno = $errno; $this->errstr = $errstr; DEBUG AND trigger_error('Cache Error:'.$this->errstr); } public function __destruct() { } } ?><?php
 class cache_xcache { public $conf = array(); public $link = NULL; public $cachepre = ''; public $errno = 0; public $errstr = ''; public function __construct($conf = array()) { if(!function_exists('xcache_set')) { return $this->error(1, 'Xcache 扩展没有加载，请检查您的 PHP 版本'); } $this->conf = $conf; $this->cachepre = isset($conf['cachepre']) ? $conf['cachepre'] : 'pre_'; } public function connect() { } public function set($k, $v, $life) { return xcache_set($k, $v, $life); } public function get($k) { $r = xcache_get($k); if($r === FALSE) $r = NULL; return $r; } public function delete($k) { return xcache_unset($k); } public function truncate() { xcache_unset_by_prefix($this->cachepre); return TRUE; } public function error($errno = 0, $errstr = '') { $this->errno = $errno; $this->errstr = $errstr; DEBUG AND trigger_error('Cache Error:'.$this->errstr); } public function __destruct() { } } ?><?php
 class cache_yac { public $yac = NULL; public $cachepre = ''; public $errno = 0; public $errstr = ''; public function __construct($conf = array()) { if(!class_exists('Yac')) { return $this->error(1, 'yac 扩展没有加载，请检查您的 PHP 版本'); } $this->cachepre = isset($conf['cachepre']) ? $conf['cachepre'] : 'pre_'; $this->yac = new Yac($this->cachepre); } public function connect() { } public function set($k, $v, $life) { return $this->yac->set($k, $v, $life); } public function get($k) { $r = $this->yac->get($k); if($r === FALSE) $r = NULL; return $r; } public function delete($k) { return $this->yac->delete($k); } public function truncate() { $this->yac->flush(); return TRUE; } public function error($errno = 0, $errstr = '') { $this->errno = $errno; $this->errstr = $errstr; DEBUG AND trigger_error('Cache Error:'.$this->errstr); } public function __destruct() { } } ?><?php
 function db_new($dbconf) { global $errno, $errstr; if($dbconf) { switch ($dbconf['type']) { case 'mysql': $db = new db_mysql($dbconf['mysql']); break; case 'pdo_mysql': $db = new db_pdo_mysql($dbconf['pdo_mysql']); break; case 'pdo_sqlite': $db = new db_pdo_sqlite($dbconf['pdo_sqlite']); break; case 'pdo_mongodb': $db = new db_pdo_mongodb($dbconf['pdo_mongodb']); break; default: return xn_error(-1, 'Not suppported db type:'.$dbconf['type']); } if(!$db || ($db && $db->errstr)) { $errno = -1; $errstr = $db->errstr; return FALSE; } return $db; } return NULL; } function db_connect($d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; $r = $d->connect(); db_errno_errstr($r, $d); return $r; } function db_close($d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; $r = $d->close(); db_errno_errstr($r, $d); return $r; } function db_sql_find_one($sql, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $arr = $d->sql_find_one($sql); db_errno_errstr($arr, $d, $sql); return $arr; } function db_sql_find($sql, $key = NULL, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $arr = $d->sql_find($sql, $key); db_errno_errstr($arr, $d, $sql); return $arr; } function db_exec($sql, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; DEBUG AND xn_log($sql, 'db_exec'); $n = $d->exec($sql); db_errno_errstr($n, $d, $sql); return $n; } function db_count($table, $cond = array(), $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $r = $d->count($d->tablepre.$table, $cond); db_errno_errstr($r, $d); return $r; } function db_maxid($table, $field, $cond = array(), $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $r = $d->maxid($d->tablepre.$table, $field, $cond); db_errno_errstr($r, $d); return $r; } function db_create($table, $arr, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; return db_insert($table, $arr); } function db_insert($table, $arr, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $sqladd = db_array_to_insert_sqladd($arr); if(!$sqladd) return FALSE; return db_exec("INSERT INTO {$d->tablepre}$table $sqladd", $d); } function db_replace($table, $arr, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $sqladd = db_array_to_insert_sqladd($arr); if(!$sqladd) return FALSE; return db_exec("REPLACE INTO {$d->tablepre}$table $sqladd", $d); } function db_update($table, $cond, $update, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $condadd = db_cond_to_sqladd($cond); $sqladd = db_array_to_update_sqladd($update); if(!$sqladd) return FALSE; return db_exec("UPDATE {$d->tablepre}$table SET $sqladd $condadd", $d); } function db_delete($table, $cond, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $condadd = db_cond_to_sqladd($cond); return db_exec("DELETE FROM {$d->tablepre}$table $condadd", $d); } function db_truncate($table, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; return $d->truncate($d->tablepre.$table); } function db_read($table, $cond, $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; $sqladd = db_cond_to_sqladd($cond); $sql = "SELECT * FROM {$d->tablepre}$table $sqladd"; return db_sql_find_one($sql, $d); } function db_find($table, $cond = array(), $orderby = array(), $page = 1, $pagesize = 10, $key = '', $col = array(), $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; return $d->find($table, $cond, $orderby, $page, $pagesize, $key, $col); } function db_find_one($table, $cond = array(), $orderby = array(), $col = array(), $d = NULL) { $db = $_SERVER['db']; $d = $d ? $d : $db; if(!$d) return FALSE; return $d->find_one($table, $cond, $orderby, $col); } function db_errno_errstr($r, $d = NULL, $sql = '') { global $errno, $errstr; if($r === FALSE) { $errno = $d->errno; $errstr = db_errstr_safe($errno, $d->errstr); $s = 'SQL:'.$sql."\r\nerrno: ".$errno.", errstr: ".$errstr; xn_log($s, 'db_error'); } } function db_errstr_safe($errno, $errstr) { if(DEBUG) return $errstr; if($errno == 1049) { return '数据库名不存在，请手工创建'; } elseif($errno == 2003 ) { return '连接数据库服务器失败，请检查IP是否正确，或者防火墙设置'; } elseif($errno == 1024) { return '连接数据库失败'; } elseif($errno == 1045) { return '数据库账户密码错误'; } return $errstr; } function db_cond_to_sqladd($cond) { $s = ''; if(!empty($cond)) { $s = ' WHERE '; foreach($cond as $k=>$v) { if(!is_array($v)) { $v = (is_int($v) || is_float($v)) ? $v : "'".addslashes($v)."'"; $s .= "`$k`=$v AND "; } elseif(isset($v[0])) { $s .= '('; foreach ($v as $v1) { $v1 = (is_int($v1) || is_float($v1)) ? $v1 : "'".addslashes($v1)."'"; $s .= "`$k`=$v1 OR "; } $s = substr($s, 0, -4); $s .= ') AND '; } else { foreach($v as $k1=>$v1) { if($k1 == 'LIKE') { $k1 = ' LIKE '; $v1="%$v1%"; } $v1 = (is_int($v1) || is_float($v1)) ? $v1 : "'".addslashes($v1)."'"; $s .= "`$k`$k1$v1 AND "; } } } $s = substr($s, 0, -4); } return $s; } function db_orderby_to_sqladd($orderby) { $s = ''; if(!empty($orderby)) { $s .= ' ORDER BY '; $comma = ''; foreach($orderby as $k=>$v) { $s .= $comma."`$k` ".($v == 1 ? ' ASC ' : ' DESC '); $comma = ','; } } return $s; } function db_array_to_update_sqladd($arr) { $s = ''; foreach($arr as $k=>$v) { $v = addslashes($v); $op = substr($k, -1); if($op == '+' || $op == '-') { $k = substr($k, 0, -1); $v = (is_int($v) || is_float($v)) ? $v : "'$v'"; $s .= "`$k`=$k$op$v,"; } else { $v = (is_int($v) || is_float($v)) ? $v : "'$v'"; $s .= "`$k`=$v,"; } } return substr($s, 0, -1); } function db_array_to_insert_sqladd($arr) { $s = ''; $keys = array(); $values = array(); foreach($arr as $k=>$v) { $k = addslashes($k); $v = addslashes($v); $keys[] = '`'.$k.'`'; $v = (is_int($v) || is_float($v)) ? $v : "'$v'"; $values[] = $v; } $keystr = implode(',', $keys); $valstr = implode(',', $values); $sqladd = "($keystr) VALUES ($valstr)"; return $sqladd; } ?><?php
 function cache_new($cacheconf) { if($cacheconf && !empty($cacheconf['enable'])) { switch ($cacheconf['type']) { case 'redis': $cache = new cache_redis($cacheconf['redis']); break; case 'memcached': $cache = new cache_memcached($cacheconf['memcached']); break; case 'pdo_mysql': case 'mysql': $cache = new cache_mysql($cacheconf['mysql']); break; case 'xcache': $cache = new cache_xcache($cacheconf['xcache']); break; case 'apc': $cache = new cache_apc($cacheconf['apc']); break; case 'yac': $cache = new cache_yac($cacheconf['yac']); break; default: return xn_error(-1, '不支持的 cache type:'.$cacheconf['type']); } return $cache; } return NULL; } function cache_get($k, $c = NULL) { $cache = $_SERVER['cache']; $c = $c ? $c : $cache; if(!$c) return FALSE; strlen($k) > 32 AND $k = md5($k); $k = $c->cachepre.$k; $r = $c->get($k); return $r; } function cache_set($k, $v, $life = 0, $c = NULL) { $cache = $_SERVER['cache']; $c = $c ? $c : $cache; if(!$c) return FALSE; strlen($k) > 32 AND $k = md5($k); $k = $c->cachepre.$k; $r = $c->set($k, $v, $life); return $r; } function cache_delete($k, $c = NULL) { $cache = $_SERVER['cache']; $c = $c ? $c : $cache; if(!$c) return FALSE; strlen($k) > 32 AND $k = md5($k); $k = $c->cachepre.$k; $r = $c->delete($k); return $r; } function cache_truncate($c = NULL) { $cache = $_SERVER['cache']; $c = $c ? $c : $cache; if(!$c) return FALSE; $r = $c->truncate(); return $r; } ?><?php
 function image_ext($filename) { return strtolower(substr(strrchr($filename, '.'), 1)); } function image_safe_name($filename, $dir) { $time = $_SERVER['time']; $s1 = substr($filename, 0, strrpos($filename, '.')); $s2 = substr(strrchr($filename, '.'), 1); $s1 = preg_replace('#\W#', '_', $s1); $s2 = preg_replace('#\W#', '_', $s2); if(is_file($dir."$s1.$s2")) { $newname = $s1.$time.rand(1, 1000).'.'.$s2; } else { $newname = "$s1.$s2"; } return $newname; } function image_thumb_name($filename) { return substr($filename, 0, strrpos($filename, '.')).'_thumb'.strrchr($filename, '.'); } function image_rand_name($k) { $time = $_SERVER['time']; return $time.'_'.rand(1000000000, 9999999999).'_'.$k; } function image_set_dir($id, $dir) { $id = sprintf("%09d", $id); $s1 = substr($id, 0, 3); $s2 = substr($id, 3, 3); $dir = $dir."$s1/$s2"; !is_dir($dir) && mkdir($dir, 0777, TRUE); return "$s1/$s2"; } function image_get_dir($id) { $id = sprintf("%09d", $id); $s1 = substr($id, 0, 3); $s2 = substr($id, 3, 3); return "$s1/$s2"; } function image_thumb($sourcefile, $destfile, $forcedwidth = 80, $forcedheight = 80) { $return = array('filesize'=>0, 'width'=>0, 'height'=>0); $destext = image_ext($destfile); if(!in_array($destext, array('gif', 'jpg', 'bmp', 'png'))) { return $return; } $imginfo = getimagesize($sourcefile); $src_width = $imginfo[0]; $src_height = $imginfo[1]; if($src_width == 0 || $src_height == 0) { return $return; } if(!function_exists('imagecreatefromjpeg')) { copy($sourcefile, $destfile); $return = array('filesize'=>filesize($destfile), 'width'=>$src_width, 'height'=>$src_height); return $return; } $src_scale = $src_width / $src_height; $des_scale = $forcedwidth / $forcedheight; if($src_width <= $forcedwidth && $src_height <= $forcedheight) { $des_width = $src_width; $des_height = $src_height; } elseif($src_scale >= $des_scale) { $des_width = ($src_width >= $forcedwidth) ? $forcedwidth : $src_width; $des_height = $des_width / $src_scale; $des_height = ($des_height >= $forcedheight) ? $forcedheight : $des_height; } else { $des_height = ($src_height >= $forcedheight) ? $forcedheight : $src_height; $des_width = $des_height * $src_scale; $des_width = ($des_width >= $forcedwidth) ? $forcedwidth : $des_width; } switch ($imginfo['mime']) { case 'image/jpeg': $img_src = imagecreatefromjpeg($sourcefile); !$img_src && $img_src = imagecreatefromgif($sourcefile); break; case 'image/gif': $img_src = imagecreatefromgif($sourcefile); !$img_src && $img_src = imagecreatefromjpeg($sourcefile); break; case 'image/png': $img_src = imagecreatefrompng($sourcefile); break; case 'image/wbmp': $img_src = imagecreatefromwbmp($sourcefile); break; default : return $return; } if(!$img_src) return $return; $img_dst = imagecreatetruecolor($des_width, $des_height); imagefill($img_dst, 0, 0 , 0xFFFFFF); imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, $des_width, $des_height, $src_width, $src_height); $conf = _SERVER('conf'); $tmppath = isset($conf['tmp_path']) ? $conf['tmp_path'] : ini_get('upload_tmp_dir').'/'; $tmppath == '/' AND $tmppath = './tmp/'; $tmpfile = $tmppath.md5($destfile).'.tmp'; switch($destext) { case 'jpg': imagejpeg($img_dst, $tmpfile, 90); break; case 'gif': imagegif($img_dst, $tmpfile); break; case 'png': imagepng($img_dst, $tmpfile); break; } $r = array('filesize'=>filesize($tmpfile), 'width'=>$des_width, 'height'=>$des_height);; copy($tmpfile, $destfile); is_file($tmpfile) && unlink($tmpfile); imagedestroy($img_dst); return $r; } function image_clip($sourcefile, $destfile, $clipx, $clipy, $clipwidth, $clipheight) { $getimgsize = getimagesize($sourcefile); if(empty($getimgsize)) { return 0; } else { $imgwidth = $getimgsize[0]; $imgheight = $getimgsize[1]; if($imgwidth == 0 || $imgheight == 0) { return 0; } } if(!function_exists('imagecreatefromjpeg')) { copy($sourcefile, $destfile); return filesize($destfile); } switch($getimgsize[2]) { case 1 : $imgcolor = imagecreatefromgif($sourcefile); break; case 2 : $imgcolor = imagecreatefromjpeg($sourcefile); break; case 3 : $imgcolor = imagecreatefrompng($sourcefile); break; } if(!$imgcolor) return 0; $img_dst = imagecreatetruecolor($clipwidth, $clipheight); imagefill($img_dst, 0, 0 , 0xFFFFFF); imagecopyresampled($img_dst, $imgcolor, 0, 0, $clipx, $clipy, $imgwidth, $imgheight, $imgwidth, $imgheight); $conf = _SERVER('conf'); $tmppath = isset($conf['tmp_path']) ? $conf['tmp_path'] : ini_get('upload_tmp_dir').'/'; $tmppath == '/' AND $tmppath = './tmp/'; $tmpfile = $tmppath.md5($destfile).'.tmp'; imagejpeg($img_dst, $tmpfile, 100); $n = filesize($tmpfile); copy($tmpfile, $destfile); is_file($tmpfile) && @unlink($tmpfile); return $n; } function image_clip_thumb($sourcefile, $destfile, $forcedwidth = 80, $forcedheight = 80) { $getimgsize = getimagesize($sourcefile); if(empty($getimgsize)) { return 0; } else { $src_width = $getimgsize[0]; $src_height = $getimgsize[1]; if($src_width == 0 || $src_height == 0) { return 0; } } $src_scale = $src_width / $src_height; $des_scale = $forcedwidth / $forcedheight; if($src_width <= $forcedwidth && $src_height <= $forcedheight) { $des_width = $src_width; $des_height = $src_height; $n = image_clip($sourcefile, $destfile, 0, 0, $des_width, $des_height); return filesize($destfile); } elseif($src_scale >= $des_scale) { $des_height = $src_height; $des_width = $src_height / $des_scale; $n = image_clip($sourcefile, $destfile, 0, 0, $des_width, $des_height); if($n <= 0) return 0; $r = image_thumb($destfile, $destfile, $forcedwidth, $forcedheight); return $r['filesize']; } else { $des_width = $src_width; $des_height = $src_width / $des_scale; $n = image_clip($sourcefile, $destfile, 0, 0, $des_width, $des_height); if($n <= 0) return 0; $r = image_thumb($destfile, $destfile, $forcedwidth, $forcedheight); return $r['filesize']; } } function image_safe_thumb($sourcefile, $id, $ext, $dir1, $forcedwidth, $forcedheight, $randomname = 0) { $time = $_SERVER['time']; $ip = $_SERVER['ip']; $dir2 = image_set_dir($id, $dir1); $filename = $randomname ? md5(rand(0, 1000000000).$time.$ip).$ext : $id.$ext; $filepath = "$dir1$dir2/$filename"; $arr = image_thumb($sourcefile, $filepath, $forcedwidth, $forcedheight); $arr['fileurl'] = "$dir2/$filename"; return $arr; } ?><?php
 function array_value($arr, $key, $default = '') { return isset($arr[$key]) ? $arr[$key] : $default; } function array_filter_empty($arr) { foreach($arr as $k=>$v) { if(empty($v)) unset($arr[$k]); } return $arr; } function array_addslashes(&$var) { if(is_array($var)) { foreach($var as $k=>&$v) { array_addslashes($v); } } else { $var = addslashes($var); } return $var; } function array_stripslashes(&$var) { if(is_array($var)) { foreach($var as $k=>&$v) { array_stripslashes($v); } } else { $var = stripslashes($var); } return $var; } function array_htmlspecialchars(&$var) { if(is_array($var)) { foreach($var as $k=>&$v) { array_htmlspecialchars($v); } } else { $var = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $var); } return $var; } function array_trim(&$var) { if(is_array($var)) { foreach($var as $k=>&$v) { array_trim($v); } } else { $var = trim($var); } return $var; } function array_diff_value($arr1, $arr2) { foreach ($arr1 as $k=>$v) { if(isset($arr2[$k]) && $arr2[$k] == $v ) unset($arr1[$k]); } return $arr1; } function arrlist_multisort($arrlist, $col, $asc = TRUE) { $colarr = array(); foreach($arrlist as $k=>$arr) { $colarr[$k] = $arr[$col]; } $asc = $asc ? SORT_ASC : SORT_DESC; array_multisort($colarr, $asc, $arrlist); return $arrlist; } function arrlist_cond_orderby($arrlist, $cond = array(), $orderby = array(), $page = 1, $pagesize = 20) { $resultarr = array(); if(empty($arrlist)) return $arrlist; if($cond) { foreach($arrlist as $key=>$val) { $ok = TRUE; foreach($cond as $k=>$v) { if(!isset($val[$k])) { $ok = FALSE; break; } if(!is_array($v)) { if($val[$k] != $v) { $ok = FALSE; break; } } else { foreach($v as $k3=>$v3) { if( ($k3 == '>' && $val[$k] <= $v3) || ($k3 == '<' && $val[$k] >= $v3) || ($k3 == '>=' && $val[$k] < $v3) || ($k3 == '<=' && $val[$k] > $v3) || ($k3 == '==' && $val[$k] != $v3) || ($k3 == 'LIKE' && stripos($val[$k], $v3) === FALSE) ) { $ok = FALSE; break 2; } } } } if($ok) $resultarr[$key] = $val; } } else { $resultarr = $arrlist; } if($orderby) { $k = key($orderby); $v = current($orderby); $resultarr = arrlist_multisort($resultarr, $k, $v == 1); } $start = ($page - 1) * $pagesize; $resultarr = array_assoc_slice($resultarr, $start, $pagesize); return $resultarr; } function array_assoc_slice($arrlist, $start, $length = 0) { if(isset($arrlist[0])) return array_slice($arrlist, $start, $length); $keys = array_keys($arrlist); $keys2 = array_slice($keys, $start, $length); $retlist = array(); foreach($keys2 as $key) { $retlist[$key] = $arrlist[$key]; } return $retlist; } function arrlist_key_values($arrlist, $key, $value = NULL, $pre = '') { $return = array(); if($key) { foreach((array)$arrlist as $k=>$arr) { $return[$pre.$arr[$key]] = $value ? $arr[$value] : $k; } } else { foreach((array)$arrlist as $arr) { $return[] = $arr[$value]; } } return $return; } function arrlist_values($arrlist, $key) { if(!$arrlist) return array(); $return = array(); foreach($arrlist as &$arr) { $return[] = $arr[$key]; } return $return; } function arrlist_sum($arrlist, $key) { if(!$arrlist) return 0; $n = 0; foreach($arrlist as &$arr) { $n += $arr[$key]; } return $n; } function arrlist_max($arrlist, $key) { if(!$arrlist) return 0; $first = array_pop($arrlist); $max = $first[$key]; foreach($arrlist as &$arr) { if($arr[$key] > $max) { $max = $arr[$key]; } } return $max; } function arrlist_min($arrlist, $key) { if(!$arrlist) return 0; $first = array_pop($arrlist); $min = $first[$key]; foreach($arrlist as &$arr) { if($min > $arr[$key]) { $min = $arr[$key]; } } return $min; } function arrlist_change_key($arrlist, $key = '', $pre = '') { $return = array(); if(empty($arrlist)) return $return; foreach($arrlist as &$arr) { if(empty($key)) { $return[] = $arr; } else { $return[$pre.''.$arr[$key]] = $arr; } } return $return; } function arrlist_keep_keys($arrlist, $keys = array()) { !is_array($keys) AND $keys = array($keys); foreach($arrlist as &$v) { $arr = array(); foreach($keys as $key) { $arr[$key] = isset($v[$key]) ? $v[$key] : NULL; } $v = $arr; } return $arrlist; } function arrlist_chunk($arrlist, $key) { $r = array(); if(empty($arrlist)) return $r; foreach($arrlist as &$arr) { !isset($r[$arr[$key]]) AND $r[$arr[$key]] = array(); $r[$arr[$key]][] = $arr; } return $r; } ?><?php
 function xn_key($fromso = TRUE) { $conf = _SERVER('conf'); return ($fromso && function_exists('xiuno_key')) ? xiuno_key() : (isset($conf['auth_key']) ? $conf['auth_key'] : ''); } function xn_safe_key() { global $conf, $longip, $time, $useragent; $conf = _SERVER('conf'); $longip = _SERVER('longip'); $time = _SERVER('time'); $useragent = _SERVER('useragent'); $key = xn_key(); $behind = intval(substr($time, -2, 2)); $t = $behind > 80 ? $time - 20 : ($behind < 20 ? $time - 40 : $time); $front = substr($t, 0, -2); $key = md5($key.$useragent.$front); return $key; } function xn_encrypt($txt, $key = '') { empty($key) AND $key = xn_key(); $encrypt = function_exists('xiuno_encrypt') ? xiuno_encrypt($txt, $key) : xxtea_encrypt($txt, $key); return xn_urlencode(base64_encode($encrypt)); } function xn_decrypt($txt, $key = '') { empty($key) AND $key = xn_key(); $encrypt = base64_decode(xn_urldecode($txt)); $ret = function_exists('xiuno_decrypt') ? xiuno_decrypt($encrypt, $key) : xxtea_decrypt($encrypt, $key); return $ret; } if(!function_exists('xxtea_encrypt')) { function xxtea_long2str($v, $w) { $len = count($v); $n = ($len - 1) << 2; if ($w) { $m = $v[$len - 1]; if (($m < $n - 3) || ($m > $n)) return FALSE; $n = $m; } $s = array(); for ($i = 0; $i < $len; $i++) { $s[$i] = pack("V", $v[$i]); } if ($w) { return substr(join('', $s), 0, $n); } else { return join('', $s); } } function xxtea_str2long($s, $w) { $v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3)); $v = array_values($v); if ($w) { $v[count($v)] = strlen($s); } return $v; } function xxtea_int32($n) { while ($n >= 2147483648) $n -= 4294967296; while ($n <= -2147483649) $n += 4294967296; return (int)$n; } function xxtea_encrypt($str, $key) { if($str == '') return ''; $v = xxtea_str2long($str, TRUE); $k = xxtea_str2long($key, FALSE); if (count($k) < 4) { for ($i = count($k); $i < 4; $i++) { $k[$i] = 0; } } $n = count($v) - 1; $z = $v[$n]; $y = $v[0]; $delta = 0x9E3779B9; $q = floor(6 + 52 / ($n + 1)); $sum = 0; while (0 < $q--) { $sum = xxtea_int32($sum + $delta); $e = $sum >> 2 & 3; for ($p = 0; $p < $n; $p++) { $y = $v[$p + 1]; $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); $z = $v[$p] = xxtea_int32($v[$p] + $mx); } $y = $v[0]; $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); $z = $v[$n] = xxtea_int32($v[$n] + $mx); } return xxtea_long2str($v, FALSE); } function xxtea_decrypt($str, $key) { if($str == '') return ''; $v = xxtea_str2long($str, FALSE); $k = xxtea_str2long($key, FALSE); if(count($k) < 4) { for ($i = count($k); $i < 4; $i++) { $k[$i] = 0; } } $n = count($v) - 1; $z = $v[$n]; $y = $v[0]; $delta = 0x9E3779B9; $q = floor(6 + 52 / ($n + 1)); $sum = xxtea_int32($q * $delta); while ($sum != 0) { $e = $sum >> 2 & 3; for ($p = $n; $p > 0; $p--) { $z = $v[$p - 1]; $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); $y = $v[$p] = xxtea_int32($v[$p] - $mx); } $z = $v[$n]; $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); $y = $v[0] = xxtea_int32($v[0] - $mx); $sum = xxtea_int32($sum - $delta); } return xxtea_long2str($v, TRUE); } } ?><?php
 function xn_message($code, $message) { $ajax = $_SERVER['ajax']; echo $ajax ? xn_json_encode(array('code'=>$code, 'message'=>$message)) : $message; exit; } function xn_log_post_data() { $method = $_SERVER['method']; if($method != 'POST') return; $post = $_POST; isset($post['password']) AND $post['password'] = '******'; isset($post['password_new']) AND $post['password_new'] = '******'; isset($post['password_old']) AND $post['password_old'] = '******'; xn_log(xn_json_encode($post), 'post_data'); } function error_handle($errno, $errstr, $errfile, $errline) { if(DEBUG == 0) return FALSE; $time = $_SERVER['time']; $ajax = $_SERVER['ajax']; IN_CMD AND $errstr = str_replace('<br>', "\n", $errstr); $subject = "Error[$errno]: $errstr, File: $errfile, Line: $errline"; $message = array(); xn_log($subject, 'php_error'); $arr = debug_backtrace(); array_shift($arr); foreach($arr as $v) { $args = ''; if(!empty($v['args']) && is_array($v['args'])) foreach ($v['args'] as $v2) $args .= ($args ? ' , ' : '').(is_array($v2) ? 'array('.count($v2).')' : (is_object($v2) ? 'object' : $v2)); !isset($v['file']) AND $v['file'] = ''; !isset($v['line']) AND $v['line'] = ''; $message [] = "File: $v[file], Line: $v[line], $v[function]($args) "; } $txt = $subject."\r\n".implode("\r\n", $message); $html = $s = "<fieldset class=\"fieldset small notice\">
			<b>$subject</b>
			<div>".implode("<br>\r\n", $message)."</div>
		</fieldset>"; echo ($ajax || IN_CMD) ? $txt : $html; DEBUG == 2 AND xn_log($txt, 'debug_error'); return TRUE; } function xn_error($no, $str, $return = FALSE) { global $errno, $errstr; $errno = $no; $errstr = $str; return $return; } function param($key, $defval = '', $htmlspecialchars = TRUE, $addslashes = FALSE) { if(!isset($_REQUEST[$key]) || ($key === 0 && empty($_REQUEST[$key]))) { if(is_array($defval)) { return array(); } else { return $defval; } } $val = $_REQUEST[$key]; $val = param_force($val, $defval, $htmlspecialchars, $addslashes); return $val; } function param_word($key, $len = 32) { $s = param($key); $s = xn_safe_word($s, $len); return $s; } function param_base64($key, $len = 0) { $s = param($key, '', FALSE); if(empty($s)) return ''; $s = substr($s, strpos($s, ',') + 1); $s = base64_decode($s); $len AND $s = substr($s, 0, $len); return $s; } function param_json($key) { $s = param($key, '', FALSE); if(empty($s)) return ''; $arr = xn_json_decode($s); return $arr; } function param_url($key) { $s = param($key, '', FALSE); $arr = xn_urldecode($s); return $arr; } function xn_safe_word($s, $len) { $s = preg_replace('#\W+#', '', $s); $s = substr($s, 0, $len); return $s; } function param_force($val, $defval, $htmlspecialchars = TRUE, $addslashes = FALSE) { $get_magic_quotes_gpc = _SERVER('get_magic_quotes_gpc'); if(is_array($defval)) { $defval = empty($defval) ? '' : $defval[0]; if(is_array($val)) { foreach($val as &$v) { if(is_array($v)) { $v = $defval; } else { if(is_string($defval)) { $addslashes AND !$get_magic_quotes_gpc && $v = addslashes($v); !$addslashes AND $get_magic_quotes_gpc && $v = stripslashes($v); $htmlspecialchars AND $v = htmlspecialchars($v); } else { $v = intval($v); } } } } else { return array(); } } else { if(is_array($val)) { $val = $defval; } else { if(is_string($defval)) { $addslashes AND !$get_magic_quotes_gpc && $val = addslashes($val); !$addslashes AND $get_magic_quotes_gpc && $val = stripslashes($val); $htmlspecialchars AND $val = htmlspecialchars($val); } else { $val = intval($val); } } } return $val; } function lang($key, $arr = array()) { $lang = $_SERVER['lang']; if(!isset($lang[$key])) return 'lang['.$key.']'; $s = $lang[$key]; if(!empty($arr)) { foreach($arr as $k=>$v) { $s = str_replace('{'.$k.'}', $v, $s); } } return $s; } function jump($message, $url = '', $delay = 3) { $ajax = $_SERVER['ajax']; if($ajax) return $message; if(!$url) return $message; $url == 'back' AND $url = 'javascript:history.back()'; $htmladd = '<script>setTimeout(function() {window.location=\''.$url.'\'}, '.($delay * 1000).');</script>'; return '<a href="'.$url.'">'.$message.'</a>'.$htmladd; } function xn_strlen($s) { return mb_strlen($s, 'UTF-8'); } function xn_substr($s, $start, $len) { return mb_substr($s, $start, $len, 'UTF-8'); } function xn_txt_to_html($s) { $s = htmlspecialchars($s); $s = str_replace(" ", '&nbsp; ', $s); $s = str_replace("\t", ' &nbsp; &nbsp; &nbsp; &nbsp;', $s); $s = str_replace("\r\n", "\n", $s); $s = str_replace("\n", '<br>', $s); return $s; } function xn_urlencode($s) { $s = urlencode($s); $s = str_replace('_', '_5f', $s); $s = str_replace('-', '_2d', $s); $s = str_replace('.', '_2e', $s); $s = str_replace('+', '_2b', $s); $s = str_replace('=', '_3d', $s); $s = str_replace('%', '_', $s); return $s; } function xn_urldecode($s) { $s = str_replace('_', '%', $s); $s = urldecode($s); return $s; } function xn_json_encode($data, $pretty = FALSE, $level = 0) { if(version_compare(PHP_VERSION, '5.4.0') >= 0) { return json_encode($data, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE); } $tab = $pretty ? str_repeat("\t", $level) : ''; $tab2 = $pretty ? str_repeat("\t", $level + 1) : ''; $br = $pretty ? "\r\n" : ''; switch($type = gettype($data)) { case 'NULL': return 'null'; case 'boolean': return ($data ? 'true' : 'false'); case 'integer': case 'double': case 'float': return $data; case 'string': $data = '"'.str_replace(array('\\', '"'), array('\\\\', '\\"'), $data).'"'; $data = str_replace("\r", '\\r', $data); $data = str_replace("\n", '\\n', $data); $data = str_replace("\t", '\\t', $data); return $data; case 'object': $data = get_object_vars($data); case 'array': $output_index_count = 0; $output_indexed = array(); $output_associative = array(); foreach($data as $key => $value) { $output_indexed[] = xn_json_encode($value, $pretty, $level + 1); $output_associative[] = $tab2.'"'.$key.'":' . xn_json_encode($value, $pretty, $level + 1); if ($output_index_count !== NULL && $output_index_count++ !== $key) { $output_index_count = NULL; } } if($output_index_count !== NULL) { return '[' . implode(",$br", $output_indexed) . ']'; } else { return "{{$br}" . implode(",$br", $output_associative) . "{$br}{$tab}}"; } default: return ''; } } function xn_json_decode($json) { $json = trim($json, "\xEF\xBB\xBF"); $json = trim($json, "\xFE\xFF"); return json_decode($json, 1); } function pagination_tpl($url, $text, $active = '') { global $g_pagination_tpl; empty($g_pagination_tpl) AND $g_pagination_tpl = '<li class="page-item{active}"><a href="{url}" class="page-link">{text}</a></li>'; return str_replace(array('{url}', '{text}', '{active}'), array($url, $text, $active), $g_pagination_tpl); } function pagination($url, $totalnum, $page, $pagesize = 20) { $totalpage = ceil($totalnum / $pagesize); if($totalpage < 2) return ''; $page = min($totalpage, $page); $shownum = 5; $start = max(1, $page - $shownum); $end = min($totalpage, $page + $shownum); $right = $page + $shownum - $totalpage; $right > 0 && $start = max(1, $start -= $right); $left = $page - $shownum; $left < 0 && $end = min($totalpage, $end -= $left); $s = ''; $page != 1 && $s .= pagination_tpl(str_replace('{page}', $page-1, $url), '◀', ''); if($start > 1) $s .= pagination_tpl(str_replace('{page}', 1, $url),'1 '.($start > 2 ? '...' : '')); for($i=$start; $i<=$end; $i++) { $s .= pagination_tpl(str_replace('{page}', $i, $url), $i, $i == $page ? ' active' : ''); } if($end != $totalpage) $s .= pagination_tpl(str_replace('{page}', $totalpage, $url), ($totalpage - $end > 1 ? '...' : '').$totalpage); $page != $totalpage && $s .= pagination_tpl(str_replace('{page}', $page+1, $url), '▶'); return $s; } function pager($url, $totalnum, $page, $pagesize = 20) { $totalpage = ceil($totalnum / $pagesize); if($totalpage < 2) return ''; $page = min($totalpage, $page); $s = ''; $page > 1 AND $s .= '<li><a href="'.str_replace('{page}', $page-1, $url).'">上一页</a></li>'; $s .= " $page / $totalpage "; $totalnum >= $pagesize AND $page != $totalpage AND $s .= '<li><a href="'.str_replace('{page}', $page+1, $url).'">下一页</a></li>'; return $s; } function mid($n, $min, $max) { if($n < $min) return $min; if($n > $max) return $max; return $n; } function humandate($timestamp, $lan = array()) { $time = $_SERVER['time']; $lang = $_SERVER['lang']; static $custom_humandate = NULL; if($custom_humandate === NULL) $custom_humandate = function_exists('custom_humandate'); if($custom_humandate) return custom_humandate($timestamp, $lan); $seconds = $time - $timestamp; $lan = empty($lang) ? $lan : $lang; empty($lan) AND $lan = array( 'month_ago'=>'月前', 'day_ago'=>'天前', 'hour_ago'=>'小时前', 'minute_ago'=>'分钟前', 'second_ago'=>'秒前', ); if($seconds > 31536000) { return date('Y-n-j', $timestamp); } elseif($seconds > 2592000) { return floor($seconds / 2592000).$lan['month_ago']; } elseif($seconds > 86400) { return floor($seconds / 86400).$lan['day_ago']; } elseif($seconds > 3600) { return floor($seconds / 3600).$lan['hour_ago']; } elseif($seconds > 60) { return floor($seconds / 60).$lan['minute_ago']; } else { return $seconds.$lan['second_ago']; } } function humannumber($num) { static $custom_humannumber = NULL; if($custom_humannumber === NULL) $custom_humannumber = function_exists('custom_humannumber'); if($custom_humannumber) return custom_humannumber($num); $num > 100000 && $num = ceil($num / 10000).'万'; return $num; } function humansize($num) { static $custom_humansize = NULL; if($custom_humansize === NULL) $custom_humansize = function_exists('custom_humansize'); if($custom_humansize) return custom_humansize($num); if($num > 1073741824) { return number_format($num / 1073741824, 2, '.', '').'G'; } elseif($num > 1048576) { return number_format($num / 1048576, 2, '.', '').'M'; } elseif($num > 1024) { return number_format($num / 1024, 2, '.', '').'K'; } else { return $num.'B'; } } function ip() { $conf = _SERVER('conf'); $ip = '127.0.0.1'; if(empty($conf['cdn_on'])) { $ip = _SERVER('REMOTE_ADDR'); } else { if(isset($_SERVER['HTTP_CDN_SRC_IP'])) { $ip = $_SERVER['HTTP_CDN_SRC_IP']; } elseif(isset($_SERVER['HTTP_CLIENTIP'])) { $ip = $_SERVER['HTTP_CLIENTIP']; } elseif(isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; $arr = array_filter(explode(',', $ip)); $ip = trim(end($arr)); } else { $ip = _SERVER('REMOTE_ADDR'); } } return long2ip(ip2long($ip)); } function xn_log($s, $file = 'error') { if(DEBUG == 0 && strpos($file, 'error') === FALSE) return; $time = $_SERVER['time']; $ip = $_SERVER['ip']; $conf = _SERVER('conf'); $uid = intval(G('uid')); $day = date('Ym', $time); $mtime = date('Y-m-d H:i:s'); $url = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; $logpath = $conf['log_path'].$day; !is_dir($logpath) AND mkdir($logpath, 0777, true); $s = str_replace(array("\r\n", "\n", "\t"), ' ', $s); $s = "<?php exit;?>\t$mtime\t$ip\t$url\t$uid\t$s\r\n"; @error_log($s, 3, $logpath."/$file.php"); } function get__browser() { $browser = array( 'device'=>'pc', 'name'=>'chrome', 'version'=>30, ); $agent = _SERVER('HTTP_USER_AGENT'); if(strpos($agent, 'msie') !== FALSE || stripos($agent, 'trident') !== FALSE) { $browser['name'] = 'ie'; $browser['version'] = 8; preg_match('#msie\s*([\d\.]+)#is', $agent, $m); if(!empty($m[1])) { if(strpos($agent, 'compatible; msie 7.0;') !== FALSE) { $browser['version'] = 8; } else { $browser['version'] = intval($m[1]); } } else { preg_match('#Trident/([\d\.]+)#is', $agent, $m); if(!empty($m[1])) { $trident = intval($m[1]); $trident == 4 AND $browser['version'] = 8; $trident == 5 AND $browser['version'] = 9; $trident > 5 AND $browser['version'] = 10; } } } if(isset($_SERVER['HTTP_X_WAP_PROFILE']) || (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap") || stripos($agent, 'phone') || stripos($agent, 'mobile') || strpos($agent, 'ipod'))) { $browser['device'] = 'mobile'; } elseif(strpos($agent, 'pad') !== FALSE) { $browser['device'] = 'pad'; $browser['name'] = ''; $browser['version'] = ''; } else { $robots = array('bot', 'spider', 'slurp'); foreach($robots as $robot) { if(strpos($agent, $robot) !== FALSE) { $browser['name'] = 'robot'; return $browser; } } } return $browser; } function check_browser($browser) { if($browser['name'] == 'ie' && $browser['version'] < 8) { include _include(APP_PATH.'view/htm/browser.htm'); exit; } } function is_robot() { $agent = _SERVER('HTTP_USER_AGENT'); $robots = array('bot', 'spider', 'slurp'); foreach($robots as $robot) { if(strpos($agent, $robot) !== FALSE) { return TRUE; } } return FALSE; } function browser_lang() { $accept = _SERVER('HTTP_ACCEPT_LANGUAGE'); $accept = substr($accept, 0, strpos($accept, ';')); if(strpos($accept, 'ko-kr') !== FALSE) { return 'ko-kr'; } else { return 'zh-cn'; } } function http_get($url, $cookie = '', $timeout = 30, $times = 3) { if(substr($url, 0, 8) == 'https://') { return https_get($url, $cookie, $timeout, $times); } $arr = array( 'http' => array( 'method'=> 'GET', 'timeout' => $timeout ) ); $stream = stream_context_create($arr); while($times-- > 0) { $s = file_get_contents($url, NULL, $stream, 0, 4096000); if($s !== FALSE) return $s; } return FALSE; } function http_post($url, $post = '', $cookie='', $timeout = 30, $times = 3) { if(substr($url, 0, 8) == 'https://') { return https_post($url, $post, $cookie, $timeout, $times); } is_array($post) AND $post = http_build_query($post); is_array($cookie) AND $cookie = http_build_query($cookie); $stream = stream_context_create(array('http' => array('header' => "Content-type: application/x-www-form-urlencoded\r\nx-requested-with: XMLHttpRequest\r\nCookie: $cookie\r\n", 'method' => 'POST', 'content' => $post, 'timeout' => $timeout))); while($times-- > 0) { $s = file_get_contents($url, NULL, $stream, 0, 4096000); if($s !== FALSE) return $s; } return FALSE; } function https_get($url, $cookie = '', $timeout = 30, $times = 1) { if(substr($url, 0, 7) == 'http://') { return http_get($url, $cookie, $timeout, $times); } return https_post($url, '', $cookie, $timeout, $times, 'GET'); } function https_post($url, $post = '', $cookie = '', $timeout = 30, $times = 1, $method = 'POST') { if(substr($url, 0, 7) == 'http://') { return http_post($url, $post, $cookie, $timeout, $times); } is_array($post) AND $post = http_build_query($post); is_array($cookie) AND $cookie = http_build_query($cookie); $w = stream_get_wrappers(); $allow_url_fopen = strtolower(ini_get('allow_url_fopen')); $allow_url_fopen = (empty($allow_url_fopen) || $allow_url_fopen == 'off') ? 0 : 1; if(extension_loaded('openssl') && in_array('https', $w) && $allow_url_fopen) { $stream = stream_context_create(array('http' => array('header' => "Content-type: application/x-www-form-urlencoded\r\nx-requested-with: XMLHttpRequest\r\nCookie: $cookie\r\n", 'method' => $method, 'content' => $post, 'timeout' => $timeout))); $s = file_get_contents($url, NULL, $stream, 0, 4096000); return $s; } elseif (!function_exists('curl_init')) { return xn_error(-1, 'server not installed curl.'); } $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 2); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded', 'x-requested-with: XMLHttpRequest')); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, _SERVER('HTTP_USER_AGENT')); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); if($method == 'POST') { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); } $header = array('Content-type: application/x-www-form-urlencoded', 'X-Requested-With: XMLHttpRequest'); if($cookie) { $header[] = "Cookie: $cookie"; } curl_setopt($ch, CURLOPT_HTTPHEADER, $header); (!ini_get('safe_mode') && !ini_get('open_basedir')) && curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); $data = curl_exec($ch); if(curl_errno($ch)) { return xn_error(-1, 'Errno'.curl_error($ch)); } if(!$data) { curl_close($ch); return ''; } list($header, $data) = explode("\r\n\r\n", $data); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($http_code == 301 || $http_code == 302) { $matches = array(); preg_match('/Location:(.*?)\n/', $header, $matches); $url = trim(array_pop($matches)); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, false); $data = curl_exec($ch); } curl_close($ch); return $data; } function http_multi_get($urls) { $data = array(); if(!function_exists('curl_multi_init')) { foreach($urls as $k=>$url) { $data[$k] = https_get($url); } return $data; } $multi_handle = curl_multi_init(); foreach ($urls as $i => $url) { $conn[$i] = curl_init($url); curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1); $timeout = 3; curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($conn[$i], CURLOPT_FOLLOWLOCATION, 1); curl_multi_add_handle($multi_handle, $conn[$i]); } do { $mrc = curl_multi_exec($multi_handle, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while($active and $mrc == CURLM_OK) { if(curl_multi_select($multi_handle) != - 1) { do { $mrc = curl_multi_exec($multi_handle, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } foreach($urls as $i => $url) { $data[$i] = curl_multi_getcontent($conn[$i]); curl_multi_remove_handle($multi_handle, $conn[$i]); curl_close($conn[$i]); } return $data; } function file_replace_var($filepath, $replace = array(), $pretty = FALSE) { $ext = file_ext($filepath); if($ext == 'php') { $arr = include $filepath; $arr = array_merge($arr, $replace); $s = "<?php\r\nreturn ".var_export($arr, true).";\r\n?>"; file_backup($filepath); $r = file_put_contents_try($filepath, $s); $r != strlen($s) ? file_backup_restore($filepath) : file_backup_unlink($filepath); return $r; } elseif($ext == 'js' || $ext == 'json') { $s = file_get_contents_try($filepath); $arr = xn_json_decode($s); if(empty($arr)) return FALSE; $arr = array_merge($arr, $replace); $s = xn_json_encode($arr, $pretty); file_backup($filepath); $r = file_put_contents_try($filepath, $s); $r != strlen($s) ? file_backup_restore($filepath) : file_backup_unlink($filepath); return $r; } } function file_backname($filepath) { $dirname = dirname($filepath); $filepre = file_pre($filepath); $fileext = file_ext($filepath); $s = "$filepre.backup.$fileext"; return $s; } function is_backfile($filepath) { return strpos($filepath, '.backup.') !== FALSE; } function file_backup($filepath) { $backfile = file_backname($filepath); if(is_file($backfile)) return TRUE; $r = xn_copy($filepath, $backfile); clearstatcache(); return $r && filesize($backfile) == filesize($filepath); } function file_backup_restore($filepath) { $backfile = file_backname($filepath); $r = xn_copy($backfile, $filepath); clearstatcache(); $r && filesize($backfile) == filesize($filepath) && xn_unlink($backfile); return $r; } function file_backup_unlink($filepath) { $backfile = file_backname($filepath); $r = xn_unlink($backfile); return $r; } function file_get_contents_try($file, $times = 3) { while($times-- > 0) { $fp = fopen($file, 'rb'); if($fp) { $size = filesize($file); if($size == 0) return ''; $s = fread($fp, $size); fclose($fp); return $s; } else { sleep(1); } } return FALSE; } function file_put_contents_try($file, $s, $times = 3) { while($times-- > 0) { $fp = fopen($file, 'wb'); if($fp AND flock($fp, LOCK_EX)){ $n = fwrite($fp, $s); version_compare(PHP_VERSION, '5.3.2', '>=') AND flock($fp, LOCK_UN); fclose($fp); clearstatcache(); return $n; } else { sleep(1); } } return FALSE; } function in_string($s, $str) { if(!$s || !$str) return FALSE; $s = ",$s,"; $str = ",$str,"; return strpos($str, $s) !== FALSE; } function move_upload_file($srcfile, $destfile) { $r = xn_copy($srcfile, $destfile); return $r; } function file_ext($filename, $max = 16) { $ext = strtolower(substr(strrchr($filename, '.'), 1)); $ext = xn_urlencode($ext); strlen($ext) > $max AND $ext = substr($ext, 0, $max); if(!preg_match('#^\w+$#', $ext)) $ext = 'attach'; return $ext; } function file_pre($filename, $max = 32) { return substr($filename, 0, strrpos($filename, '.')); } function file_name($path) { return substr($path, strrpos($path, '/') + 1); } function http_url_path() { $port = _SERVER('SERVER_PORT'); $host = _SERVER('HTTP_HOST'); $https = strtolower(_SERVER('HTTPS', 'off')); $proto = strtolower(_SERVER('HTTP_X_FORWARDED_PROTO')); $path = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/')); $http = (($port == 443) || $proto == 'https' || ($https && $https != 'off')) ? 'https' : 'http'; return "$http://$host$path/"; } function xn_url_parse($request_url) { $request_url = str_replace('/?', '/', $request_url); $arr = parse_url($request_url); $q = array_value($arr, 'path'); $pos = strrpos($q, '/'); $pos === FALSE && $pos = -1; $q = substr($q, $pos + 1); $sep = strpos($q, '?') === FALSE ? strpos($q, '&') : FALSE; if($sep !== FALSE) { $front = substr($q, 0, $sep); $behind = substr($q, $sep + 1); } else { $front = $q; $behind = ''; } if(substr($front, -4) == '.htm') $front = substr($front, 0, -4); $r = $front ? (array)explode('-', $front) : array(); $arr1 = $arr2 = $arr3 = array(); $behind AND parse_str($behind, $arr1); if(!empty($arr['query'])) { parse_str($arr['query'], $arr2); } else { !empty($_GET) AND $_GET = array(); } $arr3 = $arr1 + $arr2; if($arr3) { count($arr3) != count($_GET) AND $_GET = $arr3; } else { !empty($_GET) AND $_GET = array(); } $r += $arr3; $_SERVER['REQUEST_URI_NO_PATH'] = substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/') + 1); $conf = _SERVER('conf'); if(!empty($conf['url_rewrite_on']) && $conf['url_rewrite_on'] == 3) { $r = xn_url_parse_path_format($_SERVER['REQUEST_URI']) + $r; } isset($r[0]) AND $r[0] == 'index.php' AND $r[0] = 'index'; return $r; } function xn_url_add_arg($url, $k, $v) { $pos = strpos($url, '.htm'); if($pos === FALSE) { return strpos($url, '?') === FALSE ? $url."&$k=$v" : $url."?$k=$v"; } else { return substr($url, 0, $pos).'-'.$v.substr($url, $pos); } } function xn_url_parse_path_format($s) { $get = array(); substr($s, 0, 1) == '/' AND $s = substr($s, 1); $arr = explode('/', $s); $get = $arr; $last = array_pop($arr); if(strpos($last, '?') !== FALSE) { $get = $arr; $arr1 = explode('?', $last); parse_str($arr1[1], $arr2); $get[] = $arr1[0]; $get = array_merge($get, $arr2); } return $get; } function glob_recursive($pattern, $flags = 0) { $files = glob($pattern, $flags); foreach(glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) { $files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags)); } return $files; } function rmdir_recusive($dir, $keepdir = 0) { if($dir == '/' || $dir == './' || $dir == '../') return FALSE; if(!is_dir($dir)) return FALSE; substr($dir, -1) != '/' AND $dir .= '/'; $files = glob($dir.'*'); foreach(glob($dir.'.*') as $v) { if(substr($v, -1) != '.' && substr($v, -2) != '..') $files[] = $v; } $filearr = $dirarr = array(); if($files) { foreach($files as $file) { if(is_dir($file)) { $dirarr[] = $file; } else { $filearr[] = $file; } } } if($filearr) { foreach($filearr as $file) { xn_unlink($file); } } if($dirarr) { foreach($dirarr as $file) { rmdir_recusive($file); } } if(!$keepdir) xn_rmdir($dir); return TRUE; } function xn_copy($src, $dest) { $r = is_file($src) ? copy($src, $dest) : FALSE; return $r; } function xn_mkdir($dir, $mod = NULL, $recusive = NULL) { $r = !is_dir($dir) ? mkdir($dir, $mod, $recusive) : FALSE; return $r; } function xn_rmdir($dir) { $r = is_dir($dir) ? rmdir($dir) : FALSE; return $r; } function xn_unlink($file) { $r = is_file($file) ? unlink($file) : FALSE; return $r; } function xn_filemtime($file) { return is_file($file) ? filemtime($file) : 0; } function xn_set_dir($id, $dir = './') { $id = sprintf("%09d", $id); $s1 = substr($id, 0, 3); $s2 = substr($id, 3, 3); $dir1 = $dir.$s1; $dir2 = $dir."$s1/$s2"; !is_dir($dir1) && mkdir($dir1, 0777); !is_dir($dir2) && mkdir($dir2, 0777); return "$s1/$s2"; } function xn_get_dir($id) { $id = sprintf("%09d", $id); $s1 = substr($id, 0, 3); $s2 = substr($id, 3, 3); return "$s1/$s2"; } function copy_recusive($src, $dst) { substr($src, -1) == '/' AND $src = substr($src, 0, -1); substr($dst, -1) == '/' AND $dst = substr($dst, 0, -1); $dir = opendir($src); !is_dir($dst) AND mkdir($dst); while(FALSE !== ($file = readdir($dir))) { if(($file != '.') && ($file != '..')) { if(is_dir($src . '/' . $file)) { copy_recusive($src.'/'.$file,$dst.'/'.$file); } else { xn_copy($src.'/'.$file, $dst.'/'.$file); } } } closedir($dir); } function xn_rand($n = 16) { $str = '23456789ABCDEFGHJKMNPQRSTUVWXYZ'; $len = strlen($str); $return = ''; for($i=0; $i<$n; $i++) { $r = mt_rand(1, $len); $return .= $str[$r - 1]; } return $return; } function xn_is_writable($file) { if(PHP_OS != 'WINNT') { return is_writable($file); } else { if(is_file($file)) { $fp = fopen($file, 'a+'); if(!$fp) return FALSE; fclose($fp); return TRUE; } elseif(is_dir($file)) { $tmpfile = $file.uniqid().'.tmp'; $r = touch($tmpfile); if(!$r) return FALSE; if(!is_file($tmpfile)) return FALSE; xn_unlink($tmpfile); return TRUE; } else { return FALSE; } } } function xn_shutdown_handle() { } function xn_debug_info() { $db = $_SERVER['db']; $starttime = $_SERVER['starttime']; $s = ''; if(DEBUG > 1) { $s .= '<fieldset class="fieldset small debug break-all">'; $s .= '<p>Processed Time:'.(microtime(1) - $starttime).'</p>'; if(IN_CMD) { foreach($db->sqls as $sql) { $s .= "$sql\r\n"; } } else { $s .= "\r\n<ul>\r\n"; foreach($db->sqls as $sql) { $s .= "<li>$sql</li>\r\n"; } $s .= "</ul>\r\n"; $s .= '_REQUEST:<br>'; $s .= xn_txt_to_html(print_r($_REQUEST, 1)); if(!empty($_SESSION)) { $s .= '_SESSION:<br>'; $s .= xn_txt_to_html(print_r($_SESSION, 1)); } $s .= ''; } $s .= '</fieldset>'; } return $s; } function base64_decode_file_data($data) { if(substr($data, 0, 5) == 'data:') { $data = substr($data, strpos($data, ',') + 1); } $data = base64_decode($data); return $data; } function http_404() { header('HTTP/1.1 404 Not Found'); header('Status: 404 Not Found'); echo '<h1>404 Not Found</h1>'; exit; } function http_403() { header('HTTP/1.1 403 Forbidden'); header('Status: 403 Forbidden'); echo '<h1>403 Forbidden</h1>'; exit; } function http_location($url) { header('Location:'.$url); exit; } function http_referer() { $len = strlen(http_url_path()); $referer = param('referer'); empty($referer) AND $referer = _SERVER('HTTP_REFERER'); $referer2 = substr($referer, $len); if(strpos($referer, url('user-login')) !== FALSE || strpos($referer, url('user-logout')) !== FALSE || strpos($referer, url('user-create')) !== FALSE) { $referer = './'; } if(!preg_match('#^\\??[\w\-/]+\.htm$#', $referer2) && !preg_match('#^[\w\/]*$#', $referer2)) { $referer = './'; } return $referer; } function str_push($str, $v, $sep = '_') { if(empty($str)) return $v; if(strpos($str, $v.$sep) === FALSE) { return $str.$sep.$v; } return $str; } function y2f($rmb) { $rmb = floor($rmb * 10 * 10); return $rmb; } function f2y($rmb, $round = 'float') { $rmb = floor($rmb * 100) / 10000; if($round == 'float') { $rmb = number_format($rmb, 2, '.', ''); } elseif($round == 'round') { $rmb = round($rmb); } elseif ($round == 'ceil') { $rmb = ceil($rmb); } elseif ($round == 'floor') { $rmb = floor($rmb); } return $rmb; } function _GET($k, $def = NULL) { return isset($_GET[$k]) ? $_GET[$k] : $def; } function _POST($k, $def = NULL) { return isset($_POST[$k]) ? $_POST[$k] : $def; } function _COOKIE($k, $def = NULL) { return isset($_COOKIE[$k]) ? $_COOKIE[$k] : $def; } function _REQUEST($k, $def = NULL) { return isset($_REQUEST[$k]) ? $_REQUEST[$k] : $def; } function _ENV($k, $def = NULL) { return isset($_ENV[$k]) ? $_ENV[$k] : $def; } function _SERVER($k, $def = NULL) { return isset($_SERVER[$k]) ? $_SERVER[$k] : $def; } function GLOBALS($k, $def = NULL) { return isset($GLOBALS[$k]) ? $GLOBALS[$k] : $def; } function G($k, $def = NULL) { return isset($GLOBALS[$k]) ? $GLOBALS[$k] : $def; } function _SESSION($k, $def = NULL) { global $g_session; return isset($_SESSION[$k]) ? $_SESSION[$k] : (isset($g_session[$k]) ? $g_session[$k] : $def); }

// hook xiunophp_include_after.php

empty($conf) AND $conf = array('db'=>array(), 'cache'=>array(), 'tmp_path'=>'./', 'log_path'=>'./', 'timezone'=>'Asia/Shanghai');
empty($conf['tmp_path']) AND $conf['tmp_path'] = ini_get('upload_tmp_dir');
empty($conf['log_path']) AND $conf['log_path'] = './';

$ip = ip();
$longip = ip2long($ip);
$longip < 0 AND $longip = sprintf("%u", $longip); // fix 32 位 OS 下溢出的问题
$useragent = _SERVER('HTTP_USER_AGENT');

// 语言包变量
!isset($lang) AND $lang = array();

// 全局的错误，非多线程下很方便。
$errno = 0;
$errstr = '';

// error_handle
// register_shutdown_function('xn_shutdown_handle');
DEBUG AND set_error_handler('error_handle', -1);
empty($conf['timezone']) AND $conf['timezone'] = 'Asia/Shanghai';
date_default_timezone_set($conf['timezone']);

// 超级全局变量
!empty($_SERVER['HTTP_X_REWRITE_URL']) AND $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
!isset($_SERVER['REQUEST_URI']) AND $_SERVER['REQUEST_URI'] = '';
$_SERVER['REQUEST_URI'] = str_replace('/index.php?', '/', $_SERVER['REQUEST_URI']); // 兼容 iis6
$_REQUEST = array_merge($_COOKIE, $_POST, $_GET, xn_url_parse($_SERVER['REQUEST_URI']));

// IP 地址
!isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] = '';
!isset($_SERVER['SERVER_ADDR']) AND $_SERVER['SERVER_ADDR'] = '';

// $_SERVER['REQUEST_METHOD'] === 'PUT' ? @parse_str(file_get_contents('php://input', false , null, -1 , $_SERVER['CONTENT_LENGTH']), $_PUT) : $_PUT = array(); // 不需要支持 PUT
$ajax = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower(trim($_SERVER['HTTP_X_REQUESTED_WITH'])) == 'xmlhttprequest') || param('ajax');
$method = $_SERVER['REQUEST_METHOD'];



// 保存到超级全局变量，防止冲突被覆盖。
$_SERVER['starttime'] = $starttime;
$_SERVER['time'] = $time;
$_SERVER['ip'] = $ip;
$_SERVER['longip'] = $longip;
$_SERVER['useragent'] = $useragent;
$_SERVER['conf'] = $conf;
$_SERVER['lang'] = $lang;
$_SERVER['errno'] = $errno;
$_SERVER['errstr'] = $errstr;
$_SERVER['method'] = $method;
$_SERVER['ajax'] = $ajax;
$_SERVER['get_magic_quotes_gpc'] = $get_magic_quotes_gpc;




// 初始化 db cache，这里并没有连接，在获取数据的时候会自动连接。
$db = !empty($conf['db']) ? db_new($conf['db']) : NULL;
//$db AND $db->errno AND xn_message(-1, $db->errstr); // 安装的时候检测过了，不必每次都检测。但是要考虑环境移植。

$conf['cache']['mysql']['db'] = $db; // 这里直接传 $db，复用 $db；如果传配置文件，会产生新链接。
$cache = !empty($conf['cache']) ? cache_new($conf['cache']) : NULL;
unset($conf['cache']['mysql']['db']); // 用完清除，防止保存到配置文件
//$cache AND $cache->errno AND xn_message(-1, $cache->errstr);

// 对 key 进行安全保护，Xiuno 专用扩展
!empty($conf) AND (function_exists('xiuno_key') ? ($conf['auth_key'] = xiuno_key()) : NULL);

$_SERVER['db'] = $db;
$_SERVER['cache'] = $cache;

?>