首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > PHP >

[小结+讨论]php 字符串过滤 各类函数应用

2012-09-19 
[总结+讨论]php 字符串过滤 各类函数应用首先自我检讨一下..因为正则不过关,所以自己写的过滤条件基本失败

[总结+讨论]php 字符串过滤 各类函数应用
首先自我检讨一下..因为正则不过关,所以自己写的过滤条件基本失败了...
上网查的函数也看不懂,改了也出错....

在csdn的各路神仙指点下,略微开了点窍...原问题帖链接

现放出各个路子的函数,供各位已经死过还尚未死成的同志使用....
希望大家积极补充,把平时常用的方法帖出来

基础函数
-----------------------------------------------
其实mysql和php自带很多函数可以处理字符问题,下面给出几个会经常用到的.
ps:由于php6开始不支持magic_quotes_gpc,所以下面的东西都是假设在magic_quotes_gpc=off的条件上(不知道php6会出什么新东西....)

mysql_real_escape_string()
定义:函数转义 SQL 语句中使用的字符串中的特殊字符。
语法: mysql_real_escape_string(string,connection)
说明:本函数将 string 中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()。
由于实例代码过长,给出函数解释链接 w3school phpnet

addSlashes()
定义:addslashes() 函数在指定的预定义字符前添加反斜杠。
语法:addslashes(string)
注释:默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
由于实例代码过长,给出函数解释链接 w3school phpnet
相关函数
StripSlashes()去掉反斜线字符。(解释过滤字符时用)

mb_convert_encoding()
PHP的内码转换函数
版本(PHP 4 >= 4.0.6, PHP 5)
这个函数可以将各种编码互相转换
相关链接 phpnet

iconv()
php内码转换函数,同上
因为iconv()在转换gb2312时的bug,所以要这样处理

PHP code
iconv( "UTF-8", "gb2312//IGNORE" , $str)

ignore的意思是忽略转换时的错误,发现iconv在转换字符"—"到gb2312时会出错,如果没有ignore参数,所有该字符后面的字符串都无法被保存。
另外mb_convert_encoding没有这个bug,所以最好的写法是:
PHP code
mb_convert_encoding($str,"gb2312", "UTF-8");

但是需要先enable mbstring 扩展库。
也可以把mysql数据库的collation设成utf-8就不用作转换了
三句mysql真言
SQL code
SET NAMES utf8;SET CHARACTER SET utf8;SET COLLATION_CONNECTION='utf8_general_ci';

相关链接 phpnet
资料参考 link1 link2 link3

自定函数1
-----------------------------------------------
网上找的转换函数,将GB2312进行转换的,修改为utf-8后转换错误,无法解析中文.....期待正则狂人...
PHP code
<?phpfunction escape($str) {         preg_match_all("/[\x80-\xff].|[\x01-\x7f]+/",$str,$r);        $ar = $r[0];        foreach($ar as $k=>$v) {                 if(ord($v[0]) < 128)                            $ar[$k] = rawurlencode($v);                 else                            $ar[$k] = "%u".bin2hex(iconv("GB2312","UCS-2",$v));                                                     }        return join("",$ar);}function unescape($str) {       $str = rawurldecode($str);       preg_match_all("/(?:%u.{4})|.+/",$str,$r);       $ar = $r[0];       foreach($ar as $k=>$v) {                if(substr($v,0,2) == "%u" && strlen($v) == 6)                $ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,-4)));                  }       return join("",$ar);}?>


自定函数2
-----------------------------------------------
感谢论坛gingzai777 ,高手就是不一样,一眼就能看出问题所在.....
以后php过滤用这个行了,不需要顾虑文件编码了.....
PHP code
<?phpfunction addslashes_str($str){$str=addslashes($str);$str=str_replace($str,";",'\;');return $str;}function stripslashes_str($str){$str=stripslashes($str);$str=str_replace($str,'\;',";");return $str;}?>


-------------------------------------------------


ps:如果有什么错误,希望大家指出,另外希望大家把平时用到的一些方法提供一下,互相学习...散分...

我写的原文

[解决办法]
写得很好,支持一下,顶,坐个沙发,呵呵!
[解决办法]
不懂,帮忙顶
[解决办法]
良好的学习习惯,
恭喜.
相信不久将来你也会成为高手的.
[解决办法]

不错,关注,学习中。。。
[解决办法]
不错
[解决办法]
不错,比较了解了

<?php
function addslashes_str($str){
$str=addslashes($str);
$str=str_replace($str,";",'\;');
return $str;
}


?>

$str=str_replace($str,";",'\;');这个有什么用?

[解决办法]

探讨
不错,比较了解了

<?php
function addslashes_str($str){
$str=addslashes($str);
$str=str_replace($str,";",'\;');
return $str;
}


?>

$str=str_replace($str,";",'\;');这个有什么用?


[解决办法]
1)
请使用mysqli或者pdo,不要再使用mysql了。mysql这个已经不怎么维护了。

2)
“SET NAMES utf8;”,这个用法是错误的,在某些编码下存在漏洞。在php5.0.5以后,都应该用mysqli_set_charset(类似的是mysql_set_charset)。
http://cn.php.net/manual/en/mysqli.set-charset.php

至于为什么mysql_query("set names xxx")存在漏洞,说起来就比较复杂了,一句话就是:某些编码里,\会作为字符的一部分,导致串解析异常。mysqli_set_charset的作用是除了client,connection,result之外,还设置了mysql的某个内部结构的charset。

不要再使用set names了,也不要再叫别人去使用它了。

