请注意,当 magic_quotes_gpc 设置为开启时,不仅 $_POST、$_GET、$_REQUEST、$_COOKIE 数组的值会添加斜杠。实际上,$GLOBALS 数组中的每个字符串值都会添加斜杠,例如 $GLOBALS['_SERVER']['PATH_INFO'](或 $_SERVER['PATH_INFO'])。
(PHP 4, PHP 5, PHP 7)
get_magic_quotes_gpc — 获取 magic_quotes_gpc 的当前配置设置
此函数从 PHP 7.4.0 开始已被 *弃用*,从 PHP 8.0.0 开始已被 *移除*。强烈建议不要依赖此函数。
此函数没有参数。
始终返回 false
。
版本 | 描述 |
---|---|
7.4.0 | 此函数已弃用。 |
请注意,当 magic_quotes_gpc 设置为开启时,不仅 $_POST、$_GET、$_REQUEST、$_COOKIE 数组的值会添加斜杠。实际上,$GLOBALS 数组中的每个字符串值都会添加斜杠,例如 $GLOBALS['_SERVER']['PATH_INFO'](或 $_SERVER['PATH_INFO'])。
这是我用来从请求数据中删除魔术引号的方法。
如果 magic_quotes_sybase 打开,则将两个单引号替换为一个单引号,否则只去除斜杠。
请注意,`foreach` 样式仅适用于 PHP 5 及更高版本。
<?php
// 从请求数据中去除魔术引号。
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
// 创建 Lambda 风格的去除转义函数(用于可移植性)
$quotes_sybase = strtolower(ini_get('magic_quotes_sybase'));
$unescape_function = (empty($quotes_sybase) || $quotes_sybase === 'off') ? 'stripslashes($value)' : 'str_replace("\'\'","\'",$value)';
$stripslashes_deep = create_function('&$value, $fn', '
if (is_string($value)) {
$value = ' . $unescape_function . ';
} else if (is_array($value)) {
foreach ($value as &$v) $fn($v, $fn);
}
');
// 去除数据转义
$stripslashes_deep($_POST, $stripslashes_deep);
$stripslashes_deep($_GET, $stripslashes_deep);
$stripslashes_deep($_COOKIE, $stripslashes_deep);
$stripslashes_deep($_REQUEST, $stripslashes_deep);
}
?>
Re: php at kaiundina dot de (03-Feb-2005 02:18)
1. magic_quotes_gpc=on/off 和 magic_quotes_sybase=on/off
我进行了测试,您的函数运行正常。
以下是我使用的 <input ... /> 名称
name="a"
name="b.b b\b"
name="c[c.1]"
name="c[c 2]"
name="c[c\3]"
name="c.c c[c.' 4]"
name="c ' c[c"4]"
name="d"[d"1]"
(我使用 " 因为我不知道其他方法来将 " 放入名称中)
以及用户输入的值
a ' " \ \' \" \\ a
2. > 17) 字符 "."、" " 在用作键时始终会被替换为 "_"。
这仅适用于顶级键,如上面的 "b.b b\b"、"c.c c" 和 "c ' c"。二级键 "[c.' 4]" 没有更改为 [c_'_4],而是根据 magic_quites_XXX 的设置进行了转义。
在 PHP 4.4.0 上测试。
这些魔术引号真的是黑魔法 :(
最好对 $_SESSION 进行测试,但我今天做不到。
GPC 数组中键字符串的转义行为与它们的值的转义行为不同。
首先我以为提交的 GPC 数组中的键永远不会被转义。
无论如何。在我看到转义的键后,我假设它们是根据魔术引号的设置进行转义的。
... 甚至更糟...
我花了超过 2 天的时间测试,才弄清楚确切的行为,并创建了两个函数(分别针对每个 PHP 版本),可以可靠地从提交给脚本的任何数组中去除斜杠。希望这能节省一些人的时间和神经。
以下内容适用于 $_GET 和 $_POST 数组。我希望受魔术引号影响的其他数组的行为也一样。
我没有测试 magic_quotes_sybase 设置时的行为。
== 可能的案例组合的图例 ==
Px = 我们使用的 PHP 版本
P4 = PHP 4.3.9
P5 = PHP 5.0.2
MQ = MagicQuotes GPC
+MQ = 魔术引号开启
-MQ = 魔术引号关闭
TL = 顶级键
+TL = 键位于顶级(例如 $_GET['myKey'])
-TL = 键嵌套在另一个数组中(例如 $_GET['myList']['myKey'])
AK = 数组键
+AK = 键的值是另一个数组(例如 is_array($_GET['myKey']) == true)
-AK = 值是普通的字符串(例如 is_string($_GET['myKey']) == true)
== 可能结果的图例 ==
KE = 键转义
+KE = 控制字符前缀为反斜杠
-KE = 键按提交方式返回,不需要去除转义
VE = 值转义(不适用于数组作为值)
+VE = 控制字符前缀为反斜杠
-VE = 值按提交方式返回,不需要去除转义
== 以下规则适用 ==
1) P4 +MQ +AK +TL --> -KE
2) P4 +MQ +AK -TL --> +KE
3) P4 +MQ -AK +TL --> -KE +VE
4) P4 +MQ -AK -TL --> +KE +VE
5) P4 -MQ +AK +TL --> -KE
6) P4 -MQ +AK -TL --> -KE
7) P4 -MQ -AK +TL --> -KE -VE
8) P4 -MQ -AK -TL --> -KE -VE
9) P5 +MQ +AK +TL --> -KE
10) P5 +MQ +AK -TL --> +KE
11) P5 +MQ -AK +TL --> +KE +VE
12) P5 +MQ -AK -TL --> +KE +VE
13) P5 -MQ +AK +TL --> -KE
14) P5 -MQ +AK -TL --> -KE
15) P5 -MQ -AK +TL --> +KE -VE
16) P5 -MQ -AK -TL --> +KE -VE
17) 字符 "."、" " 在用作键时始终会被替换为 "_"。
示例(规则 15)
在 PHP 5.0.2 下运行,魔术引号关闭时,顶级包含字符串的 GPC 键会被转义,而它们的值不会被转义。
== 以下函数将去除 PHP 4.3.9 的 GPC 数组 ==
<?php
function transcribe($aList, $aIsTopLevel = true) {
$gpcList = array();
$isMagic = get_magic_quotes_gpc();
foreach ($aList as $key => $value) {
$decodedKey = ($isMagic && !$aIsTopLevel)?stripslashes($key):$key;
if (is_array($value)) {
$decodedValue = transcribe($value, false);
} else {
$decodedValue = ($isMagic)?stripslashes($value):$value;
}
$gpcList[$decodedKey] = $decodedValue;
}
return $gpcList;
}
?>
== 以下函数将去除 PHP 5.0.2 中的 GPC 数组 ==
<?php
function transcribe($aList, $aIsTopLevel = true) {
$gpcList = array();
$isMagic = get_magic_quotes_gpc();
foreach ($aList as $key => $value) {
if (is_array($value)) {
$decodedKey = ($isMagic && !$aIsTopLevel)?stripslashes($key):$key;
$decodedValue = transcribe($value, false);
} else {
$decodedKey = stripslashes($key);
$decodedValue = ($isMagic)?stripslashes($value):$value;
}
$gpcList[$decodedKey] = $decodedValue;
}
return $gpcList;
}
?>
用法
<?php
$unstrippedGET = transcribe($_GET);
$unstrippedPOST = transcribe($_POST);
?>
也许有人愿意测试其他 PHP 版本以及 magic_quotes_sybase 设置为“on”时的组合——请告诉我。
对于大量的文本表示歉意,但它是完整的。我无法将决策表压缩得更小。
<?php
function stripper($stringvar){
if (1 == get_magic_quotes_gpc()){
$stringvar = stripslashes($stringvar);
}
return $stringvar;
}
?>
用法
<?php
$Body = stripper($rs->fields('Body'));
echo($Body);
?>
这检查 get_magic_quotes_gpc() 是否开启,并在开启时去除字符串变量以供输出。如果开发服务器和生产服务器设置不同,这很有用。
@ dot dot dot dot dot alexander at gmail dot com
我建议用“stripslashes_deep”替换 foreach
示例 #2 对数组使用 stripslashes()
<https://php.net/manual/en/function.stripslashes.php>:
<?php
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
?>
这将得到
<?php
if((function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) || (ini_get('magic_quotes_sybase') && (strtolower(ini_get('magic_quotes_sybase'))!="off")) ){
stripslashes_deep($_GET);
stripslashes_deep($_POST);
stripslashes_deep($_COOKIE);
}
?>
当你处理表单和数据库时,你应该使用这个概念
1. 当将用户输入插入数据库时,使用 add_slashes() 或类似方法对 $_POST/$_GET 进行转义(以匹配特定的数据库转义规则)
$query='INSERT INTO users SET fullname="'.add_slashes($_POST['fullname']).'"';
insert_into_db($query);
2. 当从数据库读取先前提交的输入时,使用 html_special_chars 来显示转义后的结果!
read_db_row('SELECT fullname FROM users');
echo '<input type="text" name="fullname" value="'.html_special_chars($db_row['fullname']).'" />
这样你就可以安全地存储和使用原始(未转义)数据。
只是一个小小的修正
( 由于 ini_get 函数可能返回一个字符串值“off”,其计算结果为 TRUE )
<?php
if(
( function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc() )
|| ( ini_get('magic_quotes_sybase') && ( strtolower(ini_get('magic_quotes_sybase')) != "off" ) )
){
foreach($_GET as $k => $v) $_GET[$k] = stripslashes($v);
foreach($_POST as $k => $v) $_POST[$k] = stripslashes($v);
foreach($_COOKIE as $k => $v) $_COOKIE[$k] = stripslashes($v);
}
?>
> “如果指令 magic_quotes_sybase 为 ON,它将完全覆盖 magic_quotes_gpc。”
这个“注释”有点误导。magic_quotes_sybase 只有在 magic_quotes_gpc 已经启用时才会覆盖对 Get/Post/Cookie 数据使用的转义方法。如果 magic_quotes_gpc 未启用,则 magic_quotes_sybase 在此处将不起作用。
因此,其他一些注释在确定何时从输入中“去除反斜杠”方面是错误的,因为当 magic_quotes_gpc 或 magic_quotes_sybase 启用时,它们会“去除反斜杠”。你应该只在 magic_quotes_gpc 启用时使用 stripslashes(),因为只有在这种情况下才会自动添加反斜杠。
stripslashes() 也是 magic_quotes_sybase 意识的,因此你不需要在 magic_quotes_sybase 启用时执行任何特殊操作(例如,编写自定义函数来处理这种情况,如另一个注释所建议的)。当 magic_quotes_sybase 启用时,stripslashes() 实际上不会去除任何反斜杠,而是只使用单引号转义的单引号进行反转义。
但是,magic_quotes_sybase 确实会影响 addslashes() 和 stripslashes() 分别使用的转义(和反转义)方法,无论 magic_quotes_gpc(或 magic_quotes_runtime)是否启用。
关于以下三个主要的去除方法(两个使用 foreach,一个使用 json 方法),我使用“真实”分析(使用注册的 tickhandler,其中 declare(ticks=1))进行了一些基准测试。
我想知道 json 是否会非常慢。
我不会讨论分析器,但会用以下陈述和用于基准测试的代码来代替。
json 方法是迄今为止最快的(与我想象的不同),所以如果你需要快速处理,就使用它!
<?php
declare(ticks=1);
function g()
{
return array(
'a'=>'i\\\\\\'m',
array('a1' => 'x', 'b1' => 'x'),
array( 'a2' => array('a3' => '\\\\\\'x', 'b3' => 'random' )
)
);
}
function strip_json($d)
{
$rs = json_decode(stripslashes(json_encode($d, JSON_HEX_APOS)), true);
return $rs;
}
function strip_deep1($d)
{
foreach ($d as $k=>$v)
{
if (is_array($v)) { $d[$k] = strip_deep1($v); }
else { $d[$k] = stripslashes($v); }
}
return $d;
}
function strip_deep2(&$d)
{
$d = is_array($d) ? array_map('strip_deep2', $d) : stripslashes($d);
return $d;
}
// now profile it
require_once './TickProfiler.php';
$N = 1000;
$d = g();
TickProfiler::Register();
for ($i = 0; $i < $N; $i++){ strip_json($d); }
for ($i = 0; $i < $N; $i++){ strip_deep1($d); }
for ($i = 0; $i < $N; $i++){ strip_deep2($d); }
TickProfiler::Unregister();
TickProfiler::Display();
?>
我的输出(PHP 5.3.1,win32)
[TickProfiler::tick] => 数组
(
[time] => 0.76188707351685
[calls] => 46001
)
[TickProfiler::Register] => 数组
(
[time] => 3.0994415283203E-5
[calls] => 1
)
[strip_json] => 数组
(
[time] => 0.025638580322266
[calls] => 1000
)
[strip_deep1] => 数组
(
[time] => 0.40303444862366
[calls] => 36000
)
[strip_deep2] => 数组
(
[time] => 0.14928555488586
[calls] => 9000
)
)
如上所示,使用 json 使输出速度至少提高了 5 倍(接近 6 倍)。
只是想分享一下 :D
请注意,strip_json 函数有两行代码,而不是简单的 return 语句,否则它将不会被 tickprofiler 捕获(它将立即从代码中返回,永远不会到达 profiler)!
strip_deep2 中的 return 语句的使用是不必要的,因为参数是通过引用传递的。
一个新的测试表明,这样做的时间损失大约是 0.09 秒。
实际上,这意味着 strip_deep2 与 strip_json 之间的时间比率只有大约 2。
尽管如此,strip_json 的速度仍然是 strip_deep2 的两倍左右