<?php
namespace imcat;
(!
defined('RUN_INIT')) && die('No Init');

/**
safBase : 常规-安全过滤(Safil=Safety Filter)
  formAuto,formRev,formCheck,
  urlFrom,urlScan,urlStamp
*/
class safComm// extends safBase
    
    
static function chkVImg(){
        
safComm::urlStamp('check');
        
$mod req('mod'); $key req('key'); 
        
$key = (is_string($mod)&&is_string($key)) ? "{$mod}_{$key}date('mdHis');
        
$vcode req($key);
        if(
is_array($vcode)){
            
safBase::Stop('Error:'.var_export($vcode,1));
        }
        
$re safComm::formCVimg($mod$vcode'check'600);
        if(
strstr($re,'-Error')){
            echo 
lang('plus.cajax_vcerr');
        }elseif(
strstr($re,'-Timeout')){
            echo 
lang('plus.cajax_vctout');
        }else{
            echo 
"success";
        }
    }

    
// 综合认证:
    
static function formCAll($mod,$path='',$timeout=3600,$clear=1){
        
$re '';
        
//fromUrl 认证
        
self::urlFrom($path);
        
$rest self::formCInit('x'$timeout);
        
$code basReq::val("{$mod}_{$rest[1]}");
        
$revc self::formCVimg($mod$code'check'$timeout$clear);
        if(!empty(
$rest[0])){ 
            
$re basLang::show('safcomm_vcoderr')."[$rest[0]]";
        }elseif(!empty(
$revc)){ //认证码 认证
            
$re basLang::show('safcomm_vcoderr')."[$revc]";
        }
        return array(
$re,$code); //认证结果
    
}
    
    
// ---- 表单过滤项 ---------------------------------------
    
    // 检查表单项 --- formCVimg()
    
static function formCVimg($mod$vcode$act$timeout=3600$clear=0){ 
        global 
$_cbase;
        
$sform $_cbase['safe']['safil'];
        if(
$act=='save'){
            
$stamp $_cbase['run']['stamp']; 
            
$encode $stamp.','.comConvert::sysEncode($sform.strtoupper($vcode),$stamp);
            
comCookie::mset('vcodes',0,$mod,$encode); 
            return;
        }elseif(
$mod=='vsms4'){
            
$enc comConvert::sysBase64($vcode); 
            
$ck comCookie::oget('vsms4'); 
            
$res strlen($vcode)>&& $enc==$ck;
            return 
$res '' 'VCode-Error[vsms4]!';
        }else{ 
//check
            
$cookie comCookie::mget('vcodes',$mod); 
            
$stamp substr($cookie,0,strpos($cookie,',')); 
            
$encode $stamp.','.comConvert::sysEncode($sform.strtoupper($vcode),$stamp);
            if(
strlen($cookie)<24 || $cookie!=$encode){
                
$re "VCode-Error[1]!"
            }elseif((
$_cbase['run']['stamp']-$stamp)>$timeout){
                
$re "VCode-Timeout[2]!";
            }else{
                
$re '';
            }
            
$clear && comCookie::mset('vcodes',0,$mod,'null');
            return 
$re;
        }
    }
    
    
// 检查表单项 --- 表单时间戳
    