3)
addslash*,无论是自定义,还是官方的,大多数情况下都是多余的东西。

要遵循一个原则,就是过滤在倒数第二步执行。而且大多数操作,对过滤的要求都不一样,例如对于MySQL,因为涉及编码问题,所以addslashes就是不安全的。这就是为什么PHP6会取消magic_quote。

4)
那个escape,根本和正则屁关系都没有。只要知道utf-8的编码规则就行。编码规则如下:
0000-007F | 0xxxxxxx
0080-07FF | 110xxxxx 10xxxxxx
0800-FFFF | 1110xxxx 10xxxxxx 10xxxxxx
10000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


个个都说写得好,却不知道去寻找其中的问题,不去思考。现在网络上大多数错误的编程经验,就是这样出来的。如果我不在这里说,不知道还有多少人被误导。

写这种总结帖是不错,但是如果没有人来挑错,那就会使得其中的错误编程思想被传播开。
[解决办法]
而且对于set names utf8,我很怀疑这里是否有人知道这究竟代表什么。在这种论坛里,我从来没见过有人能正确描述set names的作用,因为这里根本没人知道mysql的编码层次。
[解决办法]
探讨
1)
请使用mysqli或者pdo,不要再使用mysql了。mysql这个已经不怎么维护了。

2)
“SET NAMES utf8;”,这个用法是错误的,在某些编码下存在漏洞。在php5.0.5以后,都应该用mysqli_set_charset(类似的是mysql_set_charset)。
http://cn.php.net/manual/en/mysqli.set-charset.php

至于为什么mysql_query("set names xxx")存在漏洞,说起来就比较复杂了,一句话就是:某些编码里,\会作为字符的一部分,导致串解析异常。m…

[解决办法]
关于“set names utf8”,可能大家还不明白我说什么。我说用mysql_set_charset()来代替mysql_query("SET NAMES UTF8");,不是说不要设置编码。mysql_set_charset()比mysql_query("SET NAMES UTF8")多一个操作。具体是什么我就不说了,上面有一句话我已经提到过了。

如果不相信我,至少也要相信手册,手册里(http://cn2.php.net/mysql_set_charset)写着:
Note: This is the preferred way to change the charset. Using mysql_query() to execute SET NAMES .. is not reccomended. 

翻译过来就是
注意:推荐使用这种方式(指mysql_set_charset())来改变charset。使用mysql_query()来SET NAMES...是不被推荐的。
[解决办法]
探讨
4.疑问....
如果说php6取消了magic_quotes_gpc,而addslashes()根据surfchen说的不安全,那过滤函字符用什么?


php6有什么新花样?
还是mysqli_real_escape_string() ????


[解决办法]
刚才看了一下 php 5.2.8 的 ext/mysql/php_mysql.c,1099 行:
C/C++ code
PHP_FUNCTION(mysql_set_charset){    zval *mysql_link = NULL;    char *csname;    int id = -1, csname_len;    php_mysql_conn *mysql;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &csname, &csname_len, &mysql_link) == FAILURE) {        return;    }    if (ZEND_NUM_ARGS() == 1) {        id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);        CHECK_LINK(id);    }    ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);    if (!mysql_set_character_set(&mysql->conn, csname)) {        RETURN_TRUE;    } else {        RETURN_FALSE;    }}
[解决办法]
刚才看了一下 php 5.2.8 的 ext/mysql/php_mysql.c,1099 行:
C/C++ code
PHP_FUNCTION(mysql_set_charset){    zval *mysql_link = NULL;    char *csname;    int id = -1, csname_len;    php_mysql_conn *mysql;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &csname, &csname_len, &mysql_link) == FAILURE) {        return;    }    if (ZEND_NUM_ARGS() == 1) {        id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);        CHECK_LINK(id);    }    ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);    if (!mysql_set_character_set(&mysql->conn, csname)) {        RETURN_TRUE;    } else {        RETURN_FALSE;    }}
[解决办法]
补充一句:大家不要认为addslashes和mysql有什么关系,addslashes只不过正好可以用在mysql这个场景下而已。当然如我上面所说,实际上addslashes和mysql所要求的过滤还是有一些区别的。
[解决办法]
探讨
这里调用的是 mysql lib 提供的 mysql_set_character_set 函数。关于这个更底层的 mysql lib,可以看这个:http://jabberd2.xiaoka.com/ticket/177,尤其是这个说明:http: //dev.mysql.com/doc/refman/5.0/en/mysql-set-character-set.html

This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()

[解决办法]
探讨
1)
请使用mysqli或者pdo,不要再使用mysql了。mysql这个已经不怎么维护了。

2)
“SET NAMES utf8;”,这个用法是错误的,在某些编码下存在漏洞。在php5.0.5以后,都应该用mysqli_set_charset(类似的是mysql_set_charset)。
http://cn.php.net/manual/en/mysqli.set-charset.php

至于为什么mysql_query("set names xxx")存在漏洞,说起来就比较复杂了,一句话就是:某些编码里,\会作为字符的一部分,导致串解析异常。mys…

[解决办法]
探讨
个个都说写得好,却不知道去寻找其中的问题,不去思考。现在网络上大多数错误的编程经验,就是这样出来的。如果我不在这里说,不知道还有多少人被误导。

写这种总结帖是不错,但是如果没有人来挑错,那就会使得其中的错误编程思想被传播开。

[解决办法]
探讨
引用:
很少看到这么治学严谨的兄弟了.
汗颜!


感觉这样子,学习的氛围才会好,要不然小白是挖不出内核的...

热点排行