编程

PHP 8.2: Mbstring: Base64、Uuencode、QPrint 和 HTML Entity 编码弃用

1059 2022-12-07 03:35:29

PHP 多字节字符串扩展(mbstring) 添加功能,用来操作包含多字节的字符比如中文、Emojis 和其他不能用单字节表示的文字。

该扩展支持将其他几种字符集比如 UTF-8/16/32 和 ISO-8859-1 之间的转换。Mbstring 也支持一些编码如 Base64, QuotedPrintable, Uuencode 和 HTML Entities。这4种编码与其他文本编码不匹配,他们不处理构成Unicode码点的字节序列,而是处理原始字节。

此外,PHP核心已经提供了编码/解码Base64、Quoted Printable、Uuencode和HTML实体的函数作为单独的专用函数。

在PHP 8.2中,不推荐使用Mbstring扩展将字符串编码/解码为Base64、Quoted Printable、Uuencode和HTML实体。

以下标记的编码会受到影响。编码标签不区分大小写。

  • BASE64
  • UUENCODE
  • HTML-ENTITIES
  • html (alias of HTML-ENTITIES)
  • Quoted-Printable
  • qprint (alias of Quoted-Printable)

使用Mbstring扩展对所述字符编码进行编码/解码将发出PHP弃用通知。在PHP9.0中,将不再支持这些编码。

mb_detect_encoding和mb_convert_encodiing更改

自PHP 8.2及更高版本以来,mb_detect_encoding函数不再检测上面列出的编码。此外,mb_convert_encoding函数不会尝试将文本编码检测为不推荐的编码之一。

在此更改之前,mb_detect_encoding函数将大致返回编码,如UUENCODE,即便文本未编码。

更换弃用的功能

PHP 已经提供了内建函数支持 Base64、Quoted-Printable、Uuencode 和 HTML Entities编码及解码。

使用内建专用函数替换Mbstring提供的转换函数,可以避免弃用通知,同时可以在无需Mbstring扩展的情况下,在PHP内核中使用该功能。

Base64 编码/解码

尝试使用 Mbstring 函数将 Base64 编码转换成字符串,会导致弃用通知:

mb_convert_encoding('test', 'base64'));
Deprecated: mb_convert_encoding(): Handling Base64 via mbstring is deprecated; use base64_encode/base64_decode instead in ... on line ...

要避免弃用通知,使用 base64_encode() 和 base64_decode() 替换 Base64 的编码/解码函数:

- $base64Encoded = mb_convert_encoding('test', 'Base64'));
+ $base64Encoded = base64_encode('test'));
- $str = mb_convert_encoding($base64Encoded, 'UTF-8', 'Base64'));
+ $str = base64_decode($base64Encoded));

HTML Entities 编码/解码

Mbstring 扩展提供了名为HTML-Entities的编码,可用于将字符串编码/解码为HTML entities。该功能类似于 PHP 内核的 htmlentities 和 html_entity_decode 函数。

$str = '¢ <script>';
$entities = mb_convert_encoding($str, 'HTML-Entities', 'UTF-8');
// "&cent; <script>"
Deprecated: mb_convert_encoding(): Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead in ... on line ...

Mbstring 提供的 HTML 实体转换可以用 htmlentities 函数替换,用以编码所有 HTML 实体。

  $str = '¢ <script>';
- $entities = mb_convert_encoding($str, 'HTML-Entities', 'UTF-8');
- // "&cent; <script>"
+ $entities = htmlentities($str);
+ // "&cent; &lt;script&gt;"

请注意 Mbstring 中的 HTML-Entities 编码不会编码 '"<>& 字符。这些字符是由 htmlspecialchars 专门编码的。可以逐字复制Mbstring的HTML实体编码功能,来解码htmlentities()编码的字符,但HTML-Entities没有('“<>&)。不解码这些特殊字符并将其显示给浏览器可能会导致跨站点脚本漏洞。

此外,在将非UTF-8字符传递给htmlentities函数之前,可能需要将其转换为UTF-8。

  $fromEncoding = 'ISO-8859-1';
- $encodedStr = mb_convert_encoding($str, 'HTML-Entities', $fromEncoding);
+ $encodedStr = mb_convert_encoding($str, 'UTF-8', $fromEncoding);
+ $encodedStr = htmlentities($encodedStr);

虽然不建议使用,但如果不能对“”<>&进行编码,则可以使用htmlspecialchars_code调用实现此行为:

  $fromEncoding = 'ISO-8859-1';
- $encodedStr = mb_convert_encoding($str, 'HTML-Entities', $fromEncoding);
+ $encodedStr = mb_convert_encoding($str, 'UTF-8', $fromEncoding);
+ $encodedStr = htmlentities($encodedStr);
+ $encodedStr = htmlspecialchars_decode($encodedStr);

Uuencode/decode

Mbstring的UUENCODE执行uuencoding,会导致自PHP 8.2及更高版本以来的弃用通知。

mb_convert_encoding('test', 'UUENCODE');
Deprecated: mb_convert_encoding(): Handling Uuencode via mbstring is deprecated; use convert_uuencode/convert_uudecode instead in ... on line ...

Mbstring提供的Uuencode/decode功能,可以用PHP内核的内置的convert_Uuencode()和convert_uudecode函数替换。

- $encoded = mb_convert_encoding('test', 'UUENCODE');
+ $encoded = convert_uuencode('test');
- $encoded = mb_convert_encoding('test', 'UTF-8', 'UUENCODE');
+ $encoded = # convert_uudecode('test');

现在可能是时候重新评估一下是否该使用uuencode。比如说,Base64是将二进制数据编码成字符串的一种更稳健的替代方案。

Quoted-Printable 编码/解码

类似于其他弃用的编码,使用 Quoted-Printable 编码也会在 PHP 8.2 中导致弃用通知。  

$encoded = mb_convert_encoding('a=b', 'Quoted-Printable');
Deprecated: mb_convert_encoding(): Handling QPrint via mbstring is deprecated; use quoted_printable_encode/quoted_printable_decode instead in ... on line ...

PHP 内核已经支持 Quoted-Printable 字符的编码/解码,使用 PHP 内核的 quoted_printable_encode() 和 quoted_printable_decode() 替换 Mbstring 中对应的功能,可以避免弃用通知。

-$encoded = mb_convert_encoding('a=b', 'Quoted-Printable');
+$encoded = quoted_printable_encode('a=b');
-$decoded = mb_convert_encoding('a=b', 'UTF-8', 'Quoted-Printable');
+$decoded = quoted_printable_decode('a=3Db');

向下兼容性影响

在 PHP 8.2 中,使用 Mbstring 扩展编码/解码 HTML Entities、Base64、Uuencode 和 Quoted Printable 字符串,会带来弃用通知。

弃用通知每个请求最多只会发出一次,以减少某些场景(比如循环中调用函数)带来的噪音。

请注意,弃用通知不限于 mb_convert_encoding。在字符编码弃用的任何地方都可能会碰到弃用通知。比如:

mb_strlen('test', 'BASE64');

所有这些弃用编码在 PHP 9.0 中会被移除。