static function formCInit($act='init'$time=3600$novcode=0){  
        global 
$_cbase;
        
$stamp $_cbase['run']['stamp']; 
        
$sform $_cbase['safe']['safil'];
        
$safix $_cbase['safe']['safix'];
        
$rdnum $_cbase['safe']['rnum']; 
        
$re ''$len1 34$len2 16//偶数
        
$st date('H',$stamp)>22 ? ($stamp 5400) : $stamp//23:xx -> 3600+1800
        
$sdate explode('_',date('m_d',$st));
        
$dval  =     (substr($rdnum,1,4)+substr($rdnum,4,4)*$sdate[0]); 
        
$dval .= '_'.(substr($rdnum,6,4)+substr($rdnum,9,4)*$sdate[1]);
        if(
$act=='init'){
            
$encode comConvert::sysEncode($sform,$stamp,$len1);
            
$restr "<input type='hidden' name='{$safix}[dt]' value='$dval' />";
            
$restr .= "<input type='hidden' name='{$safix}[tm]' value='$stamp' />";
            
$restr .= "<input type='hidden' name='{$safix}[enc]' value='$encode' />";
            if(
$novcode){ return $restr; }
            
$fmid basReq::val('fmid',''); $tabi basReq::val('tabi',19790);
            
$pos basReq::val('pos',''); 
            
$css1 basReq::val('css1','form-control'); // txt w60
            
$css2 basReq::val('css2','fs_vimg');
            
$senc comConvert::sysEncode($sform,$stamp,$len2); 
            
$vstr "maxlength='5' reg='vimg:3-5' tip='".basLang::show('core.safcomm_vcode')."' url='".PATH_BASE."?ajax-cajax&act=chkVImg&mod={$fmid}&key={$senc}'";
            
$restr .= "<input placeholder='".basLang::show('vcode')."' id='{$fmid}_{$senc}' name='{$fmid}_{$senc}' tabindex='$tabi' type='text' class='$css1' onFocus=\\\"fsCode('{$fmid}',0,'$pos')\\\" $vstr />";
            
$restr .= "<samp id='{$fmid}_vBox' class='$css2' style='display:none'></samp>"//samp,span, style='width:50px;'
            
return $restr;
        }else{
            
$re_date basReq::ark($safix,'dt');
            
$re_stamp basReq::ark($safix,'tm'); 
            
$re_encode basReq::ark($safix,'enc'); 
            
$enc comConvert::sysEncode($sform,$re_stamp,$len2); 
            if(empty(
$re_stamp) || empty($re_encode)){
                
$re 'Error-Null';
            }elseif(
$stamp-$re_stamp>$time){ 
                
$re 'Timeout';
            }elseif(!(
$re_encode==comConvert::sysEncode($sform,$re_stamp,$len1))){ 
                
$re 'Error-E';
            }elseif(!(
$re_date==$dval)){ 
                
$re 'Error-D';
            }
            return array(
$re,$enc);
        }
    }

    
// QUERY-7参数检测
    
static function urlQstr7($re=0){ 
        
$q basEnv::serval("QUERY_STRING");
        
$q urldecode($q);
        if(
$q!=str_replace(array('<','>','"',"'","\\","\r","\n"),'',$q)){
            
$msg "[QUERY]Error!";
            if(
$re) return $msg;
            
basMsg::show($msg,'die'); 
        }
        return 
0;
    }
    
    
//检测是否外部提交过来的Url
    //expath : 路径匹配部分,可为空
    //die : 默认直接die, 如为空则返回用于判断
    //return : 默认直接die; false:不是外部提交来的地址; true(string):相关信息,表示是外部提交或直接输入网址过来
    //demo: if(xxx::urlFrom('',0)) die("不是来自{PATH_ROOT}的请求!");
    //demo: if(xxx::urlFrom('/dgpeace/_php_test.php'));
    
