s9e / bencode
快速高效的bencode解码器/编码器,旨在优雅地处理格式错误和恶意输入。
2.3.2
2024-04-09 19:49 UTC
Requires
- php: >=8.1
Requires (Dev)
- nikic/php-fuzzer: *
- phpunit/phpunit: ^10.0
- s9e/repdoc: dev-wip
README
s9e\Bencode是一个简洁高效的Bencode编码器/解码器。它旨在优雅地处理格式错误和恶意输入。
安装
composer require s9e/bencode
用法
解码bencoded字符串
use s9e\Bencode\Bencode; print_r(Bencode::decode('d3:bar4:spam3:fooi42ee'));
ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[bar] => spam
[foo] => 42
)
)
编码PHP值
use s9e\Bencode\Bencode; print_r(Bencode::encode(['foo' => 42, 'bar' => 'spam']));
d3:bar4:spam3:fooi42ee
支持以下类型
array
、int
和string
值会被原生编码。float
值在无损转换到整数时会强制转换为int
。bool
值会强制转换为int
。- 实现了
s9e\Bencode\BencodeSerializable
的对象会以它的bencodeSerialize()
方法返回的值进行编码。 stdClass
对象的属性以字典形式编码。ArrayObject
的实例被视为数组。
use s9e\Bencode\Bencode; use s9e\Bencode\BencodeSerializable; $bencodable = new class implements BencodeSerializable { public function bencodeSerialize(): array|int|string { return 42; } }; print_r(Bencode::encode($bencodable));
i42e
处理异常
try { s9e\Bencode\Bencode::decode('i123x'); } catch (s9e\Bencode\Exceptions\DecodingException $e) { var_dump($e->getMessage(), $e->getOffset()); }
string(29) "Illegal character at offset 4"
int(4)
try { s9e\Bencode\Bencode::encode(2.5); } catch (s9e\Bencode\Exceptions\EncodingException $e) { var_dump($e->getMessage(), $e->getValue()); }
string(17) "Unsupported value"
float(2.5)
恢复不符合规范的数据
默认情况下,解码器会通过抛出ComplianceError
异常来拒绝不符合规范的数据,该异常是DecodingException
的子类型。如果您必须处理由不符合规范编码器生成的输入,则decodeNonCompliant
方法可能能够通过以下方式恢复它
- 无序字典会自动排序。
- 字典中的重复条目会覆盖先前的条目。
- 用作字典键的整数会被转换为字符串。
- 整数前的
0
会被移除。 - 负零会被转换为
0
。 - 输入末尾的垃圾数据会被忽略。
在以下示例中,我们尝试正常加载一个无效字典,并在失败时,使用非规范解码器重试。
use s9e\Bencode\Bencode; $input = 'd3:fooi42e3:bar4:spame'; try { $value = Bencode::decode($input); } catch (s9e\Bencode\Exceptions\ComplianceError $e) { echo 'Failed: ', $e->getMessage(), "\nRetry with non-compliant decoder:\n"; $value = Bencode::decodeNonCompliant($input); print_r($value); }
Failed: Out of order dictionary entry 'bar' at offset 10
Retry with non-compliant decoder:
ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[bar] => spam
[foo] => 42
)
)
实现细节
- 拒绝无效的bencoded数据,并抛出有意义的异常信息。
- 使用ArrayObject实例来表示字典。可以使用数组表示法或对象表示法创建和读取字典。
- 整数范围限制在
PHP_INT_MIN
到PHP_INT_MAX
之间。 - 编码器接受布尔值,但将它们转换为整数。
- 编码器接受等于其整数值的浮点数。