Thinkphp基礎之輸入類處理

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------
// $Id: Input.class.php 2528 2012-01-03 14:58:50Z liu21st $

/** 輸入數據管理類
 * 使用方法
 *  $Input = Input::getInstance();
 *  $Input->get('name','md5','0');
 *  $Input->session('memberId','','0');
 *
 * 下面總結了一些常用的數據處理方法。以下方法無需考慮magic_quotes_gpc的設置。
 *
 * 獲取數據:
 *    如果從$_POST或者$_GET中獲取,使用Input::getVar($_POST['field']);,從數據庫或者文件就不需要了。
 *    或者直接使用 Input::magicQuotes來消除所有的magic_quotes_gpc轉義。
 *
 * 存儲過程:
 *    經過Input::getVar($_POST['field'])獲得的數據,就是乾淨的數據,可以直接保存。
 *    如果要過濾危險的html,可以使用 $html = Input::safeHtml($data);
 *
 * 頁面顯示:
 *    純文本顯示在網頁中,如文章標題<title>$data</title>: $data = Input::forShow($field);
 *    HTML 在網頁中顯示,如文章內容:無需處理。
 *    在網頁中以源代碼方式顯示html:$vo = Input::forShow($html);
 *    純文本或者HTML在textarea中進行編輯: $vo = Input::forTarea($value);
 *    html在標籤中使用,如<input value="數據" /> ,使用 $vo = Input::forTag($value); 或者 $vo = Input::hsc($value);
 *
 * 特殊使用情況:
 *    字符串要在數據庫進行搜索: $data = Input::forSearch($field);
 */
class Input {

    private $filter =   null;   // 輸入過濾
    private static $_input  =   array('get','post','request','env','server','cookie','session','globals','config','lang','call');
    //html標籤設置
    public static $htmlTags = array(
        'allow' => 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a',
        'ban' => 'html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml',
    );

    static public function getInstance() {
        return get_instance_of(__CLASS__);
    }

