<?php

#.begin
#.mod[SleX.Core]
class xCore {
	const ERR_BASE = 0x100;
	const ERR_INVALID_LIB = 0x101;
	const ERR_INVALID_EXE = 0x102;
	const ERR_EXIT_FAILED = 0x103;
	const ERR_INVALID_FILE = 0x104;
	const ERR_EXE_FAILED = 0x105;
	protected static $s_Inst;
	protected $m_krlMods;
	/**
	 * @var xStrUtils
	 */
	public $strutils;
	/**
	 * @var xUtils
	 */
	public $utils;
	protected function __construct() {}
	/**
	 * Start the SleX.PHP.
	 */
	public static function start() {
		if (!self::$s_Inst) {
			mb_internal_encoding(SLEX_ENCODING);
			unset($_ENV);
			self::$s_Inst = $_ENV = new xCore();
			register_shutdown_function(array($_ENV, 'shutdown'));
			#set_error_handler(array('xError', 'errorHandler'));
			#set_exception_handler(array('xError', 'exceptionHandler'));
			$_ENV->configure('slex.i.php', '_SLEX');
			$_ENV->execLite('kernel_init');
			$_ENV->m_krlMods = array();
			if (class_exists('coms_init_sxExe'))
				$_ENV->execLite('coms_init');
		}
		return self::$s_Inst;
	}
	/**
	 * Register a uniniting function.
	 * @param string $uninitFunc
	 */
	public function regUninit($uninitFunc) {
		if (is_callable($uninitFunc, false, $t)) {
			$this->m_krlMods[] = array($uninitFunc, $t);
			return true;
		}
		return false;
	}
	/**
	 * Read static file.
	 * @param string $filename
	 */
	public function readStatic($filename) {
		$tmp = substr(@file_get_contents ($filename), 36);
		if (!$tmp || !($tmp = @unserialize($tmp)))
			throw new xError($filename, xError::ERR_BAD_FILE);
		return $tmp;
	}
	public function writeStatic($fileName, $datCache) {
		if (file_put_contents($fileName, SLEX_STATIC_CONF_HEAD.serialize($datCache)))
			return true;
		throw new xError($filename, xError::ERR_BAD_FILE);
		return false;
	}
	/**
	 * Handle all parameters into common PHP string.
	 */
	public function setSafeRequest() {
		$su = xStrUtils::getInst();
		if (get_magic_quotes_gpc())	{
			$su->deSlashes($_GET);
			$su->deSlashes($_POST);
			$su->deSlashes($_COOKIE);
			$su->deSlashes($_REQUEST);
		}
	}
	/**
	 * Check if it is visited by mobile.
	 * @return bool
	 */
	public function isMobile() {
		$uas = array('android','ucweb');
		$httpUserAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
		foreach($uas as $ua)
			if(strpos($httpUserAgent, $ua)!==false)
				return true;
		return false;
	}
	/**
	 * Boost the configure of SleX.PHP
	 */
	public function configure($conf, $confName) {
		global $$confName;
		$$confName = array();
		try {
			$$confName = $this->readStatic(__CONFS__.'cache/'.$conf);
		} catch (xError $e) {
			include __CONFS__.$conf;
			#$this->writeStatic(__CONFS__.'cache/'.$conf, $_SLEX);
		}
	}
	public function import($libName) {
		if (!file_exists(__EXTS__.$libName.'/lib.php'))
			throw new xError($libName, self::ERR_INVALID_LIB);
		include_once __EXTS__.$libName.'/lib.php';
		return true;
	}
	public function exec($exeName, $args = null, $path = __EXES__) {
		$clsName = $exeName.SLEX_EXE_SUFFIX;
		if (!class_exists($clsName)) {
			if (!file_exists($path.SLEX_EXE_PREFIX.$exeName.'.php'))
				throw new xError($exeName, self::ERR_INVALID_EXE);
			include_once $path.SLEX_EXE_PREFIX.$exeName.'.php';
		}
		return $this->execLite($exeName);
	}
	public function execLite($exeName, $args = null, $path = __EXES__) {
		$clsName = $exeName.SLEX_EXE_SUFFIX;
		if (class_exists($clsName)) {
			$obj = new $clsName;
			$obj->args = $args;
			if (method_exists($obj, 'main'))
				$result = $obj->main();
			else
				throw new xError($exeName, self::ERR_EXE_FAILED);
			if ($result) {
				if (method_exists($obj, 'onError'))
					return $obj->onError($result);
				else
					throw new xError($exeName, self::ERR_EXE_FAILED);
			}
			unset($obj);
			return $result;
		}
		return null;
	}
	public function shutdown($bQuit = false) {
		$i = count($this->m_krlMods);
		while ($i--)
			if (!call_user_func($this->m_krlMods[$i][0]))
				throw new xError($this->m_krlMods[$i][1], self::ERR_EXIT_FAILED);
		if ($bQuit)
			exit;
	}
	public function quitCrush() {
		header('HTTP/1.1 503');
		exit;
	}
	public function quitError() {
		header('HTTP/1.1 404');
		exit;
	}
}
#.mod[/SleX.Core]

