Following on from my post on
displaying a zip as a png, I wanted to do a more robust job, to have the zip file properly enclosed as a non-critical png ancillary stream and to
maybe even to have the png included as non-compressed member of the zip archive. ouch!
My main reason for doing this is compatibility reasons as I hear that windows zip-explorer cannot easily open zip files appended to a png.
PNG
Reading the
PNG file standard I find that I should probably use the chunk type:
ziPS making it a ancillary, private and unsafe to copy if the PNG is changed.
As the zip file must be at the end of the PNG it must be the last data stream in the PNG, however ancillary chunks are not allowed to have ordering restrictions, and
IEND should be the last chunk.
Making the chunk unsafe to copy reduces the chances that a png editor could place the chunk in another position, however
14.2 c states
A PNG editor is always allowed to copy all unrecognized ancillary chunks if it has only added, deleted, modified, or reordered ancillary chunks. This implies that it is not permissible for ancillary chunks to depend on other ancillary chunks.
Of course we are not attempting to preserve the zip in any major way if the png is edited, only to stop any zip stream being preserved in a way that prevents it being used.
ZIP
The resource for the zip format was wikipedia
ZIP_(file_format) where I learn the the final part of the zip central directory is a 2 byte comment length and then a comment.
This tells me that the
IEND image trailer
could be the last 4 bytes of the comment... but it would mean that the
ziPS chunk of the png would not include the entire zip file, as the last 4 bytes of the comment would be external to the zip file.
It means that a zip file which was formally extracted from the png would be incomplete and not recognisable.
I can accept this as the
ziPS chunk is not intended to be formally extracted by png-aware software, we only enclose it as a png chunk so that it may be preserved in... er... circumstances where anything after IEND might be removed.
Compatibility
I hear that some zip programs fail to work against zip archives that have been appended to a png. This is an error on the part of such zip programs, which seem to presume that the first item of the zip file is a zip File Entry.
Wikipedia
ZIP_(file_format) states:
Often the first thing in a ZIP file is a ZIP entry, which can be identified easily by its signature. But it is not necessarily the case that a ZIP file begins with a ZIP entry, and is not required by the ZIP specification.
We cannot accommodate such demanding ZIP programs, as the ZIP entry signature is:
ZIP local file header
Offset | Bytes | Description[5] |
0 | 4 | Local file header signature = 0x04034b50 (read as a little-endian number) |
4 | 2 | Version needed to extract (minimum) |
6 | 2 | General purpose bit flag |
...
and the first eight bytes of a PNG datastream always contain the following (decimal) values: 137 80 78 71 13 10 26 10
Method
The method then seems to be:
- Modify the zip file, by adding 13 bytes to the zip comment
- a NULL to sort-of terminate any existing comment to try and hide IEND which we add
- 12 bytes of IEND
- Parse the PNG to find IEND
(Probably the last 12 bytes of the file)
- replace with the crafted zip file
As this won't solve the compatibility problem, I don't feel inclined to write the necessary code unless it becomes important to stop streams after IEND from being removed by png uploaders, if you know what I mean. (An ancillary stream or critical stream in a png is part of the png. A stream after the IEND is not part of the png).