编程

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

1692 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 弃用通知。在 PHP 9.0 中,将不再支持这些编码。

mb_detect_encodingmb_convert_encoding 更改

自 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 内核的 htmlentitieshtml_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 中会被移除。