static function urlFrom($expath='',$die=1){
        
$re '';
        
$ref basEnv::serval('ref');
        if(empty(
$ref)){ //为空:(输入地址等)
            
$re 'Null'
        }else{
            
$from self::urlParse($ref); 
            
$hnow self::urlParse($_SERVER['HTTP_HOST']); 
            if(@
$from['host']!==@$hnow['host']){ // 匹配:主机/域名+端口 
                
$re $from['host']; 
            }else{ 
// 匹配:路径
                
$npath PATH_PROJ//cls_env::mconfig('cmsurl'); // 如:/house/
                
if($expath$npath str_replace(array('///','//'),'/',"$npath/$expath"); 
                if(
strlen($npath)>&& !preg_match('/^'.preg_quote($npath,"/").'/i',$from['p'])){ 
                    
$re $npath;    
                } 
            }
        }
        if(
$re && $die){ 
            
safBase::Stop('urlFrom',$re); 
        }
        return 
$re
    }
    
    
/*    获取: host(主域名+端口) 和 path(路径)
    --- Demo --- 
    $url1 = "http://m.txmao.com:808/shopinfo.d?m=fbyzm&mobile=13537432146&city=bj#aa=33";
    $url2 = "http://www.txmao.com:808/example/index.php/dir/test.php?aaa=bbb";
    $url3 = "http://192.168.1.11:888/house/dgpeace/_php_test.php?aaaa=bbb";
    $url4 = "http://[2001:410:0:1:250:fcee:e450:33ab]:8443/file.php/rrf?aa=bb"; 
    echo 'aab:<pre>'.var_dump(xxx::urlParse($url4)).'</pre><br>';
    */
    
static function urlParse($url){    
        
$aurl parse_url($url); 
        
$top basEnv::TopDomain(@$aurl['host']);
        if(!empty(
$top)){ //IP(含ipv6)
            
$aurl['host'] = $top;
        }
        
$host = @$aurl['host'].(isset($aurl['port']) ? ':'.$aurl['port'] : '');
        
$path = empty($aurl['path']) ? '' $aurl['path'];
        return array(
'h'=>$host,'p'=>$path);
    }

    
// 注入项扫描关键字
    
static function urlScan(){  
        
$filters  "(and|or)\\b.+?(>|<|=|in|like)|<\\s*script\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        
$paras basEnv::serval("QUERY_STRING");
        if(empty(
$paras)) return;
        if(
preg_match("/".$filters."/is",$paras)){   
            
safBase::Stop('urlScan');
        }    
    } 
// \\bEXEC\\b| , \\/\\*.+?\\*\\/| , '|
    
    // --- act=init,stop,flag
    
static function urlStamp($act='init'$time=3600){  
        global 
$_cbase;
        
$stamp $_cbase['run']['stamp']; 
        
$sform $_cbase['safe']['safil'];
        
$safix $_cbase['safe']['safix'];
        if(
$act=='init'){
            
$encode comConvert::sysEncode($sform$stamp);
            return 
"{$safix}[tm]=$stamp&{$safix}[enc]=$encode";
        }else{
            
$flag 0;
            
$re_stamp basReq::ark($safix'tm');
            
$re_encode basReq::ark($safix'enc'); 
            if(empty(
$re_stamp) || empty($re_encode)){ 
                
$flag 'empty'
            }elseif(
$stamp-$re_stamp>$time){ 
                
$flag 'timeout';
            }elseif(!(
$re_encode==comConvert::sysEncode($sform$re_stamp))){ 
                
$flag 'encode'
            }
            if(
$flag){
                return (
$act=='flag') ? $flag safBase::Stop('urlStamp-'.$flag);
            }
        }
    }
    
    
/*
    --- signVeryfy
    签名: data=array, keys='k1,k2'
    认证: data=timeout, keys='k1,k2'
    $act = basReq::val('act','sign');
    if($act=='sign'){
        $arr = array('act'=>'check','aa'=>'aa1','bb'=>'bb1',);
        $str = safComm::signVeryfy($arr,'act,aa');
        echo ":<a href='?$str' target='_blank'>$str</a>:";
    }elseif($act=='check'){
        $timeout = basReq::val('timeout','5');
        $res = safComm::signVeryfy($timeout,'act,aa');
        echo $res;
    }*/
    
static function signVeryfy($data=60,$keys=''){ 
        global 
$_cbase;
        
$stamp $_cbase['run']['stamp']; 
        
$snid $_cbase['safe']['rnum'];
        
$skey $_cbase['safe']['api'];
        
$safix $_cbase['safe']['safix'];
        
$udata is_array($data) ? $data $_GET;
        
$keys || implode(',',array_keys($data));
        
$akey explode(',',$keys);
        
$schk ''$sret '';
        foreach(
$udata as $key=>$val){
            if(
is_array($val)) continue;
            
$sret .= "&$key=$val";
            if(
in_array($key,$akey)){ 
                
$schk .= "&$key=$val";
            }
        }
        if(
is_array($data)){
            
$encode comConvert::sysEncode($schk,"$snid.$skey.$stamp");
            return 
"{$safix}[tm]=$stamp&{$safix}[enc]=$encode{$sret}";
        }else{
            
$ustamp basReq::ark($safix,'tm');
            if(
$stamp-$ustamp>intval($data)) return 'timeout';
            
$usign basReq::ark($safix,'enc'); 
            
$encode comConvert::sysEncode($schk,"$snid.$skey.$ustamp");
            return 
$encode==$usign '' 'error';
        }
    }
    
    
// --- act=init,stop,flag
    
static function signApi($act='init',$time=3600){  
        global 
$_cbase;
        
$stamp $_cbase['run']['stamp']; 
        
$safix $_cbase['safe']['safix'];
        
$keyapi $_cbase['safe']['api'];
        if(
$act=='init'){
            
$encode md5("$keyapi.$stamp");
            return 
"{$safix}[tm]=$stamp&{$safix}[enc]=$encode";
        }else{
            
$flag 0;
            
$re_stamp intval(basReq::ark($safix,'tm'));
            
$re_encode basReq::ark($safix,'enc'); 
            if(empty(
$re_stamp) || empty($re_encode)) $flag 'empty';
            if(
$stamp-$re_stamp>$time$flag 'timeout';
            if(!(
$re_encode==md5("$keyapi.$re_stamp"))) $flag 'encode';
            if(
$flag){
                return (
$act=='flag') ? $flag safBase::Stop('urlStamp');
            }
        }
    }
    
        
    
// --- End ----------------------------------------
    
}