#.mod[error]
class xError extends Exception {
	const ERR_RESERVED = 0x10000000;
	const ERR_BASED = 0x00;
	const ERR_UNKNOWN = 0x00;
	const ERR_BAD_ARGS = 0x01;
	const ERR_BAD_FILE = 0x02;
	const ERR_DUP = 0x03;
	const ERR_EXCEED = 0x04;
	const ERR_BAD_LINK = 0x05;
	const ERR_INVALID_OBJ = 0x06;
	public function __construct($info, $code) {
		parent::__construct($info, $code);
	}
	public static function errorHandler($errno, $errstr , $errfile, $errline,  $errcontext = false) {
		echo '<p>[SleX.PHP.Error: E'.$errno.'] <i>'.$errfile.' (#'.$errline.')</i>: <b>'.$errstr.'</b></p>';
		return true;
	}
	public static function exceptionHandler($e) {
		$info = $e->getTrace();
		$info = $info[0];
		if (isset($info['function']))
			$func = $info['function'];
		else 
			$func = '';
		if (isset($info['class']))
			$func = $info['class'].'::'.$func;
		echo '<p>[SleX.PHP.Exception'.($func?'.':'').$func.'] <i>'.$e->getFile().' (#'.$e->getLine().')</i>: <b>'.$e->getMessage().'</b></p>';
	}
}
#.mod[/error]

#.mod[global]
class xGbl {
	/**
	 * @var xMemcache
	 */
	public static $mmc;
	/**
	 * @var xMySQL
	 */
	public static $mysql;
	public static function init() {
		self::$mmc = xMemcache::getServ();
		self::$mysql = xMySQL::getServ();
	}
	public static function vars($name, $val = null, $action = 0) {
		static $gbl_vars = array();
		switch (func_num_args()) {
		case 1: return isset($gbl_vars[$name])? $gbl_vars[$name]: null;
		case 2: return ($gbl_vars[$name] = $val); break;
		case 3: {
			switch ($action) {
			case 1: unset($gbl_vars[$name]); break;
			case 2: return $gbl_vars;
			case 3: $gbl_vars = array(); break;
			default: return false;
			}
			return true;
		}
		default: return false;
		}
	}
}
#.mod[/global]

#.mod[Utils.Pages]
class xPages {
	protected function __construct() { }
	public static function makeList($page, $cnt) {
		$maxpage = (int)($cnt / 10) + ($cnt % 10 ? 1: 0);
		$min = $max = $page;
		if ($min > 5)
			$min -= 5;
		else
			$min = 1;
		
		if ($maxpage - $page >= 4)
			$max = $page + 4;
		else
			$max = $maxpage;
		if ($max - $min < 10) {
			if ($maxpage > 15 && $maxpage - $page < 4)
				$min = $maxpage - 9;
			if ($page <= 5)
				$max = $maxpage > 10? 10: $maxpage;
		}
		return array('to' => $max, 'from' => $min, 'cur' => $page, 'last' => $maxpage, 'first' => 1);
	}
	
