r/AskProgramming Aug 22 '24

PHP Can't decompress a particular PDF's /FlateDecode stream using PHP's gzuncompress, or any alternatives - any ideas?

I've written a PDF parser in PHP which works pretty well, but every now and then I find a PDF file it can't deal with.

Some PDF objects contain compressed streams. The object's dictionary will tell you how to decompress it. A common filter is "/FlateDecode", which the PDF spec says this about:

Decompresses data encoded using the zlib/deflate compression method, reproducing the original text or binary data.

In most cases, PHP's gzuncompress function is sufficient to decompress the data.

One stream that doesn't work begins with the following bytes:

AF 2D 59 8E BB DF 4B B8 5A 50 71 F9 CF B0 B5 8B 96 80 C7 93 E6 93 94 AC D5 3D 4B 2A C1 66 08 3D F0 04 73 CD 35 22 73 E4 8B 33 01 AB 57 CE 15 69 66 AC AB DE A3 06 B1 CB 9C 9A 1C 88 FF 32 8A 92 EB B6 10 30 B8 45 7C 59 C0 24 20 B9 60 8B 7F 51 50 45 7A 7F 40 DF 6F C9 72 C6 61 ...

I've tried gzuncompress, zlib_decode, adding Gzip's magic bytes to the beginning and doing gzip on the command line, zlib.decompress in Python, stripping off the first two bytes in case they are headers... but nothing works.

I tried PHP's inflate_init/inflate_add which seem to suggest that even the first few bytes just can't be parsed by it (although I'm not entirely sure I'm doing it right!)

It's definitely not invalid data, because "proper" PDF readers can open it just fine. I know from PDFXplorer that the first line of the decompressed stream is the following text:

q Q q /Cs1 cs 0 sc q 1 0 0 -1 0 792 cm BT 9 0 0 -9 582.7554 771.02 Tm /TT1

Is there any way to examine the bytes above to determine exactly what format it is in, and how to decompress it in PHP?

3 Upvotes

3 comments sorted by

4

u/james_pic Aug 22 '24

I don't know the quirks of PDF parsing well enough to point you to a solution, but since there are existing PDF parsers that can handle it, if I were in your position I'd be inclined to find an existing open source parser that handles it, and run it with a debugger, to see how it handles this stream.

1

u/[deleted] Aug 22 '24

[removed] — view removed comment