public void Write(Stream inputStream, bool encrypt = false, bool seek = true)
{
_header.ArchiveFlags = encrypt ? 4U : 0U;
_header.TOCEntrySize = 30U;
WriteManifest();
//Pack entries
List<uint> zLengths;
Dictionary<Entry, byte[]> zStreams;
DeflateEntries(out zStreams, out zLengths);
//Build zLengths
_writer = new BigEndianBinaryWriter(inputStream);
_header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum);
_toc[0].Offset = _header.TotalTOCSize;
for (int i = 1; i < _toc.Count; i++)
{
_toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length);
}
//Write Header
_writer.Write(_header.MagicNumber);
_writer.Write(_header.VersionNumber);
_writer.Write(_header.CompressionMethod);
_writer.Write(_header.TotalTOCSize);
_writer.Write(_header.TOCEntrySize);
_writer.Write(_toc.Count);
_writer.Write(_header.BlockSizeAlloc);
_writer.Write(_header.ArchiveFlags);
//Write Table of contents
foreach (Entry current in _toc)
{
current.UpdateNameMD5();
_writer.Write(current.MD5);
_writer.Write(current.zIndexBegin);
_writer.WriteUInt40((ulong)current.Data.Length); //current.Length
_writer.WriteUInt40(current.Offset);
}
foreach (uint zLen in zLengths)
{
switch (bNum)
{
case 2:
_writer.Write((ushort)zLen);
break;
case 3:
_writer.WriteUInt24(zLen);
break;
case 4:
_writer.Write(zLen);
break;
}
}
zLengths = null;
// Write zData
var ndx = 0; // for debugging
var step = Math.Round(1.0 / (this.TOC.Count + 2) * 100, 3);
double progress = 0;
// GlobalExtension.ShowProgress("Writing Zipped Data ...");
foreach (Entry current in _toc)
{
_writer.Write(zStreams[current]);
progress += step;
// GlobalExtension.UpdateProgress.Value = (int)progress;
Debug.WriteLine("Zipped: " + ndx++);
current.Data.Close();
}
zStreams = null;
if (encrypt) // Encrypt TOC
{
using (var outputStream = new MemoryStreamExtension())
{
var encStream = new MemoryStreamExtension();
inputStream.Position = 32L;
RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize);
inputStream.Position = 0L;
// quick copy header from input stream
var buffer = new byte[32];
encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length));
encStream.Position = 32; //sainty check ofc
inputStream.Flush();
int tocSize = (int)_header.TotalTOCSize - 32;
int decSize = 0;
buffer = new byte[1024 * 16]; // more effecient use of memory
ndx = 0; // for debuging
step = Math.Round(1.0 / ((tocSize / buffer.Length) + 2) * 100, 3);
progress = 0;
// GlobalExtension.ShowProgress("Writing Encrypted Data ...");
int bytesRead;
while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
{
decSize += bytesRead;
if (decSize > tocSize)
bytesRead = tocSize - (decSize - bytesRead);
encStream.Write(buffer, 0, bytesRead);
progress += step;
// GlobalExtension.UpdateProgress.Value = (int)progress;
Debug.WriteLine("Encrypted: " + ndx++);
}
inputStream.Position = 0;
encStream.Position = 0;
encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc);
}
}
if (seek) // May be redundant
{
inputStream.Flush();
inputStream.Position = 0;
}
// GlobalExtension.HideProgress();
}