	public static function makeHTML($xpage, $nhtml, $shtml, $ss = ' ... ') {
		$html = '';
		for($p = $xpage['from']; $p <= $xpage['to']; $p++) {
			if($p == $xpage['cur']) {
				$html .= str_replace('[p]', $p, $shtml);
			} else {
				$html .= str_replace('[p]', $p, $nhtml);
			}
		}
		if($xpage['from'] > $xpage['first']) {
			$html = str_replace('[p]', $info['first'], $nhtml) . $ss . $html;
		}
		if($xpage['to'] < $xpage['last']) {
			$html .= $ss . str_replace('[p]', $info['last'], $nhtml);
		}
		return $html;
	}
}
#.mod[/Utils.Pages]

#.mod[strutils]
class xStrUtils extends xISingleton {
	protected static $s_Instance;
	
	protected function __construct() {}
	public static function getInst() {
		if (!self::$s_Instance) 
			self::$s_Instance = new xStrUtils();
		return self::$s_Instance;
	}
	public function byte2Hex($i) {
		$s = '0123456789ABCDEF';
		return $s[($i & 0xF0) >> 4].$s[$i & 0xF];
	}
	public function randomString($length, $source = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
		$sourceLength = strlen($source);
		$temp = '';
		for ($i = $length; $i; $i--)
			$temp .= $source[rand(0, $sourceLength - 1)];
		return $temp;
	}
	public function deSlashes(&$str) {
		if (is_array($str))
			foreach ($str as $key => $v)
				$this->deSlashes($str[$key]);
		elseif (is_string($str))
			$str = stripslashes($str);
	}
	public function isIPv4($ip) {
		return preg_match(REXP_IPv4, $ip)? true: false;
	}
	public function isIPv6($ip) {
		return preg_match(REXP_IPv6, $ip)? true: false;
	}
	public function isIP($ip) {
		return ip2long($ip)===false? false: true;
	}
	public function isUsername($un) {
		return preg_match(REXP_USERNAME, $un)? true: false;
	}
	public function isEMail($email) {
		return preg_match(REXP_EMAIL, $email)? true: false;
	}
	public function isURL($url) {
		return preg_match(REXP_URL, $url)? true: false;
	}
	public function isInteger($i) {
		return preg_match(REXP_INT, $i)? true: false;
	}
	public function isID($id) {
		if ($this->isInteger($id.'') && $id > 0)
			return true;
		return false;
	}
	public function isHex($hex) {
		return preg_match(REXP_HEX, $hex)? true: false;
	}
	public function isFloat($f) {
		return preg_match(REXP_FLOAT, $f)? true: false;
	}
	public function isQQNum($qq) {
		return preg_match(REXP_QQ, $qq)? true: false;
	}
	public function isWord($w) {
		return preg_match(REXP_WORD, $w)? true: false;
	}
}
#.mod[/strutils]

#.mod[time]
define('TIMENOW', $_SERVER['REQUEST_TIME']);
class xTime {
	public static function now() {
		return $_SERVER['REQUEST_TIME'];
	}
	public static function today($timesrc = TIMENOW, $format = false) {
		global $_SLEX;
		return date($format? $format: $_SLEX['time']['format'], $timesrc);
	}
	public static function setTimeZone($tzone) {
		date_default_timezone_set('Etc/GMT'.($tzone>0?-$tzone:'+'.-$tzone));
	}
	public static function toSQL($unix = TIMENOW) {
		return 'FROM_UNIXTIME('.$unix.')';
	}
	public static function toUnix($sqlTime) {
		return strtotime($sqlTime);
	}
	public static function toUnixField($field) {
		return 'UNIX_TIMESTAMP(`'.$field.'`)';
	}
}
#.mod[/time]

#.mod[utilities]
class xUtils {
	protected static $s_Inst;
	
