private void OnInvalidFile(MPKFile file) { if (InvalidFile != null) { InvalidFile(file, new EventArgs()); } }
/// <summary> /// Adds a file to the MPK /// </summary> /// <param name="file">The file to add</param> /// <returns>true if successfull, false if the file is already contained</returns> public bool AddFile(MPKFile file) { if (!_files.ContainsKey(file.Header.Name)) { _files.Add(file.Header.Name, file); return(true); } return(false); }
/// <summary> /// Reads a MPK from a binary reader /// </summary> /// <param name="rdr">The binary reader pointing to the MPK</param> private void ReadArchive(BinaryReader rdr) { _files.Clear(); _crc.Value = 0; _sizeDir = 0; _sizeName = 0; _numFiles = 0; var buf = new byte[16]; rdr.Read(buf, 0, 16); for (byte i = 0; i < 16; ++i) { buf[i] ^= i; } _crc.Value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; _sizeDir = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; _sizeName = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; _numFiles = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15]; buf = new byte[_sizeName]; rdr.Read(buf, 0, _sizeName); var inf = new Inflater(); inf.SetInput(buf); buf = new byte[1024]; inf.Inflate(buf); buf[inf.TotalOut] = 0; _name = Marshal.ConvertToString(buf); long totalin = 0; buf = ReadDirectory(rdr, ref totalin); using (var directory = new MemoryStream(buf)) { long pos = rdr.BaseStream.Position; long len = rdr.BaseStream.Seek(0, SeekOrigin.End); rdr.BaseStream.Position = pos; buf = new byte[len - pos]; rdr.Read(buf, 0, buf.Length); using (var files = new MemoryStream(buf)) { rdr.BaseStream.Position = pos - totalin; buf = new byte[totalin]; rdr.Read(buf, 0, buf.Length); var crc = new Crc32(); crc.Reset(); crc.Update(buf); if (crc.Value != _crc.Value) { throw new Exception("Invalid or corrupt MPK"); } while (directory.Position < directory.Length && files.Position < files.Length) { crc.Reset(); buf = new byte[MPKFileHeader.MaxSize]; directory.Read(buf, 0, MPKFileHeader.MaxSize); MPKFileHeader hdr; using (var hdrStream = new MemoryStream(buf)) { using (var hdrRdr = new BinaryReader(hdrStream, Encoding.UTF8)) { hdr = new MPKFileHeader(hdrRdr); } } var compbuf = new byte[hdr.CompressedSize]; files.Read(compbuf, 0, compbuf.Length); crc.Update(compbuf, 0, compbuf.Length); inf.Reset(); inf.SetInput(compbuf, 0, compbuf.Length); buf = new byte[hdr.UncompressedSize]; inf.Inflate(buf, 0, buf.Length); var file = new MPKFile(compbuf, buf, hdr); if (crc.Value != hdr.CRC.Value) { OnInvalidFile(file); continue; } _files.Add(hdr.Name.ToLower(), file); } } } }
/// <summary> /// Writes the MPK to a specific filename /// </summary> /// <param name="fname"></param> public void Write(string fname) { Deflater def; byte[] buf, dir, name; var files = new MPKFile[_files.Count]; using (var dirmem = new MemoryStream(_files.Count * MPKFileHeader.MaxSize)) { int index = 0; uint offset = 0; uint diroffset = 0; foreach (MPKFile file in _files.Values) { file.Header.DirectoryOffset = diroffset; file.Header.Offset = offset; files[index] = file; using (var wrtr = new BinaryWriter(dirmem, Encoding.UTF8)) { file.Header.Write(wrtr); } offset += file.Header.UncompressedSize; diroffset += file.Header.CompressedSize; index++; } def = new Deflater(); def.SetInput(dirmem.GetBuffer(), 0, (int)dirmem.Position); def.Finish(); dir = new byte[dirmem.Position]; def.Deflate(dir); _sizeDir = (int)def.TotalOut; } def = new Deflater(); _crc.Reset(); _crc.Update(dir, 0, _sizeDir); def.SetInput(Encoding.UTF8.GetBytes(_name)); def.Finish(); name = new byte[_name.Length]; def.Deflate(name); _numFiles = _files.Count; _sizeName = (int)def.TotalOut; using (var filemem = new MemoryStream()) { using (var wrtr = new BinaryWriter(filemem, Encoding.UTF8)) { wrtr.Write((int)_crc.Value); wrtr.Write(_sizeDir); wrtr.Write(_sizeName); wrtr.Write(_numFiles); buf = new byte[16]; Buffer.BlockCopy(filemem.GetBuffer(), 0, buf, 0, 16); for (byte i = 0; i < 16; i++) { buf[i] ^= i; } } } using (FileStream fileStream = File.Open(fname, FileMode.Create, FileAccess.Write)) { using (var wrtr = new BinaryWriter(fileStream, Encoding.UTF8)) { wrtr.Write(Magic); wrtr.Write((byte)2); wrtr.Write(buf, 0, 16); wrtr.Write(name, 0, _sizeName); wrtr.Write(dir, 0, _sizeDir); foreach (MPKFile file in files) { wrtr.Write(file.CompressedData); } } } }
/// <summary> /// Removes a file from the MPK /// </summary> /// <param name="file">The file to remove</param> /// <returns>true if the file was successfully removed, false if it wasn't in the MPK</returns> public bool RemoveFile(MPKFile file) { return(RemoveFile(file.Header.Name)); }
/// <summary> /// Reads a MPK from a binary reader /// </summary> /// <param name="rdr">The binary reader pointing to the MPK</param> private void ReadArchive(BinaryReader rdr) { _files.Clear(); _crc.Value = 0; _sizeDir = 0; _sizeName = 0; _numFiles = 0; var buf = new byte[16]; rdr.Read(buf, 0, 16); for (byte i = 0; i < 16; ++i) { buf[i] ^= i; } _crc.Value = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); _sizeDir = ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]); _sizeName = ((buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]); _numFiles = ((buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15]); buf = new byte[_sizeName]; rdr.Read(buf, 0, _sizeName); var inf = new Inflater(); inf.SetInput(buf); buf = new byte[1024]; inf.Inflate(buf); buf[inf.TotalOut] = 0; _name = Marshal.ConvertToString(buf); long totalin = 0; buf = ReadDirectory(rdr, ref totalin); using (var directory = new MemoryStream(buf)) { long pos = rdr.BaseStream.Position; long len = rdr.BaseStream.Seek(0, SeekOrigin.End); rdr.BaseStream.Position = pos; buf = new byte[len - pos]; rdr.Read(buf, 0, buf.Length); using (var files = new MemoryStream(buf)) { rdr.BaseStream.Position = pos - totalin; buf = new byte[totalin]; rdr.Read(buf, 0, buf.Length); var crc = new Crc32(); crc.Reset(); crc.Update(buf); if (crc.Value != _crc.Value) { throw new Exception("Invalid or corrupt MPK"); } while (directory.Position < directory.Length && files.Position < files.Length) { crc.Reset(); buf = new byte[MPKFileHeader.MaxSize]; directory.Read(buf, 0, MPKFileHeader.MaxSize); MPKFileHeader hdr; using (var hdrStream = new MemoryStream(buf)) { using (var hdrRdr = new BinaryReader(hdrStream, Encoding.UTF8)) { hdr = new MPKFileHeader(hdrRdr); } } var compbuf = new byte[hdr.CompressedSize]; files.Read(compbuf, 0, compbuf.Length); crc.Update(compbuf, 0, compbuf.Length); inf.Reset(); inf.SetInput(compbuf, 0, compbuf.Length); buf = new byte[hdr.UncompressedSize]; inf.Inflate(buf, 0, buf.Length); var file = new MPKFile(compbuf, buf, hdr); if (crc.Value != hdr.CRC.Value) { OnInvalidFile(file); continue; } _files.Add(hdr.Name.ToLower(), file); } } } }
/// <summary> /// Writes the MPK to a specific filename /// </summary> /// <param name="fname"></param> public void Write(string fname) { Deflater def; byte[] buf, dir, name; var files = new MPKFile[_files.Count]; using (var dirmem = new MemoryStream(_files.Count*MPKFileHeader.MaxSize)) { int index = 0; uint offset = 0; uint diroffset = 0; foreach (MPKFile file in _files.Values) { file.Header.DirectoryOffset = diroffset; file.Header.Offset = offset; files[index] = file; using (var wrtr = new BinaryWriter(dirmem, Encoding.UTF8)) { file.Header.Write(wrtr); } offset += file.Header.UncompressedSize; diroffset += file.Header.CompressedSize; index++; } def = new Deflater(); def.SetInput(dirmem.GetBuffer(), 0, (int) dirmem.Position); def.Finish(); dir = new byte[dirmem.Position]; def.Deflate(dir); _sizeDir = (int) def.TotalOut; } def = new Deflater(); _crc.Reset(); _crc.Update(dir, 0, _sizeDir); def.SetInput(Encoding.UTF8.GetBytes(_name)); def.Finish(); name = new byte[_name.Length]; def.Deflate(name); _numFiles = _files.Count; _sizeName = (int) def.TotalOut; using (var filemem = new MemoryStream()) { using (var wrtr = new BinaryWriter(filemem, Encoding.UTF8)) { wrtr.Write((int) _crc.Value); wrtr.Write(_sizeDir); wrtr.Write(_sizeName); wrtr.Write(_numFiles); buf = new byte[16]; Buffer.BlockCopy(filemem.GetBuffer(), 0, buf, 0, 16); for (byte i = 0; i < 16; i++) { buf[i] ^= i; } } } using (FileStream fileStream = File.Open(fname, FileMode.Create, FileAccess.Write)) { using (var wrtr = new BinaryWriter(fileStream, Encoding.UTF8)) { wrtr.Write(Magic); wrtr.Write((byte) 2); wrtr.Write(buf, 0, 16); wrtr.Write(name, 0, _sizeName); wrtr.Write(dir, 0, _sizeDir); foreach (MPKFile file in files) { wrtr.Write(file.CompressedData); } } } }
/// <summary> /// Removes a file from the MPK /// </summary> /// <param name="file">The file to remove</param> /// <returns>true if the file was successfully removed, false if it wasn't in the MPK</returns> public bool RemoveFile(MPKFile file) { return RemoveFile(file.Header.Name); }
/// <summary> /// Adds a file to the MPK /// </summary> /// <param name="file">The file to add</param> /// <returns>true if successfull, false if the file is already contained</returns> public bool AddFile(MPKFile file) { if (!_files.ContainsKey(file.Header.Name)) { _files.Add(file.Header.Name, file); return true; } return false; }