public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks) { if (CRCCalculator == null) // should not happen, but who knows... CRCCalculator = callbacks.GetCRCAlgorithm("CRC-32"); return GetDirectory(strm); }
public void UnpackFiles(Stream strm, Callbacks callbacks) { if (CRCCalculator == null) // should not happen, but who knows... CRCCalculator = callbacks.GetCRCAlgorithm("CRC-32"); List<FileEntry> files = GetDirectory(strm); foreach (FileEntry ent in files) { FileHeader fh = ent.ObjectData["FileHeader"] as FileHeader; byte[] buf = new byte[fh.CompressedSize]; strm.Seek(fh.FileDataStartOffset, SeekOrigin.Begin); if (strm.Read(buf, 0, (int)fh.CompressedSize) != fh.CompressedSize) throw new Exception("Read error"); switch (fh.Method) { case 0: // uncompressed data callbacks.WriteData(fh.Filename, buf); break; case 1: case 2: case 3: // decode break; case 4: break; default: throw new Exception("Unknown pack method"); } } }
// fixing PNG headers by guessing is quite simple // - the width and heght fields (2x 4 bytes) are XORed with a "random" key // -> this key is an ascii representation of a hash. // -> Thus it consists of 8 chars in the range of '0'..'9' or 'a'..'f' // - first we assume dimensions < 65536 in each direction (sounds sane) // -> this means we already have 4 of the 8 key bytes (the two high order bytes from each dimension) // - now we walk through all possible key values "00" to "ff" for each of the lower order byte pairs // -> this means 256 (for x dimension) x 256 (for y dimension) tries // -> in each try, we check if the CRC if the IHDR chunk is now correct // -> if it is correct then we found the remaining 2x2 bytes of the key private byte[] FixPngHdr(byte[] hdr, ref string key, ICRCAlgorithm crcAlgo) { byte[] result = new byte[hdr.Length]; ulong target_crc = (ulong)hdr[hdr.Length - 4] << 24 | (ulong)hdr[hdr.Length - 3] << 16 | (ulong)hdr[hdr.Length - 2] << 8 | (ulong)hdr[hdr.Length - 1]; ulong crc; hdr.CopyTo(result, 0); // first, set higher order positions to zero result[4] = result[5] = 0; result[8] = result[9] = 0; for (int key1 = 0; key1 < 256; key1++) { // ascii representation of key1 string k1 = key1.ToString("x2").ToLower(); byte b1 = (byte)(k1[0]); byte b2 = (byte)(k1[1]); result[6] = (byte)(hdr[6] ^ b1); result[7] = (byte)(hdr[7] ^ b2); for (int key2 = 0; key2 < 256; key2++) { string k2 = key2.ToString("x2").ToLower(); byte b3 = (byte)(k2[0]); byte b4 = (byte)(k2[1]); result[10] = (byte)(hdr[10] ^ b3); result[11] = (byte)(hdr[11] ^ b4); crc = crcAlgo.CalculateCRC(result, result.Length - 4); if (crc == target_crc) { key = Encoding.ASCII.GetString(new byte[] { hdr[4], hdr[5], b1, b2, hdr[8], hdr[9], b3, b4 }); return result; } } } key = ""; return null; }
public bool IsSupported(Stream strm, Callbacks callbacks) { if (CRCCalculator == null) CRCCalculator = callbacks.GetCRCAlgorithm("CRC-32"); return GetDirectory(strm) != null; }