	protected function __construct() {}
	public static function getInst() {
		if (!self::$s_Inst) 
			self::$s_Inst = new xUtils();
		return self::$s_Inst;
	}
	public function setGlobal($name, $v) {
		global $$name;
		$$name = $v;
	}
	public function getGlobal($name) {
		global $$name;
		return $$name;
	}
	public function setArrayGlobal(&$arr, $keys = false, $prefix = '') {
		if ($keys === false)
			$keys = array_keys($arr);
		foreach ($keys as $key)
			if (is_string($key)) $this->setGlobal($prefix.$key, $arr[$key]);
	}
	public function verify($format, $objs) {
		$l = strlen($format);
		$s = xStrUtils::getInst();
		for ($i = 0; $i < $l; ++$i)
			switch ($format[$i]) {
			case 'e':
				if (!$s->isFloat($objs[$i]))
					return 1+$i;
				break;
			case 'n':
				if (!$s->isInteger($objs[$i]))
					return 1+$i;
				break;
			case 'r':
				if (!$s->isFloat($objs[$i]))
					return 1+$i;
				break;
			case 'i':
				if (!is_int($objs[$i]))
					return 1+$i;
				break;
			case 'f':
				if (!is_float($objs[$i]))
					return 1+$i;
				break;
			case 's':
				if (!is_string($objs[$i]))
					return 1+$i;
				break;
			case 'S':
				if (false !== @unserialize($objs[$i]))
					return 1+$i;
				break;
			default:
				break;
			}
		return true;
	}
}
#.mod[/utilities]

#.mod[memcache]
class xMemcache {
	protected $m_uQuery;
	protected $m_memcached;
	public $uExpires;
	public $bCompress;
	protected static $s_Inst;
	public function __construct($host = false, $port = false, $timeout = 30, $pconnect = false) {
		$this->m_uQuery = 0;
		$this->m_memcached = null;
		$this->bCompress = MC_DEF_COMPRESS;
		$this->uExpires = MC_DEF_EXPIRE;
	}
	public function __destruct() {
		if ($this->m_memcached)
			$this->m_memcached->close();
	}
	/**
	 * Start a Memcached Service
	 * @param string $service name of service.
	 * @return xMemcache
	 */
	public static function getServ($service = 'mmc') {
		global $_SLEX;
		if (isset(self::$s_Inst[$service]))
			return self::$s_Inst[$service];
		if (isset($_SLEX[$service]))
			$settings = $_SLEX[$service];
		else
			return null;
	
		$tmp = new xMemcache();
		if ($tmp->connect($settings['host'], $settings['port'], $settings['timeout'], $settings['pconnect']))
			return self::$s_Inst[$service] = $tmp;
		return null;
	}
	/**
	 * Stop a Memcached service.
	 * @param string $service name of service.
	 * @return bool return true if succeeded.
	 */
	public static function stopService($service) {
		if (!isset(self::$s_Inst[$service]))
			return false;
		self::$s_Inst[$service]->onServiceStop();
		unset(self::$s_Inst[$service]);
		return true;
	}
	protected function onServiceStop() {
		$this->close();
	}
	public function connect($host, $port, $timeout = MC_DEF_TIMEOUT, $pconnect = MC_DEF_PCONNECT) {
		if ($this->m_memcached)
			return true;
		$mname = $pconnect? 'pconnect': 'connect';
		$this->m_memcached = new memcache;
		if ($this->m_memcached->$mname($host, $port, $timeout))
			return true;
		else
			$this->m_memcached = null;
		throw new xError($host, xError::ERR_BAD_LINK);
		return false;
	}
	public function close() {
		if ($this->m_memcached) {
			$this->m_memcached->close();
			$this->m_memcached = null;
			$this->m_uQuery = 0;
			return true;
		}
		return false;
	}
	public function __get($varName) {
		++$this->m_uQuery;
		return @$this->m_memcached->get($varName);
	}
	public function __set($varName, $varVal) {
		++$this->m_uQuery;
		if ($this->m_memcached->set($varName, $varVal, $this->bCompress?MEMCACHE_COMPRESSED:0, $this->uExpires))
			return $varVal;
		return $this->get($varName);
	}
	public function expire($varName, $expire) {
		++$this->m_uQuery;
		return @$this->m_memcached->delete($varName, $expire); 
	}
	public function delete($varName) {
		++$this->m_uQuery;
		return @$this->m_memcached->delete($varName); 
	}
	public function add($varName, $varValue, $expire = 0, $compress = 0) {
		++$this->m_uQuery;
		return @$this->m_memcached->add($varName, $varValue, $compress?MEMCACHE_COMPRESSED:0, $expire); 
	}
	public function set($varName, $varValue, $expire = 0, $compress = 0) {
		++$this->m_uQuery;
		return $this->m_memcached->set($varName, $varValue, $compress?MEMCACHE_COMPRESSED:0, $expire); 
	}
	public function replace($varName, $varValue, $expire = 0, $compress = 0) {
		++$this->m_uQuery;
		return @$this->m_memcached->replace($varName, $varValue, $compress?MEMCACHE_COMPRESSED:0, $expire); 
	}
	public function get($varName) {
		++$this->m_uQuery;
		return $this->m_memcached->get($varName); 
	}
	public function queries() {
		return $this->m_uQuery;
	}
	public function flush() {
		++$this->m_uQuery;
		return $this->m_memcached->flush();
	}
	public function inc($key, $step = 1) {
		++$this->m_uQuery;
		return $this->m_memcached->increment($key, $step);
	}
	public function dec($key, $step = 1) {
		++$this->m_uQuery;
		return $this->m_memcached->decrement($key, $step);
	}
}
#.mod[/memcache]

