Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
加上;魔术语录;禁用,为什么PHP/WordPress继续自动转义我的帖子数据?_Php_Wordpress_Escaping - Fatal编程技术网

加上;魔术语录;禁用,为什么PHP/WordPress继续自动转义我的帖子数据?

加上;魔术语录;禁用,为什么PHP/WordPress继续自动转义我的帖子数据?,php,wordpress,escaping,Php,Wordpress,Escaping,这是一个简单的问题,有一个奇怪的难以捉摸的答案 get\u magic\u quotes\u gpc()报告0。我重复一遍,魔术语录已经关闭了。魔法引号似乎已在php.ini中禁用(不是在运行时) 然而,在PHP中访问时,所有POST数据(包括单引号('))都会转义。这可能是什么原因造成的 在准备测试用例时,我发现了问题的一般根源。我们正在引导WordPress,因为我们的应用程序与WordPress多站点安装集成。当我禁用WordPress引导时,自动转义被禁用。WordPress的自动转义

这是一个简单的问题,有一个奇怪的难以捉摸的答案

get\u magic\u quotes\u gpc()
报告0。我重复一遍,魔术语录已经关闭了。魔法引号似乎已在
php.ini
中禁用(不是在运行时)

然而,在PHP中访问时,所有POST数据(包括单引号('))都会转义。这可能是什么原因造成的



在准备测试用例时,我发现了问题的一般根源。我们正在引导WordPress,因为我们的应用程序与WordPress多站点安装集成。当我禁用WordPress引导时,自动转义被禁用。WordPress的自动转义码在哪里?我想我找到了。问题(bug):

解决方案:


注意:正如@Alexandar O'Mara所建议的,您可能需要重新考虑像这样覆盖超全局。例如,如果适合您的情况,您可以使用类似于
$post=array\u map('stripslashes\u deep',$\u post)的替代方法“局部剥离”


另请参阅@quickshiftin的优秀答案。

对@rinogo的答案进行了更深入的解释,并提供了另一种解决方法


在wp-settings.php中,有一个无条件调用
wp\u magic\u quotes

// Add magic quotes and set up $_REQUEST ( $_GET + $_POST )
wp_magic_quotes();
WordPress无论如何都会转义引号

function wp_magic_quotes() {
    // If already slashed, strip.
    // Escape with wpdb.
    // Force REQUEST to be GET + POST.
}
有趣的是,这个调用是在加载插件之后,在加载主题之前进行的。Sooo,在插件的顶部

//一种处理对wp\u magic\u quotes的不可配置调用的黑客
//例如,通过全球$\u REAL\u POST提供原始$\u POST
$\u REAL\u GET=$\u GET;
$\u REAL\u POST=$\u POST;
$\u REAL\u COOKIE=$\u COOKIE;
$\u REAL\u REQUEST=$\u REQUEST;

然后你可以在需要的地方自由使用
$\u REAL\u POST
等来代替
$\u POST
(记住它是全局的,而不是超全局的)。还请记住,虽然您的插件在主题之前已加载,但如果主题调用使用
$\u POST
的某个插件函数,它应该从
$\u REAL\u POST
中读取,以获取未加载的值。

或者,就像我所做的那样。注释掉load.php的wp_magic_quotes()方法中的所有实现

我不喜欢魔术语录。这让我头疼的事多得不值了。就个人而言,我更喜欢保持自己的卫生纪律。我只是不想开始养成坏的编程习惯


但是,我确实理解WordPress被迫加入这样一个“功能”。也许开发社区最好有一个全局选项来禁用它。

这里提供的最佳答案是复制供自己使用,如:

$post = array_map('stripslashes_deep', $_POST);
然而,这有一个理论上的问题:因为你使用的是一个副本,你不能坚持对超全局的任何更改(嘿,我不是说这是一个好的实践,好吗?)

解决方案:访问器方法 为了以一种明确的方式解决这个问题,并且没有任何副作用,我创建了“访问器方法”,透明地应用
stripslashes\u deep()
addslashes\u deep()*
,以获取/设置对以下超全局数组的请求:

*我不得不从WordPress的
stripslashes\u deep()
中抛出
addslashes\u deep()

  • $\u获取
  • $\u POST
  • $\u COOKIE
  • $\u服务器
  • $\u请求
您可以像这样使用它们:

echo _get('username');    // echo stripslashes_deep($_GET['username']);
_cookie('name', 'value'); // $_COOKIE['name'] = addslashes_deep('value');
下面是代码(我称之为
gpcsr.php
):


我不得不处理这个问题,并找到了我认为非常好的解决方法。它确保GPC永远不会被删除。我只是把它放在插件文件的顶部(我想它也可以放在主题的顶部):


现在一切都很完美

WordPress通过使用WordPress函数提供了解决方案。因此,@rinogo的答案中提到的片段将变成:

$_GET     = stripslashes_deep($_GET);
$_POST    = stripslashes_deep($_POST);
$_COOKIE  = stripslashes_deep($_COOKIE);
$_REQUEST = stripslashes_deep($_REQUEST);
另外需要注意的是,WordPress没有提到任何关于
$\u服务器
全局变量的内容,因此我假设它没有受到影响

WordPress在$\u POST/$\u GET/$\u REQUEST/$\u COOKIE中添加斜杠,而不管GET\u magic\u quotes\u gpc()返回什么。因此,在WordPress的上下文中,在使用这些变量时,应该始终使用stripslashes()或stipslashes_deep()


请向我们展示一个为您生成此行为的简明测试脚本。可能问题就出在测试方法上。您可能想检查浏览器发送的标题。ini_是否收到关闭的报告?谢谢大家的反馈!:)我可以向您保证,在2019年11月的PHP 7.1.33(2019-10-23)和WordPress 5.2.4(2019-10-14)中,这个问题也会发生。。。(魔术语录是。)谢谢你分享关于这种可笑行为的信息。两年后,我们仍然有这个bug。请注意,您不能使用这几次,因此如果您使用它,其他插件使用它,结果将是不可预测的。VilliusL,如果您有干扰其他插件的问题,请记住,您没有义务覆盖原始超全局(
$\u POST
$\u GET
,等等)。您总是可以这样做:
$post\u copy=array\u map('stripslashes\u deep',$\u post)
(请注意,$post\u copy不是超全局的,因此您可以使用
global$post\u copy;
或将$post\u copy作为参数传递。警告:按原样使用此答案中的代码是一个潜在的安全漏洞。请参阅WordPress票证中的此引用。“目前,魔法报价是必要的,因为删除它们很容易让我们面临意外的安全漏洞。即使我们修复了所有核心中的漏洞,也可能会有数百个插件(保守估计)突然受到攻击,因为它们假设数据被删剪,而事实并非如此。”18322于2019-11-22年重新开放(那是将近8年后的事了)有趣的解决办法
<?php

// cat stripslashes_deep() | sed 's/stripslashes/addslashes/g'
function addslashes_deep( $value ) {
    if ( is_array($value) ) {
        $value = array_map('addslashes_deep', $value);
    } elseif ( is_object($value) ) {
        $vars = get_object_vars( $value );
        foreach ($vars as $key=>$data) {
            $value->{$key} = addslashes_deep( $data );
        }
    } elseif ( is_string( $value ) ) {
        $value = addslashes($value);
    }

    return $value;
}

function _generic_slashes_wrap(&$arr, $key, $value = null) {
    if (func_num_args() === 2) return stripslashes_deep($arr[$key]);
    else $arr[$key] = addslashes_deep($value);
}

function _get       ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_GET,      $key); else _generic_slashes_wrap($_GET,        $key, $value); }
function _post      ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_POST,     $key); else _generic_slashes_wrap($_POST,       $key, $value); }
function _cookie    ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_COOKIE,   $key); else _generic_slashes_wrap($_COOKIE,     $key, $value); }
function _server    ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_SERVER,   $key); else _generic_slashes_wrap($_SERVER,     $key, $value); }
function _request   ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_REQUEST,  $key); else _generic_slashes_wrap($_REQUEST,    $key, $value); }

?>
add_action( 'init', 'unslash_gpc' );
function unslash_gpc() {
    $_GET       = array_map('stripslashes_deep', $_GET);
    $_POST      = array_map('stripslashes_deep', $_POST);
    $_COOKIE    = array_map('stripslashes_deep', $_COOKIE);
    $_SERVER    = array_map('stripslashes_deep', $_SERVER);
    $_REQUEST   = array_map('stripslashes_deep', $_REQUEST);
}
$_GET     = stripslashes_deep($_GET);
$_POST    = stripslashes_deep($_POST);
$_COOKIE  = stripslashes_deep($_COOKIE);
$_REQUEST = stripslashes_deep($_REQUEST);