PHP 7.4 中包含/流过滤器发生了什么
What happened to include / stream filters in PHP 7.4
去吧! AOP 框架使用带有 include 语句的流过滤器来执行代理生成。它在 PHP 7.3 中运行良好,但现在在 PHP 7.4 beta 2 发布后它看起来有些变化。
不幸的是,流过滤器的文档很差,所以我无法检查发生了什么。也许更有经验的人会知道。
检查以下示例代码:
// index.php
include __DIR__ . '/SampleFilter.php';
SampleFilter::register();
$uri = 'php://filter/read=sample.filter/resource='. __DIR__ . '/Sample.php';
$content = file_get_contents($uri);
include $uri;
Sample::printIt();
// SampleFilter.php
class SampleFilter extends php_user_filter
{
public const PHP_FILTER_READ = 'php://filter/read=';
public const FILTER_IDENTIFIER = 'sample.filter';
protected $data = '';
protected static $filterId;
public static function register(string $filterId = self::FILTER_IDENTIFIER) : void
{
if (!empty(self::$filterId))
{
throw new RuntimeException('Stream filter already registered');
}
$result = stream_filter_register($filterId, __CLASS__);
if ($result === false)
{
throw new Exception('Stream filter was not registered');
}
self::$filterId = $filterId;
}
public static function getId() : string
{
if (empty(self::$filterId))
{
throw new Exception('Stream filter was not registered');
}
return self::$filterId;
}
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in))
{
$this->data .= $bucket->data;
}
if ($closing || feof($this->stream))
{
$consumed = strlen($this->data);
echo '<h2>Before</h2><pre>'. htmlentities($this->data) .'</pre>';
$this->data = str_replace('text', 'text!!!!!!!!', $this->data);
echo '<h2>After</h2><pre>'. htmlentities($this->data) .'</pre>';
$bucket = stream_bucket_new($this->stream, $this->data);
stream_bucket_append($out, $bucket);
return PSFS_PASS_ON;
}
return PSFS_FEED_ME;
}
}
// Sample.php
class Sample
{
public static function printIt()
{
echo 'text';
}
}
如您所见,$content 已正确修改代码(完整)。
但是在包含该文件时,它看起来像代码被条带化为原始文件长度。 PHP 打印错误:Parse error: syntax error, unexpected end of file in /(...)/Sample.php on line 9
第 9 行超过原始文件大小。
这是 bug,在 PHP7.4 中介绍。已在最新版本修复。
去吧! AOP 框架使用带有 include 语句的流过滤器来执行代理生成。它在 PHP 7.3 中运行良好,但现在在 PHP 7.4 beta 2 发布后它看起来有些变化。
不幸的是,流过滤器的文档很差,所以我无法检查发生了什么。也许更有经验的人会知道。
检查以下示例代码:
// index.php
include __DIR__ . '/SampleFilter.php';
SampleFilter::register();
$uri = 'php://filter/read=sample.filter/resource='. __DIR__ . '/Sample.php';
$content = file_get_contents($uri);
include $uri;
Sample::printIt();
// SampleFilter.php
class SampleFilter extends php_user_filter
{
public const PHP_FILTER_READ = 'php://filter/read=';
public const FILTER_IDENTIFIER = 'sample.filter';
protected $data = '';
protected static $filterId;
public static function register(string $filterId = self::FILTER_IDENTIFIER) : void
{
if (!empty(self::$filterId))
{
throw new RuntimeException('Stream filter already registered');
}
$result = stream_filter_register($filterId, __CLASS__);
if ($result === false)
{
throw new Exception('Stream filter was not registered');
}
self::$filterId = $filterId;
}
public static function getId() : string
{
if (empty(self::$filterId))
{
throw new Exception('Stream filter was not registered');
}
return self::$filterId;
}
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in))
{
$this->data .= $bucket->data;
}
if ($closing || feof($this->stream))
{
$consumed = strlen($this->data);
echo '<h2>Before</h2><pre>'. htmlentities($this->data) .'</pre>';
$this->data = str_replace('text', 'text!!!!!!!!', $this->data);
echo '<h2>After</h2><pre>'. htmlentities($this->data) .'</pre>';
$bucket = stream_bucket_new($this->stream, $this->data);
stream_bucket_append($out, $bucket);
return PSFS_PASS_ON;
}
return PSFS_FEED_ME;
}
}
// Sample.php
class Sample
{
public static function printIt()
{
echo 'text';
}
}
如您所见,$content 已正确修改代码(完整)。
但是在包含该文件时,它看起来像代码被条带化为原始文件长度。 PHP 打印错误:Parse error: syntax error, unexpected end of file in /(...)/Sample.php on line 9
第 9 行超过原始文件大小。
这是 bug,在 PHP7.4 中介绍。已在最新版本修复。