#.mod[memcache.lock]
class xMemLock {
	protected static $expire;
	protected $m_name;
	protected $m_locked;
	public static function init() {
		global $_SLEX;
		self::setExpire();
	} 
	public static function setExpire($expire = MC_LOCK_TIMEOUT) {
		self::$expire = $expire;
	}
	public function __construct($name = false, $expire = false) {
		$this->m_locked = false;
		if ($name)
			$this->lock($name, $expire);
	}
	public function lock($name = false, $expire = false) {
		$this->m_locked = false;
		if ($name)
			$this->m_name = $name;
		if (!$this->m_name)
			return false;
		if (!$expire)
			$expire = self::$expire;
		if (@xGbl::$mmc->add($this->m_name.MC_LOCK_SUFFIX, 1, $expire)) {
			$this->m_locked = true;
			return true;
		}
		return false;
	}
	public function unlock($name = false) {
		if (!$name)
			$name = $this->m_name;
		if (!$name)
			return false;
		if (xGbl::$mmc->delete($name.MC_LOCK_SUFFIX))
			return true;
		return false;
	}
	public function isLocked($name = false, $realtime = false) {
		if (!$name) {
			if ($this->m_name && !$realtime)
				return $this->m_locked;
			$name = $this->m_name;
		}
		if (!@xGbl::$mmc->get($name.MC_LOCK_SUFFIX))
			return false;
		return true;
	}
}
#.mod[/memcache.lock]

#.mod[cache]
class xFileCache {
	protected static $s_uQuery;
	protected static $s_sPath;
	
