<?php
namespace imcat;

// Environment基本环境处理类
class basEnv{    

    
// 处理_pbase
    
static function runPbase($_pbase){
        global 
$_cbase;
        
// 加载runskip
        
if(isset($_cbase['skip'])){
            include 
DIR_ROOT.'/cfgs/boot/bootskip.php'
        }
        
// 全局系统配置
        
if(!empty($_pbase)){ 
            
$_cbase basArray::Merge($_cbase$_pbase);
        }
    }

    
// 系统信息,魔术变量,时区
    
static function runVersion(){
        global 
$_cbase
        
/*if(version_compare(PHP_VERSION,'5.4.0','<')) {
            ini_set('magic_quotes_runtime',0);
            ini_set('magic_quotes_gpc',0);
        }*/
        
date_default_timezone_set($_cbase['sys']['tzcode']);        
    }
    
// const,
    
static function runConst(){
        
define('IS_CGI',     substr(PHP_SAPI,0,3)=='cgi' 0);
        
define('IS_WIN',     strstr(PHP_OS,'WIN') ? 0);
        
define('IS_CLI',     PHP_SAPI=='cli' 0);
        
define('KEY_NUM10',  '0123456789');
        
define('KEY_CHR26',  'abcdefghijklmnopqrstuvwxyz');
        
define('KEY_CHR22',  'abcdefghjkmnpqrstuvwxy'); // -iloz
        
define('KEY_NUM16',  KEY_NUM10.'abcdef');
        
define('KEY_TAB36',  KEY_NUM10.KEY_CHR26); // 极端情况下用
        
define('KEY_TAB32',  KEY_NUM10.KEY_CHR22); // (字形可能与数字012混淆)
        
define('KEY_TAB30',  '123456789abcdfghjkmnpqrstuvwxy'); // - 0e + iloz (0字形,e读音易混淆)
        
define('KEY_TAB24',  '3456789abcdfghjkpqstuvwxy'); // - 012eilmnorz(25) (去除字形读音易混淆者)
        
define('NSP_INIT',   "namespace imcat;\n(!defined('RUN_INIT')) && die('No Init');");
    }

    
// 前置处理,运行时常用变量
    
static function runCbase(){
        global 
$_cbase;
        
$run = &$_cbase['run'];
        
// 运行时常用变量,
        
$run['domain'] = empty($_SERVER['SERVER_NAME']) ? $_SERVER["HTTP_HOST"] : $_SERVER['SERVER_NAME'];
        
$run['dmtop'] = self::topDomain($run['domain']);
        
$run['stamp'] = $_SERVER["REQUEST_TIME"]; 
        
$run['userag'] = self::userAG();
        
$run['userip'] = self::userIP();
        
$run['query'] = 0//查询次数
        
$run['qtime'] = 0//查询时间
        
$run['jsimp'] = ','//imp-js:files
        
$run['tplname'] = ''//tpl:name
        
$run['tplnow'] = ''//tpl:now
        
$run['tagnow'] = ''//vopApp::tagParse()使用
        
$run['tmpFile'] = array();
        
$run['jtype_mods'] = ''//fldView::lists()使用
        
$run['jtype_init'] = ''//fldView::lists()使用
        
$run['sobarnav'] = ''//dopBSo->Form()使用,搜索条上的导航
        
$_cbase['tpl']['tplpend'] = ''//默认'',除非人工改变
        
$_cbase['tpl']['tplpext'] = ''//默认'',除非人工改变
        
if(empty($_cbase['tpl']['vdir'])){ $_cbase['tpl']['vdir']=''; }
        
//$_cbase['mkv'] = array();
        
$run['headed'] = '';
        
self::sysHome(); //,topDomain,IP过滤
    
}
    
    
// 处理skips
    
static function runSkips(){
        global 
$_cbase;
        
$skip = isset($_cbase['skip']) ? $_cbase['skip'] : array(); 
        
// 错误处理类 
        
if(!isset($skip['error'])){
            
self::runError();
        }
        
// *** robot
        
if(isset($skip['robot'])){
            
safBase::robotStop(); 
        }
        
// 处理session
        
if(!isset($skip['session'])){ 
            if(
session_status()!==PHP_SESSION_ACTIVE){
                
session_start();
            }
        }
    }

    
// 加载错误处理类 
    
static function runError(){
        global 
$_cbase;
        
$debug $_cbase['debug'];
        
// 加载错误处理类 
        
if(!isset($_cbase['skip']['error'])){ // && $debug['err_hand']
            
if($debug['err_mode']){
                
ini_set('display_errors''On');
                
error_reporting(E_ALL); 
            }else{
                
error_reporting(0); 
            }
            if(
$debug['err_hand']){
                
$hkey $debug['err_hkey'];
                
$hkey = ($hkey=='(def)' || intval($hkey)<=0) ? E_ALL^E_WARNING^E_NOTICE $hkey
                
#set_exception_handler('except_handler_ys'); //注册异常处理函数
                #set_error_handler('error_handler_ys',$hkey); //注册错误处理函数
            
}
        }
    }
    
// 获取一个_SERVER值, serval=serv+val合成
    
static function serval($key$def=''){
        
$tab = [
            
'host' => 'HTTP_HOST',
            
'lang' => 'HTTP_ACCEPT_LANGUAGE',
            
'ref'  => 'HTTP_REFERER',
            
'ua'   => 'HTTP_USER_AGENT',
        ];
        
$key = isset($tab[$key]) ? $tab[$key] : $key;
        
$val = isset($_SERVER[$key]) ? $_SERVER[$key] : $def;
        
$val str_replace(array("'","\\",'"','>','<'), ''$val);
        return 
$val;
    }

    
// 获取客户端软件信息
    
static function userAG(){
        return 
self::serval('ua');
    }
    
    
// 获取客户端IP地址 (xf=::1;ra=192.168.0.1,192.168.0.1;cip=127.0.0.1)
    
static function userIP($flag=0){
        
$a = array('xf'=>'HTTP_X_FORWARDED_FOR''ra'=>'REMOTE_ADDR''cip'=>'HTTP_CLIENT_IP');
        
$ip ''//'r'=>'HTTP_X_REAL_FORWARDED_FOR',
        
foreach($a as $k=>$v){
            if(!empty(
$_SERVER[$v])){ 
                
$ip .= ($ip ";" '')."$k=".$_SERVER[$v]; 
            }
        }
        return 
str_replace(["'","\\",'"'],'',$ip);
    }

    
// ---- 用户信息 判断 --------------------------------------- 
    /*  Android.*MicroMessenger.*miniProgram//安卓端的小程序
        iPhone.*MicroMessenger//苹果端微信或小程序
    //*/
    
