<?php

class System{

	//数据库实例
	public static $db = null;
	
	//数据库连接
	public static $connect_id = null;
	
	//类初始化
	public static function init(){
		self :: init_input();
	}
	
	//初始化参数变量
	public static function init_input(){
		global $_G;
		
		//$prelength = strlen($this->config['cookie']['cookiepre']);
		foreach($_COOKIE as $key => $val) {
			//if(substr($key, 0, $prelength) == $this->config['cookie']['cookiepre']) {
				//$_G['cookie'][substr($key, $prelength)] = $val;
				$_G['cookie'][$key] = $val;
			//}
		}
	
		if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST)) {
			$_GET = array_merge($_GET, $_POST);
		}
	}

	/*
			打开或关闭 MySQL
			$close	为空或 false 为打开数据库，true 关闭数据库
	*/
	public static function connect( $close=false ){
		global $_G;
		
		//如果数据库已打开，则关闭
		if( self :: $db ){
	
			self :: $db -> close();
			self :: $db = null;
				
		}else{
		
			require_once dirname(__FILE__)."/../class/db.mysql.php";
	
			//mysql open
			self :: $db = new mysql_db( VI_DBHOST.":".VI_DBPORT, VI_DBUSER, VI_DBPASS, VI_DBNAME );
			
			//调试模式
			if( $_G['setting']['global']['debug'] == "on" ) self :: $db->setDebug();
			
			self :: $db -> setCharset( (VI_DBCHARSET?VI_DBCHARSET:$_G['product']['charset']) );
			self :: $db -> connection( true );
			self :: $connect_id = self :: $db ->_db_connect_id;
			
			return self :: $db ->_errno;
				
		}                
	}

	//系统设置
	public static function reader_config(){
		global $_G;
		
		return '
		Mo.store.site		="'.$_G['setting']['global']['site'].'";
		Mo.store.link		="'.$_G['setting']['global']['url'].'";
		Mo.store.base		="'.VI_BASE.'";
		Mo.store.build		="'.$_G['product']['build'].'";
		Mo.store.product		="'.$_G['product']['appname'].'";
		Mo.store.version		="'.$_G['product']['version'].'";
		Mo.store.licence		="'.$_G['licence']['type'].'";
		Mo.store.host		="'.VI_HOST.'";
		';
	}
	
	/*
			页面重定向
			$url		目标地址
			$msg		页面消息
	*/
	public static function redirect( $url, $msg ){
		$msg = urlencode($msg);
		if($msg){
			if (strrpos($url,"=")>0 || strrpos($url,"%3d")>0){
				$url.="&VMSG=".$msg;
			}else{
				$url.="?VMSG=".$msg;
			}
		}
		header("Location: ".$url);
		exit;
	}
	
	//////////////////////////////////
	
	/* 加载跨域脚本 */
	public static function cross_domain(){
		global $_G;
		
		//跨域支持（子域名必需）
		return $_G['setting']['global']['domain'] ? 'document.domain = "'. $_G['setting']['global']['domain'] .'";' : '';
	}

	//////////////////////////////////

	/*
			用户登录验证
			$username               用户名
			$password               密码（md5 过的）
	*/
	public static function admin_login( $username, $password ){
			
		if( !$password || !$username ){
				
				//登录信息不能为空!                        
				return -1;
		
		}elseif( $_G['setting']['global']['captcha'] == "on" && ( !$_SESSION['captcha'] || $_POST['captcha'] != $_SESSION['captcha'] ) ){
				
				//验证码输入错误!                        
				return -2;		
		
		}elseif( strlen($password) != 32 || !$_SESSION['RNDCODE'] || $_SESSION['RNDCODE'] != $_POST["rndcode"] ){
								
				//写入安全日志
				self :: insert_event( "login",time(),time(),"尝试登录系统时使用密码不符合规则：".$password);
				
				//密码或随机验证输入错误!
				return -3;
				
		}elseif( $_G['setting']['global']["ipzone"] && !checkIP( explode("\n",$_G['setting']['global']["ipzone"]) ,GetIP()) ){
								
				//写入安全日志
				self :: insert_event( "login",time(),time(),"尝试登录系统时使用的IP不在允许的范围内：".GetIP());
				
				//当前IP不在授权的范围!
				return -4;
				
		}else{
				
				//登录脚本
				$sql = "SELECT id,gid,account,avatar,email,phone,theme,last_login,last_active,stat_login from `sys:admin` WHERE ( account='".$username."' and password='".$password."' and `state`>0 ) LIMIT 0, 1";
				
				//查询数据库(Manager)
				$row = self :: $db -> getOne($sql);
				
				if( is_array( $row ) == FALSE ){
						
						//用户名或密码错误!                                
						return -5;
				
				}else{
						
					//同一用户只能登录一次
					if ( $_G['setting']['global']["sso"]=="on" && $row["last_active"] && time() - $row["last_active"] <= $_G['setting']['global']["interval"] ){
						
						//该用户已经在登录状态!                                        
						return -6;
							
					}else{					
				
						//设置Session
						self :: admin_session($row);
						
						//time
						$time = time();
						
						//更新用户最后活动信息
						$sql = "UPDATE `sys:admin` SET stat_login=stat_login+1,last_ip='".GetIP()."',last_login='".$time."',last_active=".$time." WHERE id = ".$_SESSION['Manager']['id'];
						
						self :: $db -> execute($sql);
						
						//清除最近的登录日志
						self :: delete_event( $_SESSION['Manager']['id'], "login" );
						
						//写入日志
						self :: insert_event( "login" ,$time, $time );
						
						return $_SESSION['Manager']['id'];
					
					}
				
				}
		}
			
	}
	
	/*
			生成用户会话信息
			$row            数据记录（单条）
	*/
	public static function admin_session( $row ){                
		global $_G;

		//用户信息
		$_SESSION['Manager']=array();
		
		foreach ($row as $key => $val) {
				$_SESSION['Manager'][$key]=$val;
		}	
		
		$_G['manager'] = $_SESSION['Manager'];					
	}
	
	/*
			注册新管理员
			$row            数据记录（单条）
	*/
	public static function admin_insert( $row ){                
		global $_G;

		//用户信息
		$_SESSION['Manager']=array();
		
		foreach ($row as $key => $val) {
				$_SESSION['Manager'][$key]=$val;
		}	
		
		$_G['manager'] = $_SESSION['Manager'];					
	}
	
	/*
			注册新管理员
			$row            数据记录（单条）
	*/
	public static function admin_delete( $row ){                
		global $_G;

		//用户信息
		$_SESSION['Manager']=array();
		
		foreach ($row as $key => $val) {
			$_SESSION['Manager'][$key]=$val;
		}	
		
		$_G['manager'] = $_SESSION['Manager'];
					
	}
	
	/*
			处理用户登出
	*/
	public static function admin_logout(){
		global $_G;
	
		if( $_SESSION['Manager']['id'] ){
								
			//写入日志
			self :: insert_event("exit",time(),time());					
		}

		unset( $_SESSION['Manager'], $_G['manager'] );                
	}
	
	////////////////////////////////
	
	/*
			在线用户统计
			$gid            用户组
	*/
	public static function admin_online( $gid ){
		global $_G;
		
		$sql="SELECT * FROM `sys:admin` WHERE ( ".time()." - last_active <= ".$_G['project']['heartbeat']." )";                
		$gid && $sql.=" and gid = ".$gid;                
		$sql.=" ORDER BY id desc,state desc";
		
		return self :: $db -> getAll( $sql );
	}
	
	/*
			更改用户头像
			$uid             用户ID
			$avatar        头像地址
	*/
	public static function admin_avatar( $uid, $avatar ){
			
		//更新数据
		$sql = "UPDATE `sys:admin` SET avatar='".$avatar."' WHERE id = ".$uid;                
		return self :: $db -> execute( $sql );
			
	}
	
	/*
			更改用户头像
			$uid             用户ID
			$theme        头像地址
	*/
	public static function admin_theme( $uid, $theme ){
	
		//更新数据
		$sql = "UPDATE `sys:admin` SET theme='".$theme."' WHERE id = ".$uid;                
		self :: $db -> execute($sql);
			
	}
	
	/*
		根据权限名称索引符合的用户组
		$func	权限名称
		$join	是否转换成字符串组合
	*/
	public static function get_func_gid( $func, $join = false ){
		global $_CACHE;
		
		$list = array();
		foreach( $_CACHE['system']['group'] as $gid => $row ){
			if( array_key_exists( $func, $row['config'] ) ){
				array_push( $list, $gid );
			}
		}
		
		return $join ? implode( ',', $list ) : $list;
			
	}
	
	/*
		根据权限名称索引符合的用户组
		$gid	用户组ID
		$join	是否转换成字符串组合
	*/
	public static function get_user_gid( $gid, $join = false  ){
		global $_CACHE;
		
		$list = array();
		foreach( $_CACHE['system']['admin'] as $aid => $row ){
			if( in_array( $row['gid'], $gid ) ){
				array_push( $list, $aid );
			}
		}
		
		return $join ? implode( ',', $list ) : $list;
			
	}
	
	////////////////////////////////
	
	/*
	登录状态检查
	$jump	是否登录后转到本页，true 或 false
	*/
	public static function check_login($jump=true){
		global $_G;
		
		if(!$_SESSION['Manager']['account'] && strpos(strtolower($_SERVER['PHP_SELF']),"admin.login.php")==0){
			header("Location:".VI_BASE."module/system/admin.login.php".($jump?'?jump='.urlencode(GetCurUrl()):''));
		}
	}

	/*
			页面权限
	*/
	public static function check_page(){
		global $_G;
		
		//当前模块	
		$appid = str_replace( VI_BASE.'module/', '', dirname($_SERVER["REQUEST_URI"]) );
		
		if( $appid == "system" && array_key_exists(GetCurFile(),$_G['project']['page']) && !array_key_exists(GetCurFile(),$_G['group']) && !array_key_exists("*",$_G['group']) ){
			header("Location:".VI_BASE."module/system/serve.error.php?action=page&page=".GetCurFile());
			exit();
		}
	}

	/*
		功能权限
		$func		权限名称
		$debug	显示调试信息
	*/
	public static function check_func( $func, $debug = null ){
		global $_G;
		
		//调试模式
		if( isset( $debug ) ){			
			if( !array_key_exists( $func, $_G['group'] ) && !array_key_exists("*",$_G['group']) ){	
			
				//显示错误
				if( $debug ){
					return "<div id='state' class='failure'>没有 <strong>".$func."</strong> 权限！您可能无法继续本页某些操作，请联系系统管理员。</div>";
				}else{
					ob_end_clean();
					header("Location:".VI_BASE."module/system/serve.error.php?action=func&func=".$func);
					exit;	
				}
			}
		}else{
			//返回状态
			return array_key_exists( $func, $_G['group'] );
		}
	}
	
	/*
			检查类是否存在
			$class	类名称
	*/
	public static function check_class($class){	
		if( !class_exists($class) ){
			header("Location:".VI_BASE."module/system/serve.error.php?action=class&class=".$class);
			exit;
		}
	}

	/*
			检查变量是否为空
	*/
	public static function check_empty(){
		$num = func_num_args();
		$arg = func_get_args();
		for ($i = 0; $i < $num; $i++) {
			if( empty($arg[$i]) ){
				header("Location:".VI_BASE."module/system/serve.error.php?action=empty&empty=".$i);
				exit;
			}
		}
	}

	/*
			检查变量是否为空
	*/
	public static function check_writable(){
		$num = func_num_args();
		$arg = func_get_args();
		for ($i = 0; $i < $num; $i++) {
			if( is_writable($arg[$i]) === FALSE ){
				return "<div id='state' class='failure'>警告：目录 <strong>".str_replace( VI_ROOT, VI_BASE, $arg[$i] )."</strong> 没有写权限！</div>";
			}
		}
	}
	
	//////////////////////////////////

	/*
		写入一条系统日志
		$event	事件标识
		$start	发生时间
		$last	最后更新时间
		$desc	描述内容
	*/
	public static function insert_event( $event, $start, $last, $desc = "" ){
			
		$sql="INSERT INTO `sys:event`(account,aid,event,dateline,modify,ip,description) values('".$_SESSION['Manager']['account']."','".$_SESSION['Manager']['id']."','".$event."','".$start."','".$last."','".GetIP()."','".$desc."')";
		
		self :: $db -> execute($sql);
			
	}
	
	/*
		删除过期系统日志
		$uid	用户ID
		$event	事件标识
	*/
	public static function delete_event( $uid, $event ){                
		global $_G;

		if( !$uid ) return;

		//删除日志
		$sql = "SELECT * FROM `sys:event` WHERE event='$event' and aid=".$uid;
		$rows = self :: $db -> query($sql);
		
		if( $rows > $_G['setting']['global']["logsize"]-1 ){
		
			//删除日志_不支持子查询
			$sql = "DELETE FROM `sys:event` WHERE event='$event' and dateline<".(time()-604800)." and aid=".$uid;
	
			self :: $db -> execute($sql);
		}
			
	}
	
	
	//////////////////////////////////
	
	/*
		记录新审核
		$perm		审核权限
		$appid		模块ID
		$func		操作名称
		$summary	内容摘要
		$execute	执行语句
		$original	原始摘要
	*/
	public static function examine_insert( $perm, $appid, $func, $summary, $execute, $original = array() ){
		global $_G;
		global $_CACHE;
		
		//如果有执行权限
		if( array_key_exists( $perm, $_G['group'] ) ){
			
			self :: examine_execute( $appid, $execute, $summary, $original );
			
		}else{
			
			//记录新审核
			$sql="INSERT INTO `sys:examine`(account,aid,appid,func,summary,original,execute,state,dateline,ip) values('".$_SESSION['Manager']['account']."','".$_SESSION['Manager']['id']."','".$appid."','".$func."','".format_json( fix_json( $summary ) )."','".format_json( fix_json( $original ) )."','".addslashes( $execute )."',-1,'".time()."','".GetIP()."')";
			
			self :: $db -> execute($sql);
			
			//查找拥有审核权限的用户组
			$gid = self :: get_func_gid( $perm );
			
			//查找拥有审核权限的用户组
			$uid = self :: get_user_gid( $gid );
			
			//批量发送审核提醒邮件
			foreach( $_CACHE['system']['admin'] as $aid => $row ){
				if( in_array( $aid, $uid ) && $row['email'] ){
					self :: sendmail( '新审核请求……', $row['email'], '', $row['account'].'<br />$content' );
				}
			}
			
		}

	}
	
	/*
		删除过期系统日志
		$id			审核ID
		$state		状态值
		$remark		备注信息
	*/
	public static function examine_update( $id, $state, $remark = '' ){                
		global $_G;
		global $_CACHE;
		
		//查询记录
		$sql = "SELECT * FROM `sys:examine` WHERE state = -1 and id=".$id;
		$row = self :: $db -> getOne($sql);
		
		if( $row ){
		
			$row['summary'] = fix_json( $row['summary'] );			
			$row['original'] = fix_json( $row['original'] );
			
			/*
	
			//执行查询
			self :: $db -> execute( $row['execute'] );
			
			//如果是新插入数据
			if( preg_match("/INSERT INTO/i", $row['execute'] ) ){
			
				//读取插入ID
				$newid = self :: $db -> getInsertId();
				
				//记录新ID
				$row['summary']['id'] = $newid;
			}
			
			*/
			
			//更新数据
			$sql = "UPDATE `sys:examine` SET remark='".$remark."',state='".$state."',auditor='".$_SESSION['Manager']['account']."' WHERE id = ".$id;                
			self :: $db -> execute($sql);
			
			self :: examine_execute( $row['appid'], $row['execute'], $row['summary'], $row['original'] );
			
			/*
						
			//加载模块
			Module :: loader( $row['appid'] );
			
			//调用模块接口
			call_user_func_array( array( $row['appid'], 'examine'), array( $row['summary'], $row['original'] ) );
			
			*/
			
			//审核处理完邮件提醒
			$email = $_CACHE['system']['admin'][$row['aid']]['email'];
			
			if( $email ){
				self :: sendmail( '审核处理完毕……', $email, '', '$content' );
			}
			
		}
			
	}
	
	/*
		删除过期系统日志
		$id			审核ID
		$state		状态值
		$remark		备注信息
	*/
	public static function examine_execute( $appid, $execute, $summary, $original ){                
		global $_G;

		//执行查询
		self :: $db -> execute( $execute );
		
		//如果是新插入数据
		if( preg_match("/INSERT INTO/i", $execute ) ){
		
			//读取插入ID
			$newid = self :: $db -> getInsertId();
			
			//记录新ID
			$summary['id'] = $newid;
		}
					
		//加载模块
		Module :: loader( $appid );
		
		//调用模块接口
		call_user_func_array( array( $appid, 'examine'), array( $summary, $original ) );
			
	}
	
	//////////////////////////////////

	//保存配置
	public static function append_config( $file, $mysql_host, $mysql_port, $mysql_db, $mysql_user, $mysql_password, $mysql_manpre ,$mysql_modpre ){

		$success = false;
		
		if( !$file ) return false;
		
		if($content = file_get_contents($file)) {
				$content = trim($content);
				
				$content = self :: insert_config($content, "/define\('VI_BASE',\s*'.*?'\);/i", "define('VI_BASE', '".url_base()."');");

				//所在绝对目录
				$http = url_path();

				$content = self :: insert_config($content, "/define\('VI_HOST',\s*'.*?'\);/i", "define('VI_HOST', '$http');");		
				
				$content = self :: insert_config($content, "/define\('VI_START',\s*'.*?'\);/i", "define('VI_START', '".time()."');");
				
				$content = self :: insert_config($content, "/define\('VI_DBHOST',\s*'.*?'\);/i", "define('VI_DBHOST', '$mysql_host');");
				$content = self :: insert_config($content, "/define\('VI_DBPORT',\s*'.*?'\);/i", "define('VI_DBPORT', '$mysql_port');");
				$content = self :: insert_config($content, "/define\('VI_DBNAME',\s*'.*?'\);/i", "define('VI_DBNAME', '$mysql_db');");
				$content = self :: insert_config($content, "/define\('VI_DBUSER',\s*'.*?'\);/i", "define('VI_DBUSER', '$mysql_user');");
				$content = self :: insert_config($content, "/define\('VI_DBPASS',\s*'.*?'\);/i", "define('VI_DBPASS', '$mysql_password');");
				
				$content = self :: insert_config($content, "/define\('VI_DBMANPRE',\s*'.*?'\);/i", "define('VI_DBMANPRE', '$mysql_manpre');");
				$content = self :: insert_config($content, "/define\('VI_DBMODPRE',\s*'.*?'\);/i", "define('VI_DBMODPRE', '$mysql_modpre');");

				if(@file_put_contents($file, $content)) {
					$success = true;
				}
		}

		return $success;
	}

	/*
		写入配置
		$s			原始内容
		$find		查找内容
		$replace	替换内容
	*/
	public static function insert_config($s, $find, $replace) {
		if( preg_match($find, $s) ){
			$s = preg_replace($find, $replace, $s);
		} else {
			$s .= "\r\n".$replace;
		}
		return $s;
	}

	//////////////////////////
       
	/*
		普通邮件发送函数
		$subject		主题
		$address	收件人地址
		$list			抄送人地址
		$content		邮件主体
	*/
	public static function sendmail( $subject, $address, $list, $content ){
		global $_G;
	
		//class
		require_once VI_ROOT.'config/mail.php';
		require_once VI_ROOT.'class/class.phpmailer.php';
		
		//读取邮件模板
		if( !isset( $_G['mail_template'] ) ){
			$_G['mail_template'] = sreadfile( VI_ROOT.'source/template/mail.htm' );
		}
		
		$template = $_G['mail_template'];
		
		error_reporting(E_STRICT);
		
		$mail             = new PHPMailer();
		$mail->CharSet	  = $_G['product']['charset'];
		
		//$body             = stripslashes($_POST["content"]);
		//$content             = eregi_replace("[\]",'',$content);
		
		$content             = array_var_convert( $template, array( '{TEMPLATE_HEAD}' => $_G['setting']['mail']['MAIL_TEMPLATE_HEAD'], '{TEMPLATE_FOOT}' => $_G['setting']['mail']['MAIL_TEMPLATE_FOOT'], '{TEMPLATE_TIME}' => date('Y年m月d日'), '{TEMPLATE_HOST}' => VI_HOST, '{TEMPLATE_BODY}' => stripslashes($content) ) );
		
		//exit( $content );
		
		//exit( $content );
		
		$mail->IsSMTP(); // telling the class to use SMTP
		//$mail->Host       = "smtp.qq.com"; // SMTP server
		//$mail->SMTPDebug  = 2;                     // enables SMTP debug information (for testing)
												   // 1 = errors and messages
												   // 2 = messages only
		$mail->SMTPAuth   = true;                  // enable SMTP authentication
		$mail->Host       = $_G['setting']["mail"]["MAIL_SMTP_HOST"]; // sets the SMTP server
		$mail->Port       = $_G['setting']["mail"]["MAIL_SMTP_PORT"];                    // SET the SMTP port for the GMAIL server
		$mail->Username   = $_G['setting']["mail"]["MAIL_USER"]; // SMTP account username
		$mail->Password   = $_G['setting']["mail"]["MAIL_PASS"];        // SMTP account password
		
		$mail->SetFrom($_G['setting']["mail"]["MAIL_SMTP_FROM"], $_G['setting']["mail"]["MAIL_SMTP_NAME"]);
		
		//$mail->AddReplyTo("name@yourdomain.com","First Last");
		
		$mail->Subject    = $subject;
		
		//$mail->AltBody    = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
		
		$mail->MsgHTML($content);
		
		//$address = "verywork@gmail.com";
		$mail->AddAddress($address);
		
		if( $list ){
			$array = explode(",",$list);
			foreach( $array as $address ){
				$mail->AddBCC(trim($address));
			}
		}
		
		//$mail->AddAttachment("image/phpmailer.gif");      // attachment
		//$mail->AddAttachment("image/phpmailer_mini.gif"); // attachment
		
		if(!$mail->Send()) {
			return false;
		} else {
			return true;
		}
	}
	
	public static function show_error($errno, $errstr, $errfile, $errline){

		//为了安全起见，不暴露出真实物理路径，下面两行过滤实际路径
		$errfile = str_replace(getcwd(),"",$errfile);
		$errstr = str_replace(getcwd(),"",$errstr);
		
		switch ($errno) {
			case E_USER_ERROR:		
				echo "<div id='error'><b>USER ERROR：</b> <br /><br />\n <em>$errstr</em> \n<br /><br />";
				echo "  Fatal error on line $errline in file $errfile";
				echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
				echo "Aborting...<br />\n</div>";
				exit(1);
			break;
		
			case E_USER_WARNING:
				echo "<div id='error'><b>USER WARNING：</b> <br /><br /> <em>$errstr</em> <br />\n</div>";
				exit(1);
			break;
		
			case E_USER_NOTICE:
				echo "<div id='error'><b>USER NOTICE</b> <br /><br /> <em>$errstr</em> <br />\n</div>";
				exit(1);
			break;
		
			default:
				//echo "Unknown error type: [$errno] $errstr<br />\n";
			break;
		}
		
		/* Don't execute PHP internal error handler */
		return true;
	}        
        
}

?>