如何在python中膨胀这个zlib字节串?

问题描述 投票:1回答:1

我正在写一个工具来与一个流行的数据仓库SaaS交互。 他们的在线sql编辑器将sql工作表序列化为JSON,但sql工作表的主体是使用pako.js进行zlib放空的。

一个带有sql文本的例子是信。a:

bytestring = b'x\xef\xbf\xbdK\x04\x00\x00b\x00b\n'
zlib.decompress(bytestring[4:-4], -15).decode('utf-8')
>>> "a"

如果我加入分号 a;但这无法解压。

bytestring = b'x\xef\xbf\xbdK\xef\xbf\xbd\x06\x00\x00\xef\xbf\xbd\x00\xef\xbf\xbd\n'
zlib.decompress(bytestring[4:-4], -15).decode('utf-8')
*** UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8f in position 1: invalid start byte

注:我也试过用'punycode'来解压这些例子,我在javascript的实现中找到了参考。

我对zlib的理解非常有限,但我知道zlib字符串的前两个和最后四个字节是headersfooters,如果我们用神奇的数字-15运行zlib,就可以修剪掉。 完全有可能有zlib魔数可以解压这些字符串而不需要剥离头和脚,但我在从-64循环到64的时候,无法让任何组合工作。

我断断续续地查看了在线sql工作表编辑器的保存和加载函数,发现它们使用的是pako zlib库。pako.deflate(a, {to: 'string'})pako.inflate(b['body'], {to: 'string'}) 而且我能够在浏览器中使用 pako 库,但一直无法在python中重现同样的结果。

python zlib unicode-string pako
1个回答
2
投票

每个序列的 \xef\xbf\xbd 代表原始数据损坏的一个实例。

在您的第一个例子中,第一个也是唯一一个 \xef\xbf\xbd 应该是一个单字节,也就是zlib头的第二个字节。在第二个例子中,第一个 \xef\xbf\xbd 应该是zlib头的第二个字节,第二个实例应该是 \b4第三种情况应该是 \ff第四种情况应该是 \9b.

某个地方有一些UTF-8的处理方法,这就是 不该发生. 每次遇到高位设置的字节时,它都会失败。在这些情况下,它就会用三个字节的UTF-8序列来替换该字节。U+FFFD这是用来代表未知字符的 "替换 "字符。

最重要的是,你的数据已经不可挽回地损坏了。你需要修复任何发生在上游的问题。你是否试图使用复制和粘贴来获取数据?如果你看到一个黑色菱形的问号,就是那个UTF-8字符。


2
投票

我同意这是一个数据损坏的问题。 zlib 而且 pako 应该能够读取彼此的数据,而不需要任何剥离字段或添加魔法数字。

为了证明这一点,这里有几个我制作的演示脚本,其中一个使用了 pako 来给数据放气,一个使用 zlib 再次给它充气。

// deflate.js
var pako = require("./pako.js");
console.log(escape(pako.deflate(process.argv[2], {to: "string"})));
# inflate.py
import urllib.parse, zlib, sys
print(zlib.decompress(urllib.parse.unquote_to_bytes(sys.stdin.read())).decode("utf-8"))

在命令行上运行它们,使用 node deflate.js "Here is some example text" | inflate.py. 预期的输出是传递给 node deflate.js.

有一点值得指出的是 pako 的行为,当使用 to: "string" 选项。 该 文件 这个选项的用法如下。

to (String) - 如果等于 "string",那么结果将是 "二进制字符串"(每个字符代码[0...255])

正是因为这个原因,我使用 escape 在上面的JavaScript函数中。 使用 escape 确保JavaScript和Python之间传递的字符串不包含任何非ASCII字符。 (注意 encodeURIComponent 是否 工作,因为字符串包含二进制数据)。) 然后我使用 urllib.parse.unquote_to_bytes 来撤销这个转义。

如果你能 escapepako-浏览器中被放空的数据,你有可能将其传给Python来再次膨胀它。

© www.soinside.com 2019 - 2024. All rights reserved.