    // 是否搜索引擎来访
    
static function isRobot($uastr=''){
        
$rbt glbConfig::read('uachk','sy');
        
$kw_spiders $rbt['spname'];
        
$uastr || $uastr self::userAG();
        if(
preg_match("/($kw_spiders)/i",$uastr)) return true;
        return 
false;
    }
    
// 是否miniProgram()
    
static function isMpro($ver=0){
        
$wxpos strpos(self::userAG(), 'miniProgram');
        return 
$wxpos;
    } 
    
// 是否Weixin()
    
static function isWeixin($ver=0){
        
$wxpos strpos(self::userAG(), 'MicroMessenger');
        if(
$ver){
            
preg_match('/.*?(MicroMessenger\/([0-9.]+))\s*/'$uagent$matches);
            return 
$wxpos $matches[2] : '';
        }else{
            return 
$wxpos;
        }
    }
    
// 是否Wework()
    
static function isWework(){
        
$wxpos strpos(self::userAG(), 'wxwork/');
        return 
$wxpos;
    }
    
// 是否Qq()
    
static function isQq($ver=0){
        
$wxpos strpos(self::userAG(), 'QQBrowser');
        return 
$wxpos;
    }
    
// 是否Mobile
    
static function isMobile($ckey=''){
        
//return true;
        
if(isset($_SERVER['HTTP_X_WAP_PROFILE'])){
            return 
true;
        }
        if(isset(
$_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'],"wap")){
            return 
true;
        }
        
$mbstr "Android|Windows Phone|webOS|iPhone|iPad|BlackBerry";
        if(
preg_match("/$mbstr/i",self::userAG())){
            return 
true;
        }else{
            return 
false;
        }
    }
    
// 是否ajax请求(jq)
    
static function isAjax(){ 
        
$sk 'HTTP_X_REQUESTED_WITH'
        return !empty(
$_SERVER[$sk]) && $_SERVER[$sk]=='XMLHttpRequest';
    }

    
# ======================================================

    // topDomain
    
static function topDomain($host){ 
        if(!
$host || !strpos($host,'.')){ return $host; }
        if(
strpos($host,':/')){
            
$host parse_url($host,PHP_URL_HOST);
            
//IPv6,这里得到的host有问题
        
}
        
$arr explode('.',$host);
        if(!
strpos($host,'.')){ //主机名形式:localhost/pcname; IPv6形式:FE80::1, ::1, 2000::1:2345:6789:abcd
            
return $host;
        }elseif(
is_numeric($arr[count($arr)-1])){ //IPv4
            
return $host;
        }else{ 
//域名
            
$cnt count($arr); 
            
$part1 $arr[$cnt-1]; $part2 $arr[$cnt-2];
            
$re "$part2.$part1"//默认
            
if($cnt>=3){
                
$tcfg glbConfig::read('domain','sy'); 
                
$tcfg $tcfg['dmtop'];
                
$t3p '.com.net.org.edu.gov.int.mil.';
                
$re3 $arr[$cnt-3].".$re";
                if(!empty(
$tcfg[$re])){
                    
$re $tcfg[$re]==$re3 $re;
                }elseif(
strlen($part2)==&& strlen($part1)==2){ //2.2 www.dg.gd.cn, www.88.cn
                    
$re preg_match('/[a-z]{2}/',$part2) ? $re3 $re;
                }elseif(
strlen($part2)==&& strlen($part1)==3){ //2.3 www.fyh.cn.com, www.88.com
                    
$re strpos($t3p,$part1) ? $re3 $re;
                }elseif(
strlen($part2)==&& strlen($part1)==2){ //3.2 www.txm.cn, www.net.cn
                    
$re strpos($t3p,$part2) ? $re3 $re;
                }
            }
            return 
$re;
        } 
    }
    
// sysHome // HTTP_HOST = SERVER_NAME : SERVER_PORT
    
static function sysHome(){
        global 
$_cbase;
        
$host = empty($_SERVER["HTTP_HOST"]) ? '' $_SERVER["HTTP_HOST"]; 
        
$iss self::isHttps() ? 'https' 'http';
        
$res glbConfig::read('domain','sy');
        
$sdirs $res['subDirs'];
        
// dir-跳转:
        
if(isset($sdirs[$host])){
            
$host $sdirs[$host];
            
$uri $_SERVER['REQUEST_URI'];
            
$dir "$iss://$host$uri"
            
header("Location:$dir");
        }
        
$_cbase['run']['iss'] = $iss
        
$_cbase['run']['rsite'] = "//$host"
        
$_cbase['run']['rmain'] = "//$host".PATH_PROJ
        
$_cbase['run']['roots'] = "//$host".PATH_ROOT
        
$_cbase['run']['fbase'] = "//$host".PATH_BASE
    }
    
// 判断是否 isHttps
    
static function isHttps() {
        if(isset(
$_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){
            return 
true// 1:Apache, on:IIS
        
}elseif(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO']==='https'){
            return 
true// 2:Nginx 
        
}elseif(!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS'])!=='off') {
            return 
true// 3:? 
        
}elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
            return 
true;
        }
        return 
false;
    }
    
// 检查内网ip地址
    
static function isLocal($ip=''){
        
$ip || $ip self::userIP();
        if(
strpos($ip,'.')){ // IPv4:
            
$pa explode('.',$ip);
            
$f1 in_array($pa[0],array('10','127')); // 10.*, 127.*
            
$f2 $pa[0]==192 && ($pa[1]==168); // 192.168.*
            
$f3 $pa[0]==172 && ($pa[1]>=16 && $pa[1]<=31); // 172.16.* ~ 172.31.*
            
return $f1 || $f2 || $f3;
        }elseif(
strpos($ip,':')){ // IPv6
            
$arr explode(':',$ip);
            return 
in_array($arr[0],array('FE80','FEC0'));
        }else{ 
// ::1=127.0.0.1=localhost
            
return in_array($ip,array('::1'));
        }
    }

    
// 缓冲区obSave(...)
    
static function obSave($msg=''){
        
$msg || $msg "Contents... ";
        
$file __FUNCTION__;
        echo 
'flag1';
        
ob_start(); 
        echo 
$msg.date('Y-m-d H:i:s');
        
$data ob_get_contents();
        
ob_end_clean(); 
        
comFiles::put(DIR_DTMP."/@temp/test_$file.txt",$data);
        echo(
'flag2');        
    }
    
    
// 缓冲区Start, 替代ob_start(...)
    
static function obStart(){
        !
ini_get('output_buffering') && ob_start();
    }
    
// 缓冲区Clean, 替代ob_end_clean(),ob_clean()
    
static function obClean($start=1){
        
$obList ob_list_handlers();
        
$obLen count($obList);
        while(
$obLen>0){
            
ob_clean();
            
$obLen--;
        };
        if(!empty(
$start)) self::obStart();
    }
    
// 缓冲区调试
    
static function obDebug($start=1){
        
$obList ob_list_handlers();
        
$obLen count($obList);
        
$str "\n<hr>";
        while(
$obLen>0){
            
$c ob_get_contents();
            
$str .= "Debug($obLen):$c<br>\n";
            
ob_flush();
            
$obLen--;
        };
        echo 
"$str<hr>";
    }
    static function 
obShow($data='obData',$die=1){
        
basEnv::obClean();
        echo 
"$data";
        
$die && die();
    }
}