Files
2026-06-04 11:42:34 +02:00

672 lines
17 KiB
C#

using System;
using System.Collections;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
namespace ICSharpCode.SharpZipLib.Zip
{
// Token: 0x02000080 RID: 128
public class ZipOutputStream : DeflaterOutputStream
{
// Token: 0x060004ED RID: 1261 RVA: 0x000181C8 File Offset: 0x000171C8
public ZipOutputStream(Stream baseOutputStream)
: base(baseOutputStream, new Deflater(-1, true))
{
}
// Token: 0x060004EE RID: 1262 RVA: 0x0001822C File Offset: 0x0001722C
public ZipOutputStream(Stream baseOutputStream, int bufferSize)
: base(baseOutputStream, new Deflater(-1, true), bufferSize)
{
}
// Token: 0x17000121 RID: 289
// (get) Token: 0x060004EF RID: 1263 RVA: 0x0001828F File Offset: 0x0001728F
public bool IsFinished
{
get
{
return this.entries == null;
}
}
// Token: 0x060004F0 RID: 1264 RVA: 0x0001829C File Offset: 0x0001729C
public void SetComment(string comment)
{
byte[] array = ZipConstants.ConvertToArray(comment);
if (array.Length > 65535)
{
throw new ArgumentOutOfRangeException("comment");
}
this.zipComment = array;
}
// Token: 0x060004F1 RID: 1265 RVA: 0x000182CC File Offset: 0x000172CC
public void SetLevel(int level)
{
this.deflater_.SetLevel(level);
this.defaultCompressionLevel = level;
}
// Token: 0x060004F2 RID: 1266 RVA: 0x000182E1 File Offset: 0x000172E1
public int GetLevel()
{
return this.deflater_.GetLevel();
}
// Token: 0x17000122 RID: 290
// (get) Token: 0x060004F3 RID: 1267 RVA: 0x000182EE File Offset: 0x000172EE
// (set) Token: 0x060004F4 RID: 1268 RVA: 0x000182F6 File Offset: 0x000172F6
public UseZip64 UseZip64
{
get
{
return this.useZip64_;
}
set
{
this.useZip64_ = value;
}
}
// Token: 0x060004F5 RID: 1269 RVA: 0x000182FF File Offset: 0x000172FF
private void WriteLeShort(int value)
{
this.baseOutputStream_.WriteByte((byte)(value & 255));
this.baseOutputStream_.WriteByte((byte)((value >> 8) & 255));
}
// Token: 0x060004F6 RID: 1270 RVA: 0x00018329 File Offset: 0x00017329
private void WriteLeInt(int value)
{
this.WriteLeShort(value);
this.WriteLeShort(value >> 16);
}
// Token: 0x060004F7 RID: 1271 RVA: 0x0001833C File Offset: 0x0001733C
private void WriteLeLong(long value)
{
this.WriteLeInt((int)value);
this.WriteLeInt((int)(value >> 32));
}
// Token: 0x060004F8 RID: 1272 RVA: 0x00018354 File Offset: 0x00017354
public void PutNextEntry(ZipEntry entry)
{
if (entry == null)
{
throw new ArgumentNullException("entry");
}
if (this.entries == null)
{
throw new InvalidOperationException("ZipOutputStream was finished");
}
if (this.curEntry != null)
{
this.CloseEntry();
}
if (this.entries.Count == 2147483647)
{
throw new ZipException("Too many entries for Zip file");
}
CompressionMethod compressionMethod = entry.CompressionMethod;
int num = this.defaultCompressionLevel;
entry.Flags &= 2048;
this.patchEntryHeader = false;
bool flag;
if (entry.Size == 0L)
{
entry.CompressedSize = entry.Size;
entry.Crc = 0L;
compressionMethod = CompressionMethod.Stored;
flag = true;
}
else
{
flag = entry.Size >= 0L && entry.HasCrc;
if (compressionMethod == CompressionMethod.Stored)
{
if (!flag)
{
if (!base.CanPatchEntries)
{
compressionMethod = CompressionMethod.Deflated;
num = 0;
}
}
else
{
entry.CompressedSize = entry.Size;
flag = entry.HasCrc;
}
}
}
if (!flag)
{
if (!base.CanPatchEntries)
{
entry.Flags |= 8;
}
else
{
this.patchEntryHeader = true;
}
}
if (base.Password != null)
{
entry.IsCrypted = true;
if (entry.Crc < 0L)
{
entry.Flags |= 8;
}
}
entry.Offset = this.offset;
entry.CompressionMethod = compressionMethod;
this.curMethod = compressionMethod;
this.sizePatchPos = -1L;
if (this.useZip64_ == UseZip64.On || (entry.Size < 0L && this.useZip64_ == UseZip64.Dynamic))
{
entry.ForceZip64();
}
this.WriteLeInt(67324752);
this.WriteLeShort(entry.Version);
this.WriteLeShort(entry.Flags);
this.WriteLeShort((int)((byte)entry.CompressionMethodForHeader));
this.WriteLeInt((int)entry.DosTime);
if (flag)
{
this.WriteLeInt((int)entry.Crc);
if (entry.LocalHeaderRequiresZip64)
{
this.WriteLeInt(-1);
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt(entry.IsCrypted ? ((int)entry.CompressedSize + 12) : ((int)entry.CompressedSize));
this.WriteLeInt((int)entry.Size);
}
}
else
{
if (this.patchEntryHeader)
{
this.crcPatchPos = this.baseOutputStream_.Position;
}
this.WriteLeInt(0);
if (this.patchEntryHeader)
{
this.sizePatchPos = this.baseOutputStream_.Position;
}
if (entry.LocalHeaderRequiresZip64 || this.patchEntryHeader)
{
this.WriteLeInt(-1);
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt(0);
this.WriteLeInt(0);
}
}
byte[] array = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
if (array.Length > 65535)
{
throw new ZipException("Entry name too long.");
}
ZipExtraData zipExtraData = new ZipExtraData(entry.ExtraData);
if (entry.LocalHeaderRequiresZip64)
{
zipExtraData.StartNewEntry();
if (flag)
{
zipExtraData.AddLeLong(entry.Size);
zipExtraData.AddLeLong(entry.CompressedSize);
}
else
{
zipExtraData.AddLeLong(-1L);
zipExtraData.AddLeLong(-1L);
}
zipExtraData.AddNewEntry(1);
if (!zipExtraData.Find(1))
{
throw new ZipException("Internal error cant find extra data");
}
if (this.patchEntryHeader)
{
this.sizePatchPos = (long)zipExtraData.CurrentReadIndex;
}
}
else
{
zipExtraData.Delete(1);
}
if (entry.AESKeySize > 0)
{
ZipOutputStream.AddExtraDataAES(entry, zipExtraData);
}
byte[] entryData = zipExtraData.GetEntryData();
this.WriteLeShort(array.Length);
this.WriteLeShort(entryData.Length);
if (array.Length > 0)
{
this.baseOutputStream_.Write(array, 0, array.Length);
}
if (entry.LocalHeaderRequiresZip64 && this.patchEntryHeader)
{
this.sizePatchPos += this.baseOutputStream_.Position;
}
if (entryData.Length > 0)
{
this.baseOutputStream_.Write(entryData, 0, entryData.Length);
}
this.offset += (long)(30 + array.Length + entryData.Length);
if (entry.AESKeySize > 0)
{
this.offset += (long)entry.AESOverheadSize;
}
this.curEntry = entry;
this.crc.Reset();
if (compressionMethod == CompressionMethod.Deflated)
{
this.deflater_.Reset();
this.deflater_.SetLevel(num);
}
this.size = 0L;
if (entry.IsCrypted)
{
if (entry.AESKeySize > 0)
{
this.WriteAESHeader(entry);
return;
}
if (entry.Crc < 0L)
{
this.WriteEncryptionHeader(entry.DosTime << 16);
return;
}
this.WriteEncryptionHeader(entry.Crc);
}
}
// Token: 0x060004F9 RID: 1273 RVA: 0x000187A0 File Offset: 0x000177A0
public void CloseEntry()
{
if (this.curEntry == null)
{
throw new InvalidOperationException("No open entry");
}
long totalOut = this.size;
if (this.curMethod == CompressionMethod.Deflated)
{
if (this.size >= 0L)
{
base.Finish();
totalOut = this.deflater_.TotalOut;
}
else
{
this.deflater_.Reset();
}
}
if (this.curEntry.AESKeySize > 0)
{
this.baseOutputStream_.Write(this.AESAuthCode, 0, 10);
}
if (this.curEntry.Size < 0L)
{
this.curEntry.Size = this.size;
}
else if (this.curEntry.Size != this.size)
{
throw new ZipException(string.Concat(new object[]
{
"size was ",
this.size,
", but I expected ",
this.curEntry.Size
}));
}
if (this.curEntry.CompressedSize < 0L)
{
this.curEntry.CompressedSize = totalOut;
}
else if (this.curEntry.CompressedSize != totalOut)
{
throw new ZipException(string.Concat(new object[]
{
"compressed size was ",
totalOut,
", but I expected ",
this.curEntry.CompressedSize
}));
}
if (this.curEntry.Crc < 0L)
{
this.curEntry.Crc = this.crc.Value;
}
else if (this.curEntry.Crc != this.crc.Value)
{
throw new ZipException(string.Concat(new object[]
{
"crc was ",
this.crc.Value,
", but I expected ",
this.curEntry.Crc
}));
}
this.offset += totalOut;
if (this.curEntry.IsCrypted)
{
if (this.curEntry.AESKeySize > 0)
{
this.curEntry.CompressedSize += (long)this.curEntry.AESOverheadSize;
}
else
{
this.curEntry.CompressedSize += 12L;
}
}
if (this.patchEntryHeader)
{
this.patchEntryHeader = false;
long position = this.baseOutputStream_.Position;
this.baseOutputStream_.Seek(this.crcPatchPos, SeekOrigin.Begin);
this.WriteLeInt((int)this.curEntry.Crc);
if (this.curEntry.LocalHeaderRequiresZip64)
{
if (this.sizePatchPos == -1L)
{
throw new ZipException("Entry requires zip64 but this has been turned off");
}
this.baseOutputStream_.Seek(this.sizePatchPos, SeekOrigin.Begin);
this.WriteLeLong(this.curEntry.Size);
this.WriteLeLong(this.curEntry.CompressedSize);
}
else
{
this.WriteLeInt((int)this.curEntry.CompressedSize);
this.WriteLeInt((int)this.curEntry.Size);
}
this.baseOutputStream_.Seek(position, SeekOrigin.Begin);
}
if ((this.curEntry.Flags & 8) != 0)
{
this.WriteLeInt(134695760);
this.WriteLeInt((int)this.curEntry.Crc);
if (this.curEntry.LocalHeaderRequiresZip64)
{
this.WriteLeLong(this.curEntry.CompressedSize);
this.WriteLeLong(this.curEntry.Size);
this.offset += 24L;
}
else
{
this.WriteLeInt((int)this.curEntry.CompressedSize);
this.WriteLeInt((int)this.curEntry.Size);
this.offset += 16L;
}
}
this.entries.Add(this.curEntry);
this.curEntry = null;
}
// Token: 0x060004FA RID: 1274 RVA: 0x00018B78 File Offset: 0x00017B78
private void WriteEncryptionHeader(long crcValue)
{
this.offset += 12L;
base.InitializePassword(base.Password);
byte[] array = new byte[12];
Random random = new Random();
random.NextBytes(array);
array[11] = (byte)(crcValue >> 24);
base.EncryptBlock(array, 0, array.Length);
this.baseOutputStream_.Write(array, 0, array.Length);
}
// Token: 0x060004FB RID: 1275 RVA: 0x00018BDA File Offset: 0x00017BDA
private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData)
{
extraData.StartNewEntry();
extraData.AddLeShort(2);
extraData.AddLeShort(17729);
extraData.AddData(entry.AESEncryptionStrength);
extraData.AddLeShort((int)entry.CompressionMethod);
extraData.AddNewEntry(39169);
}
// Token: 0x060004FC RID: 1276 RVA: 0x00018C18 File Offset: 0x00017C18
private void WriteAESHeader(ZipEntry entry)
{
byte[] array;
byte[] array2;
base.InitializeAESPassword(entry, base.Password, out array, out array2);
this.baseOutputStream_.Write(array, 0, array.Length);
this.baseOutputStream_.Write(array2, 0, array2.Length);
}
// Token: 0x060004FD RID: 1277 RVA: 0x00018C58 File Offset: 0x00017C58
public override void Write(byte[] buffer, int offset, int count)
{
if (this.curEntry == null)
{
throw new InvalidOperationException("No open entry.");
}
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException("offset", "Cannot be negative");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", "Cannot be negative");
}
if (buffer.Length - offset < count)
{
throw new ArgumentException("Invalid offset/count combination");
}
this.crc.Update(buffer, offset, count);
this.size += (long)count;
CompressionMethod compressionMethod = this.curMethod;
if (compressionMethod != CompressionMethod.Stored)
{
if (compressionMethod != CompressionMethod.Deflated)
{
return;
}
base.Write(buffer, offset, count);
return;
}
else
{
if (base.Password != null)
{
this.CopyAndEncrypt(buffer, offset, count);
return;
}
this.baseOutputStream_.Write(buffer, offset, count);
return;
}
}
// Token: 0x060004FE RID: 1278 RVA: 0x00018D18 File Offset: 0x00017D18
private void CopyAndEncrypt(byte[] buffer, int offset, int count)
{
byte[] array = new byte[4096];
while (count > 0)
{
int num = ((count < 4096) ? count : 4096);
Array.Copy(buffer, offset, array, 0, num);
base.EncryptBlock(array, 0, num);
this.baseOutputStream_.Write(array, 0, num);
count -= num;
offset += num;
}
}
// Token: 0x060004FF RID: 1279 RVA: 0x00018D74 File Offset: 0x00017D74
public override void Finish()
{
if (this.entries == null)
{
return;
}
if (this.curEntry != null)
{
this.CloseEntry();
}
long num = (long)this.entries.Count;
long num2 = 0L;
foreach (object obj in this.entries)
{
ZipEntry zipEntry = (ZipEntry)obj;
this.WriteLeInt(33639248);
this.WriteLeShort(51);
this.WriteLeShort(zipEntry.Version);
this.WriteLeShort(zipEntry.Flags);
this.WriteLeShort((int)((short)zipEntry.CompressionMethodForHeader));
this.WriteLeInt((int)zipEntry.DosTime);
this.WriteLeInt((int)zipEntry.Crc);
if (zipEntry.IsZip64Forced() || zipEntry.CompressedSize >= (long)((ulong)(-1)))
{
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt((int)zipEntry.CompressedSize);
}
if (zipEntry.IsZip64Forced() || zipEntry.Size >= (long)((ulong)(-1)))
{
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt((int)zipEntry.Size);
}
byte[] array = ZipConstants.ConvertToArray(zipEntry.Flags, zipEntry.Name);
if (array.Length > 65535)
{
throw new ZipException("Name too long.");
}
ZipExtraData zipExtraData = new ZipExtraData(zipEntry.ExtraData);
if (zipEntry.CentralHeaderRequiresZip64)
{
zipExtraData.StartNewEntry();
if (zipEntry.IsZip64Forced() || zipEntry.Size >= (long)((ulong)(-1)))
{
zipExtraData.AddLeLong(zipEntry.Size);
}
if (zipEntry.IsZip64Forced() || zipEntry.CompressedSize >= (long)((ulong)(-1)))
{
zipExtraData.AddLeLong(zipEntry.CompressedSize);
}
if (zipEntry.Offset >= (long)((ulong)(-1)))
{
zipExtraData.AddLeLong(zipEntry.Offset);
}
zipExtraData.AddNewEntry(1);
}
else
{
zipExtraData.Delete(1);
}
if (zipEntry.AESKeySize > 0)
{
ZipOutputStream.AddExtraDataAES(zipEntry, zipExtraData);
}
byte[] entryData = zipExtraData.GetEntryData();
byte[] array2 = ((zipEntry.Comment != null) ? ZipConstants.ConvertToArray(zipEntry.Flags, zipEntry.Comment) : new byte[0]);
if (array2.Length > 65535)
{
throw new ZipException("Comment too long.");
}
this.WriteLeShort(array.Length);
this.WriteLeShort(entryData.Length);
this.WriteLeShort(array2.Length);
this.WriteLeShort(0);
this.WriteLeShort(0);
if (zipEntry.ExternalFileAttributes != -1)
{
this.WriteLeInt(zipEntry.ExternalFileAttributes);
}
else if (zipEntry.IsDirectory)
{
this.WriteLeInt(16);
}
else
{
this.WriteLeInt(0);
}
if (zipEntry.Offset >= (long)((ulong)(-1)))
{
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt((int)zipEntry.Offset);
}
if (array.Length > 0)
{
this.baseOutputStream_.Write(array, 0, array.Length);
}
if (entryData.Length > 0)
{
this.baseOutputStream_.Write(entryData, 0, entryData.Length);
}
if (array2.Length > 0)
{
this.baseOutputStream_.Write(array2, 0, array2.Length);
}
num2 += (long)(46 + array.Length + entryData.Length + array2.Length);
}
using (ZipHelperStream zipHelperStream = new ZipHelperStream(this.baseOutputStream_))
{
zipHelperStream.WriteEndOfCentralDirectory(num, num2, this.offset, this.zipComment);
}
this.entries = null;
}
// Token: 0x04000320 RID: 800
private ArrayList entries = new ArrayList();
// Token: 0x04000321 RID: 801
private Crc32 crc = new Crc32();
// Token: 0x04000322 RID: 802
private ZipEntry curEntry;
// Token: 0x04000323 RID: 803
private int defaultCompressionLevel = -1;
// Token: 0x04000324 RID: 804
private CompressionMethod curMethod = CompressionMethod.Deflated;
// Token: 0x04000325 RID: 805
private long size;
// Token: 0x04000326 RID: 806
private long offset;
// Token: 0x04000327 RID: 807
private byte[] zipComment = new byte[0];
// Token: 0x04000328 RID: 808
private bool patchEntryHeader;
// Token: 0x04000329 RID: 809
private long crcPatchPos = -1L;
// Token: 0x0400032A RID: 810
private long sizePatchPos = -1L;
// Token: 0x0400032B RID: 811
private UseZip64 useZip64_ = UseZip64.Dynamic;
}
}