    /**
     +----------------------------------------------------------
     * 魔術方法 有不存在的操作的時候執行
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $type 輸入數據類型
     * @param array $args 參數 array(key,filter,default)
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function __call($type,$args=array()) {
        $type    =   strtolower(trim($type));
        if(in_array($type,self::$_input,true)) {
            switch($type) {
                case 'get':      $input      =& $_GET;break;
                case 'post':     $input      =& $_POST;break;
                case 'request': $input      =& $_REQUEST;break;
                case 'env':      $input      =& $_ENV;break;
                case 'server':   $input      =& $_SERVER;break;
                case 'cookie':   $input      =& $_COOKIE;break;
                case 'session':  $input      =& $_SESSION;break;
                case 'globals':   $input      =& $GLOBALS;break;
                case 'files':      $input      =& $_FILES;break;
                case 'call':       $input      =   'call';break;
                case 'config':    $input      =   C();break;
                case 'lang':      $input      =   L();break;
                default:return NULL;
            }
            if('call' === $input) {
                // 呼叫其他方式的輸入數據
                $callback    =   array_shift($args);
                $params  =   array_shift($args);
                $data    =   call_user_func_array($callback,$params);
                if(count($args)===0) {
                    return $data;
                }
                $filter =   isset($args[0])?$args[0]:$this->filter;
                if(!empty($filter)) {
                    $data    =   call_user_func_array($filter,$data);
                }
            }else{
                if(0==count($args) || empty($args[0]) ) {
                    return $input;
                }elseif(array_key_exists($args[0],$input)) {
                    // 系統變量
                    $data	 =	 $input[$args[0]];
                    $filter	=	isset($args[1])?$args[1]:$this->filter;
                    if(!empty($filter)) {
                        $data	 =	 call_user_func_array($filter,$data);
                    }
                }else{
                    // 不存在指定輸入
                    $data	 =	 isset($args[2])?$args[2]:NULL;
                }
            }
            return $data;
        }
    }

    /**
     +----------------------------------------------------------
     * 設置數據過濾方法
     +----------------------------------------------------------
     * @access private
     +----------------------------------------------------------
     * @param mixed $filter 過濾方法
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public function filter($filter) {
        $this->filter   =   $filter;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 字符MagicQuote轉義過濾
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    static public function noGPC() {
        if ( get_magic_quotes_gpc() ) {
           $_POST      = array_map( 'stripslashes_deep', $_POST );      
			$_GET       = array_map( 'stripslashes_deep', $_GET );      
			$_COOKIE    = array_map( 'stripslashes_deep', $_COOKIE );      
			$_REQUEST   = array_map( 'stripslashes_deep', $_REQUEST );  
		}  
    }

    /**
     +----------------------------------------------------------
     * 處理字符串,以便可以正常進行搜索
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function forSearch($string) {
        return str_replace( array('%','_'), array('\%','\_'), $string );
    }

    /**
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function forShow($string) {
        return self::nl2Br( self::hsc($string) );
    }

    /**
     +----------------------------------------------------------
     * 處理純文本數據,以便在textarea標籤中顯示
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function forTarea($string) {
        return str_ireplace(array('<textarea>','</textarea>'), array('<textarea>','</textarea>'), $string);
    }

    /**
     +----------------------------------------------------------
     * 將數據中的單引號和雙引號進行轉義
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $text 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function forTag($string) {
        return str_replace(array('"',"'"), array('"','''), $string);
    }

    /**
     +----------------------------------------------------------
     * 轉換文字中的超鏈接爲可點擊連接
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function makeLink($string) {
        $validChars = "a-z0-9\/\-_+=.~!%@?#&;:$\|";
        $patterns = array(
                        "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$validChars}]+)/ei",
                        "/(^|[^]_a-z0-9-=\"'\/])www\.([a-z0-9\-]+)\.([{$validChars}]+)/ei",
                        "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$validChars}]+)/ei",
                        "/(^|[^]_a-z0-9-=\"'\/:\.])([a-z0-9\-_\.]+?)@([{$validChars}]+)/ei");
        $replacements = array(
                        "'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.Input::truncate( '\\3' ).'</a>'",
                        "'\\1<a href=\"http://www.\\2.\\3\" title=\"www.\\2.\\3\" rel=\"external\">'.Input::truncate( 'www.\\2.\\3' ).'</a>'",
                        "'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.Input::truncate( 'ftp.\\2.\\3' ).'</a>'",
                        "'\\1<a href=\"mailto:\\2@\\3\" title=\"\\2@\\3\">'.Input::truncate( '\\2@\\3' ).'</a>'");
        return preg_replace($patterns, $replacements, $string);
    }

    /**
     +----------------------------------------------------------
     * 縮略顯示字符串
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     * @param int $length 縮略之後的長度
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function truncate($string, $length = '50') {
        if ( empty($string) || empty($length) || strlen($string) < $length ) return $string;
        $len = floor( $length / 2 );
        $ret = substr($string, 0, $len) . " ... ". substr($string, 5 - $len);
        return $ret;
    }

    /**
     +----------------------------------------------------------
     * 把換行轉換爲<br />標籤
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function nl2Br($string) {
        return preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $string);
    }

    /**
     +----------------------------------------------------------
     * 如果 magic_quotes_gpc 爲關閉狀態,這個函數可以轉義字符串
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function addSlashes($string) {
        if (!get_magic_quotes_gpc()) {
            $string = addslashes($string);
        }
        return $string;
    }

    /**
     +----------------------------------------------------------
     * 從$_POST,$_GET,$_COOKIE,$_REQUEST等數組中獲得數據
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function getVar($string) {
        return Input::stripSlashes($string);
    }

    /**
     +----------------------------------------------------------
     * 如果 magic_quotes_gpc 爲開啓狀態,這個函數可以反轉義字符串
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function stripSlashes($string) {
        if (get_magic_quotes_gpc()) {
            $string = stripslashes($string);
        }
        return $string;
    }

    /**
     +----------------------------------------------------------
     * 用於在textbox表單中顯示html代碼
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static function hsc($string) {
        return preg_replace(array("/&/i", "/ /i"), array('&', '&nbsp;'), htmlspecialchars($string, ENT_QUOTES));
    }

    /**
     +----------------------------------------------------------
     * 是hsc()方法的逆操作
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $text 要處理的字符串
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static function undoHsc($text) {
        return preg_replace(array("/>/i", "/</i", "/"/i", "/'/i", '/&nbsp;/i'), array(">", "<", "\"", "'", " "), $text);
    }

    /**
     +----------------------------------------------------------
     * 輸出安全的html,用於過濾危險代碼
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $text 要處理的字符串
     * @param mixed $allowTags 允許的標籤列表,如 table|td|th|td
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function safeHtml($text, $allowTags = null) {
        $text =  trim($text);
        //完全過濾註釋
        $text = preg_replace('/<!--?.*-->/','',$text);
        //完全過濾動態代碼
        $text =  preg_replace('/<\?|\?'.'>/','',$text);
        //完全過濾js
        $text = preg_replace('/<script?.*\/script>/','',$text);

        $text =  str_replace('[','[',$text);
        $text = str_replace(']',']',$text);
        $text =  str_replace('|','|',$text);
        //過濾換行符
        $text = preg_replace('/\r?\n/','',$text);
        //br
        $text =  preg_replace('/<br(\s\/)?'.'>/i','[br]',$text);
        $text = preg_replace('/(\[br\]\s*){10,}/i','[br]',$text);
        //過濾危險的屬性,如:過濾on事件lang js
        while(preg_match('/(<[^><]+)(lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
            $text=str_replace($mat[0],$mat[1],$text);
        }
        while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
            $text=str_replace($mat[0],$mat[1].$mat[3],$text);
        }
        if( empty($allowTags) ) { $allowTags = self::$htmlTags['allow']; }
        //允許的HTML標籤
        $text =  preg_replace('/<('.$allowTags.')( [^><\[\]]*)>/i','[\1\2]',$text);
        //過濾多餘html
        if ( empty($banTag) ) { $banTag = self::$htmlTags['ban']; }
        $text =  preg_replace('/<\/?('.$banTag.')[^><]*>/i','',$text);
        //過濾合法的html標籤
        while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){
            $text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text);
        }
        //轉換引號
        while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){
            $text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text);
        }
        //空屬性轉換
        $text =  str_replace('\'\'','||',$text);
        $text = str_replace('""','||',$text);
        //過濾錯誤的單個引號
        while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){
            $text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text);
        }
        //轉換其它所有不合法的 < >
        $text =  str_replace('<','<',$text);
        $text = str_replace('>','>',$text);
        $text = str_replace('"','"',$text);
        //反轉換
        $text =  str_replace('[','<',$text);
        $text =  str_replace(']','>',$text);
        $text =  str_replace('|','"',$text);
        //過濾多餘空格
        $text =  str_replace('  ',' ',$text);
        return $text;
    }

    /**
     +----------------------------------------------------------
     * 刪除html標籤,得到純文本。可以處理嵌套的標籤
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的html
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function deleteHtmlTags($string) {
        while(strstr($string, '>')) {
            $currentBeg = strpos($string, '<');
            $currentEnd = strpos($string, '>');
            $tmpStringBeg = @substr($string, 0, $currentBeg);
            $tmpStringEnd = @substr($string, $currentEnd + 1, strlen($string));
            $string = $tmpStringBeg.$tmpStringEnd;
        }
        return $string;
    }

    /**
     +----------------------------------------------------------
     * 處理文本中的換行
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $string 要處理的字符串
     * @param mixed $br 對換行的處理,
     *        false:去除換行;true:保留原樣;string:替換成string
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    static public function nl2($string, $br = '<br />') {
        if ($br == false) {
            $string = preg_replace("/(\015\012)|(\015)|(\012)/", '', $string);
        } elseif ($br != true){
            $string = preg_replace("/(\015\012)|(\015)|(\012)/", $br, $string);
        }
        return $string;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章