	public $caching;
	public $expires;
	public $buffer;
	public $id;
	public static function init() {
		global $_SLEX;
		self::$s_uQuery = 0;
		self::$s_sPath = $_SLEX['cache']['path'];
		ob_start();
	}
	public function __construct($id, $expires = 900, $clean = false, $reset = false) {
		$this->id = $id;
		$this->expires = $expires;
		if ($reset)
			$this->reset();
		elseif ($clean)
			$this->cleanUp();
		else {
			if (xGbl::$mmc->get($this->id.CACHE_LOCK_SUFFIX) && file_exists(self::$s_sPath.$this->id.'.php'))
				$this->buffer = substr(@file_get_contents (self::$s_sPath.$this->id.'.php'), 36);
			elseif (xGbl::$mmc->add($this->id.CACHE_LOCK_SUFFIX, 1, $this->expires))
				$this->caching = true;
			else
				$this->caching = false;
		}
	}
	public function __destruct() {
		$this->commit();
	}
	public function isValid() {
		return $this->buffer? true: false;
	}
	public function cleanUp($mem = true) {
		if ($this->id) {
			if ($mem)
				@xGbl::$mmc->delete($this->id.CACHE_LOCK_SUFFIX);
			@unlink(self::$s_sPath.$name.'.php');
			$this->caching = false;
			$this->buffer = '';
		}
	}
	public function reset() {
		$this->cleanUp(false);
		if (xGbl::$mmc->add($this->id.CACHE_LOCK_SUFFIX, 1, $this->expires))
			$this->caching = true;
	}
	public function append($text) {
		$this->buffer .= $text;
		$this->caching = true;
	}
	public function prefix($text) {
		$this->buffer = $text.$this->buffer;
		$this->caching = true;
	}
	public function begin() {
		ob_flush();
	}
	public function end() {
		$this->append(ob_get_contents());
		ob_flush();
	}
	public function commit($forced = false) {
		if ($this->buffer && ($this->caching || $forced)) {
			xGbl::$mmc->set($this->id.CACHE_LOCK_SUFFIX, 1, $this->expires);
			file_put_contents(self::$s_sPath.$this->id.'.php', SLEX_STATIC_CONF_HEAD.$this->buffer);
			$this->caching = false;
			return true;
		}
		return false;
	}
}
#.mod[/cache]

