我正在尝试解析我通过 POST 收到的 git 包
https://github.com/codecrafters-io/git-sample-3/git-upload-pack
数据是
0032want 23f0bc3b5c7c3108e41c448f01a3db31e7064bbb\n00000009done
并将返回的字符串存储在std::string pack
中。为了解析字符串,我执行了以下操作
pack = pack.substr(20, pack.length() - 40); // skip 8 byte http header, 12 byte pack header, 20 byte pack trailer
int type;
int pos = 0;
std::string lengthstr;
int length = 0;
type = (pack[pos] & 112) >> 4; // 112 is 11100000 so this gets the first 3 bits
length = length | (pack[pos] & 0x0F); // take the last 4 bits
if (pack[pos] & 0x80) { // if the type bit starts with 0 then the last 4 bits are simply the length
pos++;
while (pack[pos] & 0x80) { // while leftmost bit is 1
length = length << 7;
length = length | (pack[pos] & 0x7F); // flip first bit to 0 si it's ignored, then we append the other 7 bits to the integer
pos++;
}
length = length << 7;
length = length | pack[pos]; // set the leftmost bit to 1 so it's ignored, and do the same thing
}
pos++;
FILE* customStdout = fdopen(1, "w");
FILE* source = fmemopen((void*)pack.substr(pos, length).c_str(), length, "r");
std::cout << inf(source, customStdout) << "\n";
inf 来自 zpipe.c。 inf 调用结果为
Z_DATA_ERROR
,消息为 incorrect header check
我实际上以二进制形式打印了这些位,从 pos 开始的位是我对 zlib 标头的期望(
78 9C
),所以我不确定为什么我在这里得到不正确的标头。
我还尝试使用
inflateInit2(&strm, -MAX_WBITS)
并向 pos 添加 2 来完全跳过标题,但它返回相同的错误并显示消息 invalid stored block lengths
用以下代码替换
inf
调用
int ret;
unsigned have;
z_stream strm;
unsigned char in[16384];
unsigned char out[16384];
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
strm.avail_in = pack.length() - pos;
for (int i = 0; i < 16384; i++) {
in[i] = pack[pos + i];
}
strm.next_in = in;
strm.avail_out = 16384;
strm.next_out = out;
inflate(&strm, Z_NO_FLUSH);
允许 inflate 调用成功。我观察到的唯一区别是我将 pack 中的字符直接复制到流缓冲区中。我怀疑这个问题与我创建文件的方式有关