#.mod[mysql]
class xMySQLMaker {
	protected $m_itemInfo;
	protected $m_sqlOrg;
	protected $m_itemStack;
	/**
	 * 
	 * @var mysqli
	 */
	protected $m_myObj;
	public function start($sqlOrg, $myObj) {
		$this->m_itemInfo = array();
		$this->m_itemStack = array();
		$this->m_sqlOrg = $sqlOrg;
		$this->m_myObj = $myObj;
		if (preg_match_all('/\\[\\:([_a-z]\\w*)\\:(\\w)\\]/i', $sqlOrg, $tmp))
			foreach ($tmp[0] as $key => $v) {
				$this->m_itemInfo[$v] = array($tmp[1][$key], $tmp[2][$key]);
				$this->m_itemStack[$tmp[1][$key]] = 0;
			}
		else
			return false;
	}
	public function __get($varName) {
		return $this->get($varName);
	}
	public function __set($varName, $newVal) {
		return $this->set($varName, $newVal);
	}
	public function get($varName) {
		if (isset($this->m_itemStack[$varName]))
			return $this->m_itemStack[$varName];
		return false;
	}
	public function set($varName, $newVal) {
		if (isset($this->m_itemStack[$varName]))
			$this->m_itemStack[$varName] = $newVal;
		return $this->m_itemStack[$varName];
	}
	public function makeSQL() {
		$sql = $this->m_sqlOrg;
		foreach ($this->m_itemInfo as $key => $v) {
			switch ($v[1]) {
			case 'i':
				$sql = str_replace($key, (int)$this->m_itemStack[$v[0]], $sql);
				break;
			case 'f':
				$sql = str_replace($key, (float)$this->m_itemStack[$v[0]], $sql);
				break;
			case 's':
				$sql = str_replace($key, '\''.$this->m_myObj->real_escape_string($this->m_itemStack[$v[0]]).'\'', $sql);
				break;
			}
		}
		return $sql;
	}
}
class xMySQL {
	/**
	 * @var mysqli
	 */
	protected $m_link;
	protected $m_queries;
	protected $m_lastRes;
	protected static $s_Inst;
	public function __construct($host = false, $user = false, $pwd = false, $port = 3306, $dbname = '', $charset = 'utf8') {
		$this->m_queries = 0;
		$this->m_link = NULL;
		if ($host)
			$this->connect($host, $user, $pwd, $port, $dbname, $charset);
	}
	/**
	 * Start a MySQL Service
	 * @param string $service name of service.
	 * @return xMySQL
	 */
	public static function getServ($service = 'mysql') {
		global $_SLEX;
		if (isset(self::$s_Inst[$service]))
			return self::$s_Inst[$service];
		if (isset($_SLEX[$service]))
			$settings = $_SLEX[$service];
		else
			return null;
		$tmp = new xMySQL;
		try {
			if ($tmp->connect($settings['host'], $settings['user'], $settings['pwd'], $settings['port'], $settings['db'], $settings['charset']))
				return self::$s_Inst[$service] = $tmp;
		} catch (xError $e) {
			throw new xError($e->getMessage(), $e->getCode());
		}
		return null;
	}
	protected function onServiceStop() {
		$this->close();
	}
	/**
	 * Stop a MySQL service.
	 * @param string $service name of service.
	 * @return bool return true if succeeded.
	 */
	public static function stopService($service) {
		if (!isset(self::$s_Inst[$service]))
			return false;
		self::$s_Inst[$service]->onServiceStop();
		unset(self::$s_Inst[$service]);
		return true;
	}
	public function connect($host, $user, $pwd, $port = 3306, $dbname = '', $charset = 'utf8') {
		if (!$this->isConnected()) {
			$tmp = @new mysqli($host, $user, $pwd, $dbname, $port);
			if (!mysqli_connect_errno()) {
				if ($charset) $tmp->set_charset($charset);
				$this->m_queries = 0;
				$this->m_link = $tmp;
				return true;
			} else
				throw new xError($user.'@'.$host, xError::ERR_BAD_LINK);
		}
		return false;
	}
	public function pconnect($host, $user, $pwd, $port = 3306, $dbname = '') {
		return $this->connect($host, $user, $pwd, $port, $dbname);
	}
	public function close() {
		if ($this->isConnected()) {
			$this->m_queries = 0;
			$this->m_link = null;
		}
	}
	/**
	 * Execute a SQL command.
	 * @return mysqli_result
	 */
	public function exec($sql) {
		++$this->m_queries;
		return $this->m_link->query($sql);
	}
	public function selectDB($dbname) {
		return $this->m_link->select_db($dbname);
	}
	public function setCharset($csname) {
		return $this->m_link->set_charset($csname);
	}
	public function isConnected() {
		if ($this->m_link instanceof mysqli)
			return true;
		return false;
	}
	public function getStat() {
		if ($this->isConnected())
			return $this->m_link->stat();
		return false;
	}
	public function escape($str) {
		if ($this->isConnected())
			$this->m_link->real_escape_string($str);
		return addslashes($str);
	}
	public function getError() {
		if ($this->isConnected())
			return $this->m_link->error;
		return mysqli_error();
	}
	public function getErrno() {
		if ($this->isConnected())
			return $this->m_link->errno;
		return mysqli_errno();
	}
	public function getQueries() {
		return $this->m_queries;
	}
	public function getInsertID() {
		if ($this->isConnected())
			return $this->m_link->insert_id;
		return 0;
	}
	public function getAffectRows() {
		if ($this->isConnected())
			return $this->m_link->affected_rows;
		return 0;
	}
	public function listDatabases() {
		return $this->exec('SHOW DATABASES;');
	}
	public function listTables($dbname) {
		return $this->exec('SHOW TABLES FROM `'.$this->escape($dbname).'`;');
	}
	public function listFields($tbname, $dbname = '') {
		return $this->exec('SHOW FIELDS FROM '.($dbname?'`'.$this->escape($dbname).'`.':'').'`'.$this->escape($tbname).'`;');
	}
	public function makeSQL($sqlOrg) {
		if ($this->isConnected()) {
			$o = new xMySQLMaker();
			$o->start($sqlOrg, $this->m_link);
			return $o;
		}
	}
}
#.mod